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 #ifndef VTYSH_EXTRACT_PL
50 #include "zebra/zebra_vty_clippy.c"
52 #include "zebra/zserv.h"
53 #include "zebra/router-id.h"
54 #include "zebra/ipforward.h"
55 #include "zebra/zebra_vxlan_private.h"
56 #include "zebra/zebra_pbr.h"
57 #include "zebra/zebra_nhg.h"
58 #include "zebra/zebra_evpn_mh.h"
59 #include "zebra/interface.h"
60 #include "northbound_cli.h"
61 #include "zebra/zebra_nb.h"
62 #include "zebra/kernel_netlink.h"
63 #include "zebra/if_netlink.h"
64 #include "zebra/table_manager.h"
65 #include "zebra/zebra_script.h"
66 #include "zebra/rtadv.h"
67 #include "zebra/zebra_neigh.h"
69 /* context to manage dumps in multiple tables or vrfs */
70 struct route_show_ctx
{
71 bool multi
; /* dump multiple tables or vrf */
72 bool header_done
; /* common header already displayed */
75 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
76 safi_t safi
, bool use_fib
, bool use_json
,
78 const struct prefix
*longer_prefix_p
,
79 bool supernets_only
, int type
,
80 unsigned short ospf_instance_id
, uint32_t tableid
,
81 bool show_ng
, struct route_show_ctx
*ctx
);
82 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
83 int mcast
, bool use_fib
, bool show_ng
);
84 static void vty_show_ip_route_summary(struct vty
*vty
,
85 struct route_table
*table
, bool use_json
);
86 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
87 struct route_table
*table
,
89 /* Helper api to format a nexthop in the 'detailed' output path. */
90 static void show_nexthop_detail_helper(struct vty
*vty
,
91 const struct route_entry
*re
,
92 const struct nexthop
*nexthop
,
95 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
96 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
97 struct route_entry
*re
, unsigned int num
);
99 DEFUN (ip_multicast_mode
,
100 ip_multicast_mode_cmd
,
101 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
103 "Multicast options\n"
104 "RPF lookup behavior\n"
105 "Lookup in unicast RIB only\n"
106 "Lookup in multicast RIB only\n"
107 "Try multicast RIB first, fall back to unicast RIB\n"
108 "Lookup both, use entry with lower distance\n"
109 "Lookup both, use entry with longer prefix\n")
111 char *mode
= argv
[3]->text
;
113 if (strmatch(mode
, "urib-only"))
114 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
115 else if (strmatch(mode
, "mrib-only"))
116 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
117 else if (strmatch(mode
, "mrib-then-urib"))
118 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
119 else if (strmatch(mode
, "lower-distance"))
120 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
121 else if (strmatch(mode
, "longer-prefix"))
122 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
124 vty_out(vty
, "Invalid mode specified\n");
125 return CMD_WARNING_CONFIG_FAILED
;
131 DEFUN (no_ip_multicast_mode
,
132 no_ip_multicast_mode_cmd
,
133 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
136 "Multicast options\n"
137 "RPF lookup behavior\n"
138 "Lookup in unicast RIB only\n"
139 "Lookup in multicast RIB only\n"
140 "Try multicast RIB first, fall back to unicast RIB\n"
141 "Lookup both, use entry with lower distance\n"
142 "Lookup both, use entry with longer prefix\n")
144 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
151 "show ip rpf [json]",
154 "Display RPF information for multicast source\n"
157 bool uj
= use_json(argc
, argv
);
158 struct route_show_ctx ctx
= {
162 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
163 false, uj
, 0, NULL
, false, 0, 0, 0, false,
167 DEFUN (show_ip_rpf_addr
,
168 show_ip_rpf_addr_cmd
,
169 "show ip rpf A.B.C.D",
172 "Display RPF information for multicast source\n"
173 "IP multicast source address (e.g. 10.0.0.0)\n")
177 struct route_node
*rn
;
178 struct route_entry
*re
;
181 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
183 vty_out(vty
, "%% Malformed address\n");
187 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
190 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
192 vty_out(vty
, "%% No match for RPF lookup\n");
197 static char re_status_output_char(const struct route_entry
*re
,
198 const struct nexthop
*nhop
,
201 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
205 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
206 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
207 /* More-specific test for 'fib' output */
209 star_p
= !!CHECK_FLAG(nhop
->flags
,
215 if (zrouter
.asic_offloaded
&&
216 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
219 if (zrouter
.asic_offloaded
220 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
223 if (zrouter
.asic_offloaded
224 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
233 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
234 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
240 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
247 * Show backup nexthop info, in the 'detailed' output path
249 static void show_nh_backup_helper(struct vty
*vty
,
250 const struct route_entry
*re
,
251 const struct nexthop
*nexthop
)
253 const struct nexthop
*start
, *backup
, *temp
;
256 /* Double-check that there _is_ a backup */
257 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
258 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
259 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
262 /* Locate the backup nexthop(s) */
263 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
264 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
265 /* Format the backup(s) (indented) */
267 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
268 backup
= backup
->next
;
273 /* It's possible for backups to be recursive too,
274 * so walk the recursive resolution list if present.
279 show_nexthop_detail_helper(vty
, re
, backup
,
283 if (backup
->resolved
&& temp
== backup
)
284 backup
= backup
->resolved
;
286 backup
= nexthop_next(backup
);
288 if (backup
== temp
->next
)
296 * Helper api to format output for a nexthop, used in the 'detailed'
299 static void show_nexthop_detail_helper(struct vty
*vty
,
300 const struct route_entry
*re
,
301 const struct nexthop
*nexthop
,
305 char buf
[MPLS_LABEL_STRLEN
];
310 nexthop
->rparent
? " " : "");
312 vty_out(vty
, " %c%s",
313 re_status_output_char(re
, nexthop
, false),
314 nexthop
->rparent
? " " : "");
316 switch (nexthop
->type
) {
317 case NEXTHOP_TYPE_IPV4
:
318 case NEXTHOP_TYPE_IPV4_IFINDEX
:
319 vty_out(vty
, " %pI4",
320 &nexthop
->gate
.ipv4
);
321 if (nexthop
->ifindex
)
322 vty_out(vty
, ", via %s",
327 case NEXTHOP_TYPE_IPV6
:
328 case NEXTHOP_TYPE_IPV6_IFINDEX
:
330 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
332 if (nexthop
->ifindex
)
333 vty_out(vty
, ", via %s",
339 case NEXTHOP_TYPE_IFINDEX
:
340 vty_out(vty
, " directly connected, %s",
341 ifindex2ifname(nexthop
->ifindex
,
344 case NEXTHOP_TYPE_BLACKHOLE
:
345 vty_out(vty
, " unreachable");
346 switch (nexthop
->bh_type
) {
347 case BLACKHOLE_REJECT
:
348 vty_out(vty
, " (ICMP unreachable)");
350 case BLACKHOLE_ADMINPROHIB
:
352 " (ICMP admin-prohibited)");
355 vty_out(vty
, " (blackhole)");
357 case BLACKHOLE_UNSPEC
:
363 if (re
->vrf_id
!= nexthop
->vrf_id
) {
364 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
366 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
369 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
370 vty_out(vty
, " (duplicate nexthop removed)");
372 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
373 vty_out(vty
, " inactive");
375 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
376 vty_out(vty
, " onlink");
378 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
379 vty_out(vty
, " linkdown");
381 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
382 vty_out(vty
, " (recursive)");
384 /* Source specified? */
385 switch (nexthop
->type
) {
386 case NEXTHOP_TYPE_IPV4
:
387 case NEXTHOP_TYPE_IPV4_IFINDEX
:
388 if (nexthop
->src
.ipv4
.s_addr
) {
389 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
390 addrstr
, sizeof(addrstr
)))
391 vty_out(vty
, ", src %s",
396 case NEXTHOP_TYPE_IPV6
:
397 case NEXTHOP_TYPE_IPV6_IFINDEX
:
398 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
400 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
401 addrstr
, sizeof(addrstr
)))
402 vty_out(vty
, ", src %s",
412 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
414 /* Label information */
415 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
416 vty_out(vty
, ", label %s",
417 mpls_label2str(nexthop
->nh_label
->num_labels
,
418 nexthop
->nh_label
->label
, buf
,
419 sizeof(buf
), 1 /*pretty*/));
423 vty_out(vty
, ", weight %u", nexthop
->weight
);
425 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
426 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
428 for (i
= 1; i
< nexthop
->backup_num
; i
++)
429 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
433 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
434 struct json_object
*json
)
436 struct bgp_zebra_opaque bzo
= {};
437 struct ospf_zebra_opaque ozo
= {};
443 case ZEBRA_ROUTE_SHARP
:
445 json_object_string_add(json
, "opaque",
446 (char *)re
->opaque
->data
);
448 vty_out(vty
, " Opaque Data: %s",
449 (char *)re
->opaque
->data
);
452 case ZEBRA_ROUTE_BGP
:
453 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
456 json_object_string_add(json
, "asPath", bzo
.aspath
);
457 json_object_string_add(json
, "communities",
459 json_object_string_add(json
, "largeCommunities",
461 json_object_string_add(json
, "selectionReason",
462 bzo
.selection_reason
);
464 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
466 if (bzo
.community
[0] != '\0')
467 vty_out(vty
, " Communities : %s\n",
470 if (bzo
.lcommunity
[0] != '\0')
471 vty_out(vty
, " Large-Communities: %s\n",
474 vty_out(vty
, " Selection reason : %s\n",
475 bzo
.selection_reason
);
478 case ZEBRA_ROUTE_OSPF
:
479 case ZEBRA_ROUTE_OSPF6
:
480 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
483 json_object_string_add(json
, "ospfPathType",
485 if (ozo
.area_id
[0] != '\0')
486 json_object_string_add(json
, "ospfAreaId",
488 if (ozo
.tag
[0] != '\0')
489 json_object_string_add(json
, "ospfTag",
492 vty_out(vty
, " OSPF path type : %s\n",
494 if (ozo
.area_id
[0] != '\0')
495 vty_out(vty
, " OSPF area ID : %s\n",
497 if (ozo
.tag
[0] != '\0')
498 vty_out(vty
, " OSPF tag : %s\n",
507 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
511 cur
= monotime(NULL
);
514 frrtime_to_interval(cur
, buf
, bufsize
);
517 /* New RIB. Detailed information for IPv4 route. */
518 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
519 int mcast
, bool use_fib
, bool show_ng
)
521 struct route_entry
*re
;
522 struct nexthop
*nexthop
;
523 char buf
[SRCDEST2STR_BUFFER
];
524 struct zebra_vrf
*zvrf
;
527 dest
= rib_dest_from_rnode(rn
);
529 RNODE_FOREACH_RE (rn
, re
) {
531 * If re not selected for forwarding, skip re
532 * for "show ip/ipv6 fib <prefix>"
534 if (use_fib
&& re
!= dest
->selected_fib
)
537 const char *mcast_info
= "";
539 struct rib_table_info
*info
=
540 srcdest_rnode_table_info(rn
);
541 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
542 ? " using Multicast RIB"
543 : " using Unicast RIB";
546 vty_out(vty
, "Routing entry for %s%s\n",
547 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
548 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
550 vty_out(vty
, "[%d]", re
->instance
);
552 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
555 vty_out(vty
, ", tag %u", re
->tag
);
556 #if defined(SUPPORT_REALMS)
557 if (re
->tag
> 0 && re
->tag
<= 255)
558 vty_out(vty
, "(realm)");
562 vty_out(vty
, ", mtu %u", re
->mtu
);
563 if (re
->vrf_id
!= VRF_DEFAULT
) {
564 zvrf
= vrf_info_lookup(re
->vrf_id
);
565 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
567 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
568 vty_out(vty
, ", best");
571 uptime2str(re
->uptime
, buf
, sizeof(buf
));
573 vty_out(vty
, " Last update %s ago\n", buf
);
576 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
577 if (re
->nhe_installed_id
!= 0
578 && re
->nhe_id
!= re
->nhe_installed_id
)
580 " Installed Nexthop Group ID: %u\n",
581 re
->nhe_installed_id
);
584 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
585 /* Use helper to format each nexthop */
586 show_nexthop_detail_helper(vty
, re
, nexthop
,
587 false /*not backup*/);
590 /* Include backup(s), if present */
591 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
592 show_nh_backup_helper(vty
, re
, nexthop
);
594 zebra_show_ip_route_opaque(vty
, re
, NULL
);
601 * Helper for nexthop output, used in the 'show ip route' path
603 static void show_route_nexthop_helper(struct vty
*vty
,
604 const struct route_entry
*re
,
605 const struct nexthop
*nexthop
)
607 char buf
[MPLS_LABEL_STRLEN
];
610 switch (nexthop
->type
) {
611 case NEXTHOP_TYPE_IPV4
:
612 case NEXTHOP_TYPE_IPV4_IFINDEX
:
613 vty_out(vty
, " via %pI4", &nexthop
->gate
.ipv4
);
614 if (nexthop
->ifindex
)
616 ifindex2ifname(nexthop
->ifindex
,
619 case NEXTHOP_TYPE_IPV6
:
620 case NEXTHOP_TYPE_IPV6_IFINDEX
:
621 vty_out(vty
, " via %s",
622 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
624 if (nexthop
->ifindex
)
626 ifindex2ifname(nexthop
->ifindex
,
630 case NEXTHOP_TYPE_IFINDEX
:
631 vty_out(vty
, " is directly connected, %s",
632 ifindex2ifname(nexthop
->ifindex
,
635 case NEXTHOP_TYPE_BLACKHOLE
:
636 vty_out(vty
, " unreachable");
637 switch (nexthop
->bh_type
) {
638 case BLACKHOLE_REJECT
:
639 vty_out(vty
, " (ICMP unreachable)");
641 case BLACKHOLE_ADMINPROHIB
:
642 vty_out(vty
, " (ICMP admin-prohibited)");
645 vty_out(vty
, " (blackhole)");
647 case BLACKHOLE_UNSPEC
:
653 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
654 vty_out(vty
, " (vrf %s)", vrf_id_to_name(nexthop
->vrf_id
));
656 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
657 vty_out(vty
, " inactive");
659 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
660 vty_out(vty
, " onlink");
662 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
663 vty_out(vty
, " linkdown");
665 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
666 vty_out(vty
, " (recursive)");
668 switch (nexthop
->type
) {
669 case NEXTHOP_TYPE_IPV4
:
670 case NEXTHOP_TYPE_IPV4_IFINDEX
:
671 if (nexthop
->src
.ipv4
.s_addr
) {
672 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
674 vty_out(vty
, ", src %s", buf
);
675 /* SR-TE information */
676 if (nexthop
->srte_color
)
677 vty_out(vty
, ", SR-TE color %u",
678 nexthop
->srte_color
);
681 case NEXTHOP_TYPE_IPV6
:
682 case NEXTHOP_TYPE_IPV6_IFINDEX
:
683 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
684 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
686 vty_out(vty
, ", src %s", buf
);
693 /* Label information */
694 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
695 vty_out(vty
, ", label %s",
696 mpls_label2str(nexthop
->nh_label
->num_labels
,
697 nexthop
->nh_label
->label
, buf
,
701 if (nexthop
->nh_srv6
) {
702 seg6local_context2str(buf
, sizeof(buf
),
703 &nexthop
->nh_srv6
->seg6local_ctx
,
704 nexthop
->nh_srv6
->seg6local_action
);
705 vty_out(vty
, ", seg6local %s %s", seg6local_action2str(
706 nexthop
->nh_srv6
->seg6local_action
), buf
);
708 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
710 vty_out(vty
, ", seg6 %s", buf
);
714 vty_out(vty
, ", weight %u", nexthop
->weight
);
716 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
717 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
719 for (i
= 1; i
< nexthop
->backup_num
; i
++)
720 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
725 * Render a nexthop into a json object; the caller allocates and owns
726 * the json object memory.
728 static void show_nexthop_json_helper(json_object
*json_nexthop
,
729 const struct nexthop
*nexthop
,
730 const struct route_entry
*re
)
732 char buf
[SRCDEST2STR_BUFFER
];
733 json_object
*json_labels
= NULL
;
734 json_object
*json_backups
= NULL
;
735 json_object
*json_seg6local
= NULL
;
736 json_object
*json_seg6
= NULL
;
739 json_object_int_add(json_nexthop
, "flags",
742 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
743 json_object_boolean_true_add(json_nexthop
,
746 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
747 json_object_boolean_true_add(json_nexthop
,
750 switch (nexthop
->type
) {
751 case NEXTHOP_TYPE_IPV4
:
752 case NEXTHOP_TYPE_IPV4_IFINDEX
:
753 json_object_string_addf(json_nexthop
, "ip", "%pI4",
754 &nexthop
->gate
.ipv4
);
755 json_object_string_add(json_nexthop
, "afi",
758 if (nexthop
->ifindex
) {
759 json_object_int_add(json_nexthop
,
762 json_object_string_add(
763 json_nexthop
, "interfaceName",
769 case NEXTHOP_TYPE_IPV6
:
770 case NEXTHOP_TYPE_IPV6_IFINDEX
:
771 json_object_string_addf(json_nexthop
, "ip", "%pI6",
772 &nexthop
->gate
.ipv6
);
773 json_object_string_add(json_nexthop
, "afi",
776 if (nexthop
->ifindex
) {
777 json_object_int_add(json_nexthop
,
780 json_object_string_add(
781 json_nexthop
, "interfaceName",
788 case NEXTHOP_TYPE_IFINDEX
:
789 json_object_boolean_true_add(
790 json_nexthop
, "directlyConnected");
791 json_object_int_add(json_nexthop
,
794 json_object_string_add(
795 json_nexthop
, "interfaceName",
796 ifindex2ifname(nexthop
->ifindex
,
799 case NEXTHOP_TYPE_BLACKHOLE
:
800 json_object_boolean_true_add(json_nexthop
,
802 switch (nexthop
->bh_type
) {
803 case BLACKHOLE_REJECT
:
804 json_object_boolean_true_add(
805 json_nexthop
, "reject");
807 case BLACKHOLE_ADMINPROHIB
:
808 json_object_boolean_true_add(
813 json_object_boolean_true_add(
814 json_nexthop
, "blackhole");
816 case BLACKHOLE_UNSPEC
:
822 /* This nexthop is a resolver for the parent nexthop.
823 * Set resolver flag for better clarity and delimiter
824 * in flat list of nexthops in json.
826 if (nexthop
->rparent
)
827 json_object_boolean_true_add(json_nexthop
, "resolver");
829 if (nexthop
->vrf_id
!= re
->vrf_id
)
830 json_object_string_add(json_nexthop
, "vrf",
831 vrf_id_to_name(nexthop
->vrf_id
));
833 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
834 json_object_boolean_true_add(json_nexthop
,
837 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
838 json_object_boolean_true_add(json_nexthop
,
841 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
842 json_object_boolean_true_add(json_nexthop
,
845 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
846 json_object_boolean_true_add(json_nexthop
, "linkDown");
848 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
849 json_object_boolean_true_add(json_nexthop
,
852 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
853 json_backups
= json_object_new_array();
854 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
855 json_object_array_add(
857 json_object_new_int(nexthop
->backup_idx
[i
]));
860 json_object_object_add(json_nexthop
, "backupIndex",
864 switch (nexthop
->type
) {
865 case NEXTHOP_TYPE_IPV4
:
866 case NEXTHOP_TYPE_IPV4_IFINDEX
:
867 if (nexthop
->src
.ipv4
.s_addr
) {
868 if (inet_ntop(AF_INET
,
869 &nexthop
->src
.ipv4
, buf
,
871 json_object_string_add(
872 json_nexthop
, "source",
876 case NEXTHOP_TYPE_IPV6
:
877 case NEXTHOP_TYPE_IPV6_IFINDEX
:
878 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
880 if (inet_ntop(AF_INET6
,
881 &nexthop
->src
.ipv6
, buf
,
883 json_object_string_add(
884 json_nexthop
, "source",
892 if (nexthop
->nh_label
893 && nexthop
->nh_label
->num_labels
) {
894 json_labels
= json_object_new_array();
896 for (int label_index
= 0;
898 < nexthop
->nh_label
->num_labels
;
900 json_object_array_add(
903 nexthop
->nh_label
->label
906 json_object_object_add(json_nexthop
, "labels",
911 json_object_int_add(json_nexthop
, "weight",
914 if (nexthop
->srte_color
)
915 json_object_int_add(json_nexthop
, "srteColor",
916 nexthop
->srte_color
);
918 if (nexthop
->nh_srv6
) {
919 json_seg6local
= json_object_new_object();
920 json_object_string_add(
921 json_seg6local
, "action", seg6local_action2str(
922 nexthop
->nh_srv6
->seg6local_action
));
923 json_object_object_add(json_nexthop
, "seg6local",
926 json_seg6
= json_object_new_object();
927 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
929 json_object_string_add(json_seg6
, "segs", buf
);
930 json_object_object_add(json_nexthop
, "seg6", json_seg6
);
934 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
935 struct route_entry
*re
, json_object
*json
,
936 bool is_fib
, bool show_ng
)
938 const struct nexthop
*nexthop
;
940 char buf
[SRCDEST2STR_BUFFER
];
941 json_object
*json_nexthops
= NULL
;
942 json_object
*json_nexthop
= NULL
;
943 json_object
*json_route
= NULL
;
944 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
945 const struct nexthop_group
*nhg
;
946 char up_str
[MONOTIME_STRLEN
];
948 bool nhg_from_backup
= false;
950 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
952 /* If showing fib information, use the fib view of the
956 nhg
= rib_get_fib_nhg(re
);
958 nhg
= &(re
->nhe
->nhg
);
961 json_route
= json_object_new_object();
962 json_nexthops
= json_object_new_array();
964 json_object_string_add(json_route
, "prefix",
965 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
966 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
967 json_object_string_add(json_route
, "protocol",
968 zebra_route_string(re
->type
));
971 json_object_int_add(json_route
, "instance",
974 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
975 json_object_string_add(json_route
, "vrfName",
976 vrf_id_to_name(re
->vrf_id
));
978 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
979 json_object_boolean_true_add(json_route
, "selected");
981 if (dest
->selected_fib
== re
)
982 json_object_boolean_true_add(json_route
,
985 json_object_int_add(json_route
, "distance",
987 json_object_int_add(json_route
, "metric", re
->metric
);
989 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
990 json_object_boolean_true_add(json_route
, "installed");
992 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
993 json_object_boolean_true_add(json_route
, "failed");
995 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
996 json_object_boolean_true_add(json_route
, "queued");
998 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
999 json_object_boolean_true_add(json_route
, "trapped");
1001 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
1002 json_object_boolean_true_add(json_route
, "offloaded");
1004 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
1005 json_object_boolean_false_add(json_route
, "offloaded");
1008 json_object_int_add(json_route
, "tag", re
->tag
);
1011 json_object_int_add(json_route
, "table", re
->table
);
1013 json_object_int_add(json_route
, "internalStatus",
1015 json_object_int_add(json_route
, "internalFlags",
1017 json_object_int_add(json_route
, "internalNextHopNum",
1018 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
1019 json_object_int_add(json_route
, "internalNextHopActiveNum",
1020 nexthop_group_active_nexthop_num(
1022 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
1024 if (re
->nhe_installed_id
!= 0)
1025 json_object_int_add(json_route
,
1026 "installedNexthopGroupId",
1027 re
->nhe_installed_id
);
1029 json_object_string_add(json_route
, "uptime", up_str
);
1031 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1032 json_nexthop
= json_object_new_object();
1033 show_nexthop_json_helper(json_nexthop
,
1036 json_object_array_add(json_nexthops
,
1040 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1042 /* If there are backup nexthops, include them */
1044 nhg
= rib_get_fib_backup_nhg(re
);
1046 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1048 if (nhg
&& nhg
->nexthop
) {
1049 json_nexthops
= json_object_new_array();
1051 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1052 json_nexthop
= json_object_new_object();
1054 show_nexthop_json_helper(json_nexthop
,
1056 json_object_array_add(json_nexthops
,
1060 json_object_object_add(json_route
, "backupNexthops",
1063 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
1065 json_object_array_add(json
, json_route
);
1069 /* Prefix information, and first nexthop. If we're showing 'fib',
1070 * and there are no installed primary nexthops, see if there are any
1071 * backup nexthops and start with those.
1073 if (is_fib
&& nhg
->nexthop
== NULL
) {
1074 nhg
= rib_get_fib_backup_nhg(re
);
1075 nhg_from_backup
= true;
1078 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1080 len
+= vty_out(vty
, "[%d]", re
->instance
);
1081 if (nhg_from_backup
&& nhg
->nexthop
) {
1084 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1085 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1086 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1090 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1091 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1092 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1095 /* Distance and metric display. */
1096 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
1097 (re
->distance
|| re
->metric
)) ||
1098 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
1099 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1103 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
1105 /* Nexthop information. */
1106 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1109 } else if (nhg_from_backup
) {
1110 vty_out(vty
, " b%c%*c",
1111 re_status_output_char(re
, nexthop
, is_fib
),
1112 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1114 vty_out(vty
, " %c%*c",
1115 re_status_output_char(re
, nexthop
, is_fib
),
1116 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1119 show_route_nexthop_helper(vty
, re
, nexthop
);
1120 vty_out(vty
, ", %s\n", up_str
);
1123 /* If we only had backup nexthops, we're done */
1124 if (nhg_from_backup
)
1127 /* Check for backup nexthop info if present */
1129 nhg
= rib_get_fib_backup_nhg(re
);
1131 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1136 /* Print backup info */
1137 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1138 bool star_p
= false;
1141 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1143 /* TODO -- it'd be nice to be able to include
1144 * the entire list of backups, *and* include the
1145 * real installation state.
1147 vty_out(vty
, " b%c %*c",
1148 (star_p
? '*' : ' '),
1149 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1150 show_route_nexthop_helper(vty
, re
, nexthop
);
1156 static void vty_show_ip_route_detail_json(struct vty
*vty
,
1157 struct route_node
*rn
, bool use_fib
)
1159 json_object
*json
= NULL
;
1160 json_object
*json_prefix
= NULL
;
1161 struct route_entry
*re
;
1165 dest
= rib_dest_from_rnode(rn
);
1167 json
= json_object_new_object();
1168 json_prefix
= json_object_new_array();
1170 RNODE_FOREACH_RE (rn
, re
) {
1172 * If re not selected for forwarding, skip re
1173 * for "show ip/ipv6 fib <prefix> json"
1175 if (use_fib
&& re
!= dest
->selected_fib
)
1177 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
1180 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1181 json_object_object_add(json
, buf
, json_prefix
);
1182 vty_json(vty
, json
);
1185 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1186 struct route_table
*table
, afi_t afi
,
1187 bool use_fib
, route_tag_t tag
,
1188 const struct prefix
*longer_prefix_p
,
1189 bool supernets_only
, int type
,
1190 unsigned short ospf_instance_id
, bool use_json
,
1191 uint32_t tableid
, bool show_ng
,
1192 struct route_show_ctx
*ctx
)
1194 struct route_node
*rn
;
1195 struct route_entry
*re
;
1198 json_object
*json
= NULL
;
1199 json_object
*json_prefix
= NULL
;
1204 * ctx->multi indicates if we are dumping multiple tables or vrfs.
1206 * => display the common header at most once
1207 * => add newline at each call except first
1208 * => always display the VRF and table
1210 * => display the common header if at least one entry is found
1211 * => display the VRF and table if specific
1215 json
= json_object_new_object();
1217 /* Show all routes. */
1218 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
1219 dest
= rib_dest_from_rnode(rn
);
1221 RNODE_FOREACH_RE (rn
, re
) {
1222 if (use_fib
&& re
!= dest
->selected_fib
)
1225 if (tag
&& re
->tag
!= tag
)
1229 && !prefix_match(longer_prefix_p
, &rn
->p
))
1232 /* This can only be true when the afi is IPv4 */
1233 if (supernets_only
) {
1234 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1236 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1239 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1242 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1246 if (type
&& re
->type
!= type
)
1249 if (ospf_instance_id
1250 && (re
->type
!= ZEBRA_ROUTE_OSPF
1251 || re
->instance
!= ospf_instance_id
))
1256 json_prefix
= json_object_new_array();
1258 if (!ctx
->header_done
) {
1261 SHOW_ROUTE_V4_HEADER
);
1264 SHOW_ROUTE_V6_HEADER
);
1266 if (ctx
->multi
&& ctx
->header_done
)
1268 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
1271 vty_out(vty
, "VRF %s:\n",
1275 "VRF %s table %u:\n",
1279 ctx
->header_done
= true;
1283 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
1288 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1289 json_object_object_add(json
, buf
, json_prefix
);
1295 vty_json(vty
, json
);
1298 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1299 afi_t afi
, bool use_fib
, bool use_json
,
1301 const struct prefix
*longer_prefix_p
,
1302 bool supernets_only
, int type
,
1303 unsigned short ospf_instance_id
, bool show_ng
,
1304 struct route_show_ctx
*ctx
)
1306 struct zebra_router_table
*zrt
;
1307 struct rib_table_info
*info
;
1309 RB_FOREACH (zrt
, zebra_router_table_head
,
1311 info
= route_table_get_info(zrt
->table
);
1313 if (zvrf
!= info
->zvrf
)
1315 if (zrt
->afi
!= afi
||
1316 zrt
->safi
!= SAFI_UNICAST
)
1319 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1320 use_fib
, use_json
, tag
, longer_prefix_p
,
1321 supernets_only
, type
, ospf_instance_id
,
1322 zrt
->tableid
, show_ng
, ctx
);
1326 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1327 safi_t safi
, bool use_fib
, bool use_json
,
1329 const struct prefix
*longer_prefix_p
,
1330 bool supernets_only
, int type
,
1331 unsigned short ospf_instance_id
, uint32_t tableid
,
1332 bool show_ng
, struct route_show_ctx
*ctx
)
1334 struct route_table
*table
;
1335 struct zebra_vrf
*zvrf
= NULL
;
1337 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1339 vty_out(vty
, "{}\n");
1341 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1345 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1347 vty_out(vty
, "{}\n");
1349 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1354 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1356 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1359 vty_out(vty
, "{}\n");
1363 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1364 longer_prefix_p
, supernets_only
, type
,
1365 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1372 "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]",
1376 "IP nexthop tracking table\n"
1377 "IP import check tracking table\n"
1383 VRF_ALL_CMD_HELP_STR
1384 "Show Multicast (MRIB) NHT state\n")
1386 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1387 vrf_id_t vrf_id
= VRF_DEFAULT
;
1388 struct prefix prefix
, *p
= NULL
;
1389 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1393 struct zebra_vrf
*zvrf
;
1395 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1396 if ((zvrf
= vrf
->info
) != NULL
) {
1397 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1398 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1404 VRF_GET_ID(vrf_id
, vrf_name
, false);
1406 memset(&prefix
, 0, sizeof(prefix
));
1408 p
= sockunion2hostprefix(addr
, &prefix
);
1413 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
);
1417 DEFUN (ip_nht_default_route
,
1418 ip_nht_default_route_cmd
,
1419 "ip nht resolve-via-default",
1421 "Filter Next Hop tracking route resolution\n"
1422 "Resolve via default route\n")
1424 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1429 if (zvrf
->zebra_rnh_ip_default_route
)
1432 zvrf
->zebra_rnh_ip_default_route
= true;
1434 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1438 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
)
1440 struct nexthop
*nexthop
= NULL
;
1441 struct nhg_connected
*rb_node_dep
= NULL
;
1442 struct nexthop_group
*backup_nhg
;
1443 char up_str
[MONOTIME_STRLEN
];
1444 char time_left
[MONOTIME_STRLEN
];
1446 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1448 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
, zebra_route_string(nhe
->type
));
1449 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1450 if (thread_is_scheduled(nhe
->timer
))
1451 vty_out(vty
, " Time to Deletion: %s",
1452 thread_timer_to_hhmmss(time_left
, sizeof(time_left
),
1456 vty_out(vty
, " Uptime: %s\n", up_str
);
1457 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1460 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1461 vty_out(vty
, " Valid");
1462 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
))
1463 vty_out(vty
, ", Installed");
1467 vty_out(vty
, " Interface Index: %d\n", nhe
->ifp
->ifindex
);
1469 if (!zebra_nhg_depends_is_empty(nhe
)) {
1470 vty_out(vty
, " Depends:");
1471 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1472 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1477 /* Output nexthops */
1478 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1479 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1482 /* Make recursive nexthops a bit more clear */
1485 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1487 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1488 if (CHECK_FLAG(nexthop
->flags
,
1489 NEXTHOP_FLAG_HAS_BACKUP
))
1490 vty_out(vty
, " [backup %d]",
1491 nexthop
->backup_idx
[0]);
1497 /* TODO -- print more useful backup info */
1498 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
1501 vty_out(vty
, "[backup");
1502 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1503 vty_out(vty
, " %d", nexthop
->backup_idx
[i
]);
1511 /* Output backup nexthops (if any) */
1512 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1514 vty_out(vty
, " Backups:\n");
1516 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1517 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1520 /* Make recursive nexthops a bit more clear */
1523 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1528 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1529 vty_out(vty
, " Dependents:");
1530 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1532 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1539 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
)
1541 struct nhg_hash_entry
*nhe
= NULL
;
1543 nhe
= zebra_nhg_lookup_id(id
);
1546 show_nexthop_group_out(vty
, nhe
);
1548 vty_out(vty
, "Nexthop Group ID: %u does not exist\n", id
);
1554 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1556 struct nhe_show_context
{
1563 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1565 struct nhe_show_context
*ctx
= arg
;
1566 struct nhg_hash_entry
*nhe
;
1568 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1570 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1573 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1576 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1579 show_nexthop_group_out(ctx
->vty
, nhe
);
1582 return HASHWALK_CONTINUE
;
1585 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1586 struct zebra_vrf
*zvrf
, afi_t afi
,
1589 struct nhe_show_context ctx
;
1593 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1596 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1599 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1601 struct zebra_if
*zebra_if
= NULL
;
1602 struct nhg_connected
*rb_node_dep
= NULL
;
1604 zebra_if
= ifp
->info
;
1606 if (!if_nhg_dependents_is_empty(ifp
)) {
1607 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1609 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1612 show_nexthop_group_out(vty
, rb_node_dep
->nhe
);
1617 DEFPY (show_interface_nexthop_group
,
1618 show_interface_nexthop_group_cmd
,
1619 "show interface [IFNAME$if_name] nexthop-group",
1621 "Interface status and configuration\n"
1623 "Show Nexthop Groups\n")
1625 struct vrf
*vrf
= NULL
;
1626 struct interface
*ifp
= NULL
;
1629 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1631 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1633 if_nexthop_group_dump_vty(vty
, ifp
);
1637 FOR_ALL_INTERFACES (vrf
, ifp
)
1638 if_nexthop_group_dump_vty(vty
, ifp
);
1644 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1651 DEFPY (show_nexthop_group
,
1652 show_nexthop_group_cmd
,
1653 "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>]>",
1655 "Show Nexthop Groups\n"
1657 "Nexthop Group ID\n"
1658 "Show Singleton Nexthop-Groups\n"
1661 "Kernel (not installed via the zebra RIB)\n"
1662 "Zebra (implicitly created by zebra)\n"
1663 "Border Gateway Protocol (BGP)\n"
1664 "Super Happy Advanced Routing Protocol (SHARP)\n"
1665 VRF_FULL_CMD_HELP_STR
)
1668 struct zebra_vrf
*zvrf
= NULL
;
1669 afi_t afi
= AFI_UNSPEC
;
1673 return show_nexthop_group_id_cmd_helper(vty
, id
);
1681 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1684 type
= ZEBRA_ROUTE_NHG
;
1688 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1690 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1697 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1698 struct zebra_vrf
*zvrf
;
1704 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1705 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1712 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1714 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1717 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1722 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1727 DEFPY_HIDDEN(nexthop_group_use_enable
,
1728 nexthop_group_use_enable_cmd
,
1729 "[no] zebra nexthop kernel enable",
1732 "Nexthop configuration \n"
1733 "Configure use of kernel nexthops\n"
1734 "Enable kernel nexthops\n")
1736 zebra_nhg_enable_kernel_nexthops(!no
);
1740 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1741 "[no] zebra nexthop proto only",
1743 "Nexthop configuration\n"
1744 "Configure exclusive use of proto nexthops\n"
1745 "Only use proto nexthops\n")
1747 zebra_nhg_set_proto_nexthops_only(!no
);
1751 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1752 backup_nexthop_recursive_use_enable_cmd
,
1753 "[no] zebra nexthop resolve-via-backup",
1756 "Nexthop configuration \n"
1757 "Configure use of backup nexthops in recursive resolution\n")
1759 zebra_nhg_set_recursive_use_backups(!no
);
1763 DEFUN (no_ip_nht_default_route
,
1764 no_ip_nht_default_route_cmd
,
1765 "no ip nht resolve-via-default",
1768 "Filter Next Hop tracking route resolution\n"
1769 "Resolve via default route\n")
1771 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1776 if (!zvrf
->zebra_rnh_ip_default_route
)
1779 zvrf
->zebra_rnh_ip_default_route
= false;
1780 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1784 DEFUN (ipv6_nht_default_route
,
1785 ipv6_nht_default_route_cmd
,
1786 "ipv6 nht resolve-via-default",
1788 "Filter Next Hop tracking route resolution\n"
1789 "Resolve via default route\n")
1791 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1796 if (zvrf
->zebra_rnh_ipv6_default_route
)
1799 zvrf
->zebra_rnh_ipv6_default_route
= true;
1800 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1804 DEFUN (no_ipv6_nht_default_route
,
1805 no_ipv6_nht_default_route_cmd
,
1806 "no ipv6 nht resolve-via-default",
1809 "Filter Next Hop tracking route resolution\n"
1810 "Resolve via default route\n")
1812 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1817 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1820 zvrf
->zebra_rnh_ipv6_default_route
= false;
1821 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1825 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1826 "[no] ip nht hide-backup-events",
1829 "Nexthop-tracking configuration\n"
1830 "Hide notification about backup nexthops\n")
1832 rnh_set_hide_backups(!no
);
1840 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1841 [vrf <NAME$vrf_name|all$vrf_all>]\
1844 |A.B.C.D/M$prefix longer-prefixes\
1845 |supernets-only$supernets_only\
1848 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1849 |ospf$type_str (1-65535)$ospf_instance_id\
1851 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1852 [vrf <NAME$vrf_name|all$vrf_all>]\
1855 |X:X::X:X/M$prefix longer-prefixes\
1857 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1859 [<json$json|nexthop-group$ng>]",
1862 "IP forwarding table\n"
1863 "IP routing table\n"
1864 "Table to display\n"
1865 "The table number to display\n"
1867 VRF_FULL_CMD_HELP_STR
1868 "Show only routes with tag\n"
1870 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1871 "Show route matching the specified Network/Mask pair only\n"
1872 "Show supernet entries only\n"
1873 FRR_IP_REDIST_HELP_STR_ZEBRA
1874 "Open Shortest Path First (OSPFv2)\n"
1877 "IP forwarding table\n"
1878 "IP routing table\n"
1879 "Table to display\n"
1880 "The table number to display\n"
1882 VRF_FULL_CMD_HELP_STR
1883 "Show only routes with tag\n"
1886 "Show route matching the specified Network/Mask pair only\n"
1887 FRR_IP6_REDIST_HELP_STR_ZEBRA
1889 "Nexthop Group Information\n")
1891 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1894 struct zebra_vrf
*zvrf
;
1895 struct route_show_ctx ctx
= {
1896 .multi
= vrf_all
|| table_all
,
1899 if (!vrf_is_backend_netns()) {
1900 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1902 vty_out(vty
, "{}\n");
1904 vty_out(vty
, "Linux vrf backend already points to table id\n");
1905 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1911 type
= proto_redistnum(afi
, type_str
);
1913 vty_out(vty
, "Unknown route type\n");
1919 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1920 if ((zvrf
= vrf
->info
) == NULL
1921 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1925 do_show_ip_route_all(
1926 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1927 prefix_str
? prefix
: NULL
,
1928 !!supernets_only
, type
,
1929 ospf_instance_id
, !!ng
, &ctx
);
1932 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1934 prefix_str
? prefix
: NULL
,
1935 !!supernets_only
, type
,
1936 ospf_instance_id
, table
, !!ng
, &ctx
);
1939 vrf_id_t vrf_id
= VRF_DEFAULT
;
1942 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1943 vrf
= vrf_lookup_by_id(vrf_id
);
1952 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1953 prefix_str
? prefix
: NULL
,
1954 !!supernets_only
, type
,
1955 ospf_instance_id
, !!ng
, &ctx
);
1957 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1959 prefix_str
? prefix
: NULL
,
1960 !!supernets_only
, type
,
1961 ospf_instance_id
, table
, !!ng
, &ctx
);
1967 ALIAS_HIDDEN (show_route
,
1969 "show <ip$ipv4|ipv6$ipv6> ro",
1973 "IP routing table\n");
1976 DEFPY (show_route_detail
,
1977 show_route_detail_cmd
,
1980 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1985 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1991 [json$json] [nexthop-group$ng]",
1994 "IPv6 forwarding table\n"
1995 "IP routing table\n"
1996 VRF_FULL_CMD_HELP_STR
1997 "Network in the IP routing table to display\n"
1998 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2000 "IPv6 forwarding table\n"
2001 "IPv6 routing table\n"
2002 VRF_FULL_CMD_HELP_STR
2006 "Nexthop Group Information\n")
2008 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2009 struct route_table
*table
;
2011 struct route_node
*rn
;
2012 bool use_fib
= !!fib
;
2014 bool network_found
= false;
2015 bool show_ng
= !!ng
;
2018 prefix_str
= address_str
;
2019 if (str2prefix(prefix_str
, &p
) < 0) {
2020 vty_out(vty
, "%% Malformed address\n");
2026 struct zebra_vrf
*zvrf
;
2028 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2029 if ((zvrf
= vrf
->info
) == NULL
2030 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2033 rn
= route_node_match(table
, &p
);
2036 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2037 route_unlock_node(rn
);
2041 dest
= rib_dest_from_rnode(rn
);
2042 if (use_fib
&& !dest
->selected_fib
) {
2043 route_unlock_node(rn
);
2047 network_found
= true;
2049 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2051 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
2054 route_unlock_node(rn
);
2057 if (!network_found
) {
2059 vty_out(vty
, "{}\n");
2063 "%% Network not in FIB\n");
2066 "%% Network not in RIB\n");
2071 vrf_id_t vrf_id
= VRF_DEFAULT
;
2074 VRF_GET_ID(vrf_id
, vrf_name
, false);
2076 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2080 rn
= route_node_match(table
, &p
);
2082 dest
= rib_dest_from_rnode(rn
);
2084 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
2085 (use_fib
&& dest
&& !dest
->selected_fib
)) {
2087 vty_out(vty
, "{}\n");
2091 "%% Network not in FIB\n");
2094 "%% Network not in table\n");
2097 route_unlock_node(rn
);
2102 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2104 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2106 route_unlock_node(rn
);
2112 DEFPY (show_route_summary
,
2113 show_route_summary_cmd
,
2114 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2115 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2119 "IP routing table\n"
2120 VRF_FULL_CMD_HELP_STR
2121 "Summary of all routes\n"
2122 "Table to display summary for\n"
2123 "The table number\n"
2127 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2128 struct route_table
*table
;
2129 bool uj
= use_json(argc
, argv
);
2133 struct zebra_vrf
*zvrf
;
2135 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2136 if ((zvrf
= vrf
->info
) == NULL
)
2140 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2143 table
= zebra_vrf_lookup_table_with_table_id(
2144 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2151 vty_show_ip_route_summary_prefix(vty
, table
,
2154 vty_show_ip_route_summary(vty
, table
, uj
);
2157 vrf_id_t vrf_id
= VRF_DEFAULT
;
2160 VRF_GET_ID(vrf_id
, vrf_name
, false);
2163 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2165 table
= zebra_vrf_lookup_table_with_table_id(
2166 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2171 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2173 vty_show_ip_route_summary(vty
, table
, uj
);
2179 DEFUN_HIDDEN (show_route_zebra_dump
,
2180 show_route_zebra_dump_cmd
,
2181 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2191 struct route_table
*table
;
2192 const char *vrf_name
= NULL
;
2195 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2197 if (argv_find(argv
, argc
, "vrf", &idx
))
2198 vrf_name
= argv
[++idx
]->arg
;
2202 struct zebra_vrf
*zvrf
;
2204 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2207 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2210 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2211 show_ip_route_dump_vty(vty
, table
);
2214 vrf_id_t vrf_id
= VRF_DEFAULT
;
2216 VRF_GET_ID(vrf_id
, vrf_name
, true);
2218 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2222 show_ip_route_dump_vty(vty
, table
);
2228 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2229 struct route_entry
*re
, unsigned int num
)
2232 char buf
[SRCDEST2STR_BUFFER
];
2234 vty_out(vty
, " Nexthop %u:\n", num
);
2235 vty_out(vty
, " type: %u\n", nexthop
->type
);
2236 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2237 switch (nexthop
->type
) {
2238 case NEXTHOP_TYPE_IPV4
:
2239 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2240 vty_out(vty
, " ip address: %s\n",
2241 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2243 vty_out(vty
, " afi: ipv4\n");
2245 if (nexthop
->ifindex
) {
2246 vty_out(vty
, " interface index: %d\n",
2248 vty_out(vty
, " interface name: %s\n",
2249 ifindex2ifname(nexthop
->ifindex
,
2253 if (nexthop
->src
.ipv4
.s_addr
2254 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2256 vty_out(vty
, " source: %s\n", buf
);
2258 case NEXTHOP_TYPE_IPV6
:
2259 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2260 vty_out(vty
, " ip: %s\n",
2261 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2263 vty_out(vty
, " afi: ipv6\n");
2265 if (nexthop
->ifindex
) {
2266 vty_out(vty
, " interface index: %d\n",
2268 vty_out(vty
, " interface name: %s\n",
2269 ifindex2ifname(nexthop
->ifindex
,
2273 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2274 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2276 vty_out(vty
, " source: %s\n", buf
);
2279 case NEXTHOP_TYPE_IFINDEX
:
2281 " Nexthop is an interface (directly connected).\n");
2282 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2283 vty_out(vty
, " interface name: %s\n",
2284 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2286 case NEXTHOP_TYPE_BLACKHOLE
:
2287 vty_out(vty
, " Nexthop type is blackhole.\n");
2289 switch (nexthop
->bh_type
) {
2290 case BLACKHOLE_REJECT
:
2291 vty_out(vty
, " Blackhole type: reject\n");
2293 case BLACKHOLE_ADMINPROHIB
:
2295 " Blackhole type: admin-prohibited\n");
2297 case BLACKHOLE_NULL
:
2298 vty_out(vty
, " Blackhole type: NULL0\n");
2300 case BLACKHOLE_UNSPEC
:
2307 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2309 struct route_node
*rn
;
2310 struct route_entry
*re
;
2311 char buf
[SRCDEST2STR_BUFFER
];
2316 struct nexthop
*nexthop
= NULL
;
2317 int nexthop_num
= 0;
2319 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2320 vty_out(vty
, "----------------------------\n");
2322 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2323 RNODE_FOREACH_RE (rn
, re
) {
2324 vty_out(vty
, "Route: %s\n",
2325 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2326 vty_out(vty
, " protocol: %s\n",
2327 zebra_route_string(re
->type
));
2328 vty_out(vty
, " instance: %u\n", re
->instance
);
2329 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2330 vty_out(vty
, " VRF name: %s\n",
2331 vrf_id_to_name(re
->vrf_id
));
2332 vty_out(vty
, " flags: %u\n", re
->flags
);
2334 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2335 vty_out(vty
, " distance: %u\n", re
->distance
);
2336 vty_out(vty
, " metric: %u\n", re
->metric
);
2339 vty_out(vty
, " tag: %u\n", re
->tag
);
2341 uptime
= monotime(&tv
);
2342 uptime
-= re
->uptime
;
2343 gmtime_r(&uptime
, &tm
);
2345 if (uptime
< ONE_DAY_SECOND
)
2346 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2347 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2348 else if (uptime
< ONE_WEEK_SECOND
)
2349 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2350 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2352 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2354 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2357 vty_out(vty
, " status: %u\n", re
->status
);
2358 vty_out(vty
, " nexthop_num: %u\n",
2359 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2360 vty_out(vty
, " nexthop_active_num: %u\n",
2361 nexthop_group_active_nexthop_num(
2363 vty_out(vty
, " table: %u\n", re
->table
);
2364 vty_out(vty
, " uptime: %s\n", time
);
2366 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2368 show_ip_route_nht_dump(vty
, nexthop
, re
,
2378 static void vty_show_ip_route_summary(struct vty
*vty
,
2379 struct route_table
*table
, bool use_json
)
2381 struct route_node
*rn
;
2382 struct route_entry
*re
;
2383 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2384 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2385 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2386 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2387 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2388 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2391 json_object
*json_route_summary
= NULL
;
2392 json_object
*json_route_routes
= NULL
;
2394 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2395 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2396 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2397 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2400 json_route_summary
= json_object_new_object();
2401 json_route_routes
= json_object_new_array();
2402 json_object_object_add(json_route_summary
, "routes",
2406 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2407 RNODE_FOREACH_RE (rn
, re
) {
2408 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2409 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2411 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2413 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2415 rib_cnt
[re
->type
]++;
2417 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2418 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2421 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2423 fib_cnt
[re
->type
]++;
2426 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2428 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2430 trap_cnt
[re
->type
]++;
2433 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2435 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2437 offload_cnt
[re
->type
]++;
2442 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2444 zvrf_name(((struct rib_table_info
*)
2445 route_table_get_info(table
))
2448 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2449 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2450 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2451 if (i
== ZEBRA_ROUTE_BGP
) {
2453 json_object
*json_route_ebgp
=
2454 json_object_new_object();
2456 json_object_int_add(
2457 json_route_ebgp
, "fib",
2458 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2459 json_object_int_add(
2460 json_route_ebgp
, "rib",
2461 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2462 json_object_int_add(
2463 json_route_ebgp
, "fibOffLoaded",
2464 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2465 json_object_int_add(
2466 json_route_ebgp
, "fibTrapped",
2467 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2469 json_object_string_add(json_route_ebgp
,
2471 json_object_array_add(json_route_routes
,
2474 json_object
*json_route_ibgp
=
2475 json_object_new_object();
2477 json_object_int_add(
2478 json_route_ibgp
, "fib",
2479 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2480 json_object_int_add(
2481 json_route_ibgp
, "rib",
2482 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2483 json_object_int_add(
2484 json_route_ibgp
, "fibOffLoaded",
2485 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2486 json_object_int_add(
2487 json_route_ibgp
, "fibTrapped",
2488 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2489 json_object_string_add(json_route_ibgp
,
2491 json_object_array_add(json_route_routes
,
2494 vty_out(vty
, "%-20s %-20d %-20d \n",
2496 rib_cnt
[ZEBRA_ROUTE_BGP
],
2497 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2498 vty_out(vty
, "%-20s %-20d %-20d \n",
2500 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2501 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2505 json_object
*json_route_type
=
2506 json_object_new_object();
2508 json_object_int_add(json_route_type
,
2510 json_object_int_add(json_route_type
,
2513 json_object_int_add(json_route_type
,
2516 json_object_int_add(json_route_type
,
2519 json_object_string_add(
2520 json_route_type
, "type",
2521 zebra_route_string(i
));
2522 json_object_array_add(json_route_routes
,
2525 vty_out(vty
, "%-20s %-20d %-20d \n",
2526 zebra_route_string(i
),
2527 rib_cnt
[i
], fib_cnt
[i
]);
2533 json_object_int_add(json_route_summary
, "routesTotal",
2534 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2535 json_object_int_add(json_route_summary
, "routesTotalFib",
2536 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2538 vty_json(vty
, json_route_summary
);
2540 vty_out(vty
, "------\n");
2541 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2542 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2548 * Implementation of the ip route summary prefix command.
2550 * This command prints the primary prefixes that have been installed by various
2551 * protocols on the box.
2554 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2555 struct route_table
*table
,
2558 struct route_node
*rn
;
2559 struct route_entry
*re
;
2560 struct nexthop
*nexthop
;
2561 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2562 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2563 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2564 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2567 json_object
*json_route_summary
= NULL
;
2568 json_object
*json_route_routes
= NULL
;
2570 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2571 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2574 json_route_summary
= json_object_new_object();
2575 json_route_routes
= json_object_new_array();
2576 json_object_object_add(json_route_summary
, "prefixRoutes",
2580 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2581 RNODE_FOREACH_RE (rn
, re
) {
2584 * In case of ECMP, count only once.
2587 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2588 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2589 fib_cnt
[re
->type
]++;
2591 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2592 nexthop
= nexthop
->next
) {
2594 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2595 rib_cnt
[re
->type
]++;
2596 if (re
->type
== ZEBRA_ROUTE_BGP
2597 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2598 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2599 if (CHECK_FLAG(re
->status
,
2600 ROUTE_ENTRY_INSTALLED
))
2601 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2607 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2608 "Prefix Routes", "FIB",
2609 zvrf_name(((struct rib_table_info
*)
2610 route_table_get_info(table
))
2613 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2614 if (rib_cnt
[i
] > 0) {
2615 if (i
== ZEBRA_ROUTE_BGP
) {
2617 json_object
*json_route_ebgp
=
2618 json_object_new_object();
2620 json_object_int_add(
2621 json_route_ebgp
, "fib",
2622 fib_cnt
[ZEBRA_ROUTE_BGP
]
2623 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2624 json_object_int_add(
2625 json_route_ebgp
, "rib",
2626 rib_cnt
[ZEBRA_ROUTE_BGP
]
2627 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2628 json_object_string_add(json_route_ebgp
,
2630 json_object_array_add(json_route_routes
,
2633 json_object
*json_route_ibgp
=
2634 json_object_new_object();
2636 json_object_int_add(
2637 json_route_ibgp
, "fib",
2638 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2639 json_object_int_add(
2640 json_route_ibgp
, "rib",
2641 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2642 json_object_string_add(json_route_ibgp
,
2644 json_object_array_add(json_route_routes
,
2647 vty_out(vty
, "%-20s %-20d %-20d \n",
2649 rib_cnt
[ZEBRA_ROUTE_BGP
]
2650 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2651 fib_cnt
[ZEBRA_ROUTE_BGP
]
2652 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2653 vty_out(vty
, "%-20s %-20d %-20d \n",
2655 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2656 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2660 json_object
*json_route_type
=
2661 json_object_new_object();
2663 json_object_int_add(json_route_type
,
2665 json_object_int_add(json_route_type
,
2667 json_object_string_add(
2668 json_route_type
, "type",
2669 zebra_route_string(i
));
2670 json_object_array_add(json_route_routes
,
2673 vty_out(vty
, "%-20s %-20d %-20d \n",
2674 zebra_route_string(i
),
2675 rib_cnt
[i
], fib_cnt
[i
]);
2681 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2682 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2683 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2684 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2686 vty_json(vty
, json_route_summary
);
2688 vty_out(vty
, "------\n");
2689 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2690 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2695 DEFUN (allow_external_route_update
,
2696 allow_external_route_update_cmd
,
2697 "allow-external-route-update",
2698 "Allow FRR routes to be overwritten by external processes\n")
2700 zrouter
.allow_delete
= true;
2705 DEFUN (no_allow_external_route_update
,
2706 no_allow_external_route_update_cmd
,
2707 "no allow-external-route-update",
2709 "Allow FRR routes to be overwritten by external processes\n")
2711 zrouter
.allow_delete
= false;
2724 struct zebra_vrf
*zvrf
;
2726 if (vrf_is_backend_netns())
2727 vty_out(vty
, "netns-based vrfs\n");
2729 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2730 if (!(zvrf
= vrf
->info
))
2732 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2735 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2736 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2737 vty_out(vty
, "inactive");
2738 else if (zvrf_ns_name(zvrf
))
2739 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2740 zvrf_ns_name(zvrf
));
2742 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2744 if (vrf_is_user_cfged(vrf
))
2745 vty_out(vty
, " (configured)");
2752 DEFPY (evpn_mh_mac_holdtime
,
2753 evpn_mh_mac_holdtime_cmd
,
2754 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2759 "Duration in seconds\n")
2761 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2765 DEFPY (evpn_mh_neigh_holdtime
,
2766 evpn_mh_neigh_holdtime_cmd
,
2767 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2771 "Neighbor entry hold time\n"
2772 "Duration in seconds\n")
2775 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2779 DEFPY (evpn_mh_startup_delay
,
2780 evpn_mh_startup_delay_cmd
,
2781 "[no] evpn mh startup-delay(0-3600)$duration",
2786 "duration in seconds\n")
2789 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2793 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2794 "[no$no] evpn mh redirect-off",
2798 "ES bond redirect for fast-failover off\n")
2802 redirect_off
= no
? false : true;
2804 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2807 DEFUN (default_vrf_vni_mapping
,
2808 default_vrf_vni_mapping_cmd
,
2809 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2810 "VNI corresponding to the DEFAULT VRF\n"
2812 "Prefix routes only \n")
2814 char xpath
[XPATH_MAXLEN
];
2815 struct zebra_vrf
*zvrf
= NULL
;
2818 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2825 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2827 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2829 snprintf(xpath
, sizeof(xpath
),
2830 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2832 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2835 snprintf(xpath
, sizeof(xpath
),
2836 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2838 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2841 return nb_cli_apply_changes(vty
, NULL
);
2844 DEFUN (no_default_vrf_vni_mapping
,
2845 no_default_vrf_vni_mapping_cmd
,
2846 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2848 "VNI corresponding to DEFAULT VRF\n"
2850 "Prefix routes only \n")
2852 char xpath
[XPATH_MAXLEN
];
2854 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2855 struct zebra_vrf
*zvrf
= NULL
;
2857 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2864 if (zvrf
->l3vni
!= vni
) {
2865 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2870 snprintf(xpath
, sizeof(xpath
),
2871 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2873 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2876 snprintf(xpath
, sizeof(xpath
),
2877 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2879 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2882 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2884 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2886 return nb_cli_apply_changes(vty
, NULL
);
2889 DEFUN (vrf_vni_mapping
,
2890 vrf_vni_mapping_cmd
,
2891 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2892 "VNI corresponding to tenant VRF\n"
2894 "prefix-routes-only\n")
2898 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2906 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2907 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2911 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2912 NB_OP_MODIFY
, "true");
2914 return nb_cli_apply_changes(vty
, NULL
);
2917 DEFUN (no_vrf_vni_mapping
,
2918 no_vrf_vni_mapping_cmd
,
2919 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2921 "VNI corresponding to tenant VRF\n"
2923 "prefix-routes-only\n")
2927 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2928 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2936 if (zvrf
->l3vni
!= vni
) {
2937 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2942 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2946 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2947 NB_OP_DESTROY
, "true");
2949 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2951 return nb_cli_apply_changes(vty
, NULL
);
2955 DEFUN (show_vrf_vni
,
2957 "show vrf vni [json]",
2964 struct zebra_vrf
*zvrf
;
2965 json_object
*json
= NULL
;
2966 json_object
*json_vrfs
= NULL
;
2967 bool uj
= use_json(argc
, argv
);
2970 json
= json_object_new_object();
2971 json_vrfs
= json_object_new_array();
2975 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2976 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2978 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2983 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2987 json_object_object_add(json
, "vrfs", json_vrfs
);
2988 vty_json(vty
, json
);
2994 DEFUN (show_evpn_global
,
2995 show_evpn_global_cmd
,
3001 bool uj
= use_json(argc
, argv
);
3003 zebra_vxlan_print_evpn(vty
, uj
);
3007 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
3008 SHOW_STR IP_STR
"neighbors\n")
3011 zebra_neigh_show(vty
);
3016 DEFPY(show_evpn_l2_nh
,
3017 show_evpn_l2_nh_cmd
,
3018 "show evpn l2-nh [json$json]",
3026 zebra_evpn_l2_nh_show(vty
, uj
);
3033 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3036 "Ethernet Segment\n"
3038 "Detailed information\n"
3045 if (!str_to_esi(esi_str
, &esi
)) {
3046 vty_out(vty
, "%% Malformed ESI\n");
3049 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3052 zebra_evpn_es_show_detail(vty
, uj
);
3054 zebra_evpn_es_show(vty
, uj
);
3060 DEFPY(show_evpn_es_evi
,
3061 show_evpn_es_evi_cmd
,
3062 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3065 "Ethernet Segment per EVI\n"
3066 "VxLAN Network Identifier\n"
3068 "Detailed information\n"
3075 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3077 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3082 DEFPY(show_evpn_access_vlan
,
3083 show_evpn_access_vlan_cmd
,
3084 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3089 "Detailed information\n"
3095 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3098 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3100 zebra_evpn_acc_vl_show(vty
, uj
);
3106 DEFUN (show_evpn_vni
,
3108 "show evpn vni [json]",
3111 "VxLAN Network Identifier\n"
3114 struct zebra_vrf
*zvrf
;
3115 bool uj
= use_json(argc
, argv
);
3117 zvrf
= zebra_vrf_get_evpn();
3118 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3122 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3123 "show evpn vni detail [json]",
3126 "VxLAN Network Identifier\n"
3127 "Detailed Information On Each VNI\n"
3130 struct zebra_vrf
*zvrf
;
3131 bool uj
= use_json(argc
, argv
);
3133 zvrf
= zebra_vrf_get_evpn();
3134 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3138 DEFUN (show_evpn_vni_vni
,
3139 show_evpn_vni_vni_cmd
,
3140 "show evpn vni " CMD_VNI_RANGE
"[json]",
3143 "VxLAN Network Identifier\n"
3147 struct zebra_vrf
*zvrf
;
3149 bool uj
= use_json(argc
, argv
);
3151 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3152 zvrf
= zebra_vrf_get_evpn();
3153 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3157 DEFUN (show_evpn_rmac_vni_mac
,
3158 show_evpn_rmac_vni_mac_cmd
,
3159 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3166 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3171 bool uj
= use_json(argc
, argv
);
3173 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3174 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3175 vty_out(vty
, "%% Malformed MAC address\n");
3178 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3182 DEFUN (show_evpn_rmac_vni
,
3183 show_evpn_rmac_vni_cmd
,
3184 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3193 bool uj
= use_json(argc
, argv
);
3195 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3196 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3201 DEFUN (show_evpn_rmac_vni_all
,
3202 show_evpn_rmac_vni_all_cmd
,
3203 "show evpn rmac vni all [json]",
3211 bool uj
= use_json(argc
, argv
);
3213 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3218 DEFUN (show_evpn_nh_vni_ip
,
3219 show_evpn_nh_vni_ip_cmd
,
3220 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3227 "Host address (ipv4 or ipv6)\n"
3232 bool uj
= use_json(argc
, argv
);
3234 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3235 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3237 vty_out(vty
, "%% Malformed Neighbor address\n");
3240 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3245 DEFUN (show_evpn_nh_vni
,
3246 show_evpn_nh_vni_cmd
,
3247 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3256 bool uj
= use_json(argc
, argv
);
3258 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3259 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3264 DEFUN (show_evpn_nh_vni_all
,
3265 show_evpn_nh_vni_all_cmd
,
3266 "show evpn next-hops vni all [json]",
3274 bool uj
= use_json(argc
, argv
);
3276 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3281 DEFUN (show_evpn_mac_vni
,
3282 show_evpn_mac_vni_cmd
,
3283 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3287 "VxLAN Network Identifier\n"
3291 struct zebra_vrf
*zvrf
;
3293 bool uj
= use_json(argc
, argv
);
3295 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3296 zvrf
= zebra_vrf_get_evpn();
3297 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3301 DEFUN (show_evpn_mac_vni_all
,
3302 show_evpn_mac_vni_all_cmd
,
3303 "show evpn mac vni all [json]",
3307 "VxLAN Network Identifier\n"
3311 struct zebra_vrf
*zvrf
;
3312 bool uj
= use_json(argc
, argv
);
3314 zvrf
= zebra_vrf_get_evpn();
3315 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3319 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3320 "show evpn mac vni all detail [json]",
3324 "VxLAN Network Identifier\n"
3326 "Detailed Information On Each VNI MAC\n"
3329 struct zebra_vrf
*zvrf
;
3330 bool uj
= use_json(argc
, argv
);
3332 zvrf
= zebra_vrf_get_evpn();
3333 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3337 DEFUN (show_evpn_mac_vni_all_vtep
,
3338 show_evpn_mac_vni_all_vtep_cmd
,
3339 "show evpn mac vni all vtep A.B.C.D [json]",
3343 "VxLAN Network Identifier\n"
3346 "Remote VTEP IP address\n"
3349 struct zebra_vrf
*zvrf
;
3350 struct in_addr vtep_ip
;
3351 bool uj
= use_json(argc
, argv
);
3353 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3355 vty_out(vty
, "%% Malformed VTEP IP address\n");
3358 zvrf
= zebra_vrf_get_evpn();
3359 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3365 DEFUN (show_evpn_mac_vni_mac
,
3366 show_evpn_mac_vni_mac_cmd
,
3367 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3371 "VxLAN Network Identifier\n"
3374 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3378 struct zebra_vrf
*zvrf
;
3381 bool uj
= use_json(argc
, argv
);
3383 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3384 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3385 vty_out(vty
, "%% Malformed MAC address\n");
3388 zvrf
= zebra_vrf_get_evpn();
3389 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3393 DEFUN (show_evpn_mac_vni_vtep
,
3394 show_evpn_mac_vni_vtep_cmd
,
3395 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3399 "VxLAN Network Identifier\n"
3402 "Remote VTEP IP address\n"
3405 struct zebra_vrf
*zvrf
;
3407 struct in_addr vtep_ip
;
3408 bool uj
= use_json(argc
, argv
);
3410 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3411 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3413 vty_out(vty
, "%% Malformed VTEP IP address\n");
3417 zvrf
= zebra_vrf_get_evpn();
3418 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3422 DEFPY (show_evpn_mac_vni_all_dad
,
3423 show_evpn_mac_vni_all_dad_cmd
,
3424 "show evpn mac vni all duplicate [json]",
3428 "VxLAN Network Identifier\n"
3430 "Duplicate address list\n"
3433 struct zebra_vrf
*zvrf
;
3434 bool uj
= use_json(argc
, argv
);
3436 zvrf
= zebra_vrf_get_evpn();
3437 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3442 DEFPY (show_evpn_mac_vni_dad
,
3443 show_evpn_mac_vni_dad_cmd
,
3444 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3448 "VxLAN Network Identifier\n"
3450 "Duplicate address list\n"
3453 struct zebra_vrf
*zvrf
;
3454 bool uj
= use_json(argc
, argv
);
3456 zvrf
= zebra_vrf_get_evpn();
3458 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3463 DEFPY (show_evpn_neigh_vni_dad
,
3464 show_evpn_neigh_vni_dad_cmd
,
3465 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3468 "ARP and ND cache\n"
3469 "VxLAN Network Identifier\n"
3471 "Duplicate address list\n"
3474 struct zebra_vrf
*zvrf
;
3475 bool uj
= use_json(argc
, argv
);
3477 zvrf
= zebra_vrf_get_evpn();
3478 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3482 DEFPY (show_evpn_neigh_vni_all_dad
,
3483 show_evpn_neigh_vni_all_dad_cmd
,
3484 "show evpn arp-cache vni all duplicate [json]",
3487 "ARP and ND cache\n"
3488 "VxLAN Network Identifier\n"
3490 "Duplicate address list\n"
3493 struct zebra_vrf
*zvrf
;
3494 bool uj
= use_json(argc
, argv
);
3496 zvrf
= zebra_vrf_get_evpn();
3497 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3502 DEFUN (show_evpn_neigh_vni
,
3503 show_evpn_neigh_vni_cmd
,
3504 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3507 "ARP and ND cache\n"
3508 "VxLAN Network Identifier\n"
3512 struct zebra_vrf
*zvrf
;
3514 bool uj
= use_json(argc
, argv
);
3516 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3517 zvrf
= zebra_vrf_get_evpn();
3518 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3522 DEFUN (show_evpn_neigh_vni_all
,
3523 show_evpn_neigh_vni_all_cmd
,
3524 "show evpn arp-cache vni all [json]",
3527 "ARP and ND cache\n"
3528 "VxLAN Network Identifier\n"
3532 struct zebra_vrf
*zvrf
;
3533 bool uj
= use_json(argc
, argv
);
3535 zvrf
= zebra_vrf_get_evpn();
3536 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3540 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3541 "show evpn arp-cache vni all detail [json]",
3544 "ARP and ND cache\n"
3545 "VxLAN Network Identifier\n"
3547 "Neighbor details for all vnis in detail\n" JSON_STR
)
3549 struct zebra_vrf
*zvrf
;
3550 bool uj
= use_json(argc
, argv
);
3552 zvrf
= zebra_vrf_get_evpn();
3553 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3557 DEFUN (show_evpn_neigh_vni_neigh
,
3558 show_evpn_neigh_vni_neigh_cmd
,
3559 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3562 "ARP and ND cache\n"
3563 "VxLAN Network Identifier\n"
3566 "Neighbor address (IPv4 or IPv6 address)\n"
3569 struct zebra_vrf
*zvrf
;
3572 bool uj
= use_json(argc
, argv
);
3574 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3575 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3577 vty_out(vty
, "%% Malformed Neighbor address\n");
3580 zvrf
= zebra_vrf_get_evpn();
3581 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3585 DEFUN (show_evpn_neigh_vni_vtep
,
3586 show_evpn_neigh_vni_vtep_cmd
,
3587 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3590 "ARP and ND cache\n"
3591 "VxLAN Network Identifier\n"
3594 "Remote VTEP IP address\n"
3597 struct zebra_vrf
*zvrf
;
3599 struct in_addr vtep_ip
;
3600 bool uj
= use_json(argc
, argv
);
3602 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3603 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3605 vty_out(vty
, "%% Malformed VTEP IP address\n");
3609 zvrf
= zebra_vrf_get_evpn();
3610 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3614 /* policy routing contexts */
3615 DEFUN (show_pbr_ipset
,
3617 "show pbr ipset [WORD]",
3619 "Policy-Based Routing\n"
3620 "IPset Context information\n"
3621 "IPset Name information\n")
3625 found
= argv_find(argv
, argc
, "WORD", &idx
);
3627 zebra_pbr_show_ipset_list(vty
, NULL
);
3629 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3633 /* policy routing contexts */
3634 DEFUN (show_pbr_iptable
,
3635 show_pbr_iptable_cmd
,
3636 "show pbr iptable [WORD]",
3638 "Policy-Based Routing\n"
3639 "IPtable Context information\n"
3640 "IPtable Name information\n")
3645 found
= argv_find(argv
, argc
, "WORD", &idx
);
3647 zebra_pbr_show_iptable(vty
, NULL
);
3649 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3653 /* policy routing contexts */
3654 DEFPY (show_pbr_rule
,
3658 "Policy-Based Routing\n"
3661 zebra_pbr_show_rule(vty
);
3665 DEFPY (pbr_nexthop_resolve
,
3666 pbr_nexthop_resolve_cmd
,
3667 "[no$no] pbr nexthop-resolve",
3669 "Policy Based Routing\n"
3670 "Resolve nexthop for dataplane programming\n")
3672 zebra_pbr_expand_action_update(!no
);
3676 DEFPY (clear_evpn_dup_addr
,
3677 clear_evpn_dup_addr_cmd
,
3678 "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>]>",
3681 "Duplicate address \n"
3682 "VxLAN Network Identifier\n"
3686 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3691 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3692 int ret
= CMD_SUCCESS
;
3694 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3695 *yang_dup_mac
= NULL
;
3700 yang_dup
= yang_data_new(
3701 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3704 yang_dup
= yang_data_new_uint32(
3705 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3707 if (!is_zero_mac(&mac
->eth_addr
)) {
3708 yang_dup_mac
= yang_data_new_mac(
3709 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3712 listnode_add(input
, yang_dup_mac
);
3714 if (sockunion_family(ip
) == AF_INET
) {
3715 host_ip
.ipa_type
= IPADDR_V4
;
3716 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3718 host_ip
.ipa_type
= IPADDR_V6
;
3719 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3720 sizeof(struct in6_addr
));
3723 yang_dup_ip
= yang_data_new_ip(
3724 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3728 listnode_add(input
, yang_dup_ip
);
3733 listnode_add(input
, yang_dup
);
3734 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3738 list_delete(&input
);
3743 /* Static ip route configuration write function. */
3744 static int zebra_ip_config(struct vty
*vty
)
3748 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3753 DEFUN (ip_zebra_import_table_distance
,
3754 ip_zebra_import_table_distance_cmd
,
3755 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3757 "import routes from non-main kernel table\n"
3758 "kernel routing table id\n"
3759 "Distance for imported routes\n"
3760 "Default distance value\n"
3761 "route-map for filtering\n"
3764 uint32_t table_id
= 0;
3766 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3767 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3769 strmatch(argv
[argc
- 2]->text
, "route-map")
3770 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3774 if (argc
== 7 || (argc
== 5 && !rmap
))
3775 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3777 if (!is_zebra_valid_kernel_table(table_id
)) {
3779 "Invalid routing table ID, %d. Must be in range 1-252\n",
3782 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3786 if (is_zebra_main_routing_table(table_id
)) {
3788 "Invalid routing table ID, %d. Must be non-default table\n",
3791 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3795 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3798 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3803 DEFUN_HIDDEN (zebra_packet_process
,
3804 zebra_packet_process_cmd
,
3805 "zebra zapi-packets (1-10000)",
3808 "Number of packets to process before relinquishing thread\n")
3810 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3812 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3813 memory_order_relaxed
);
3818 DEFUN_HIDDEN (no_zebra_packet_process
,
3819 no_zebra_packet_process_cmd
,
3820 "no zebra zapi-packets [(1-10000)]",
3824 "Number of packets to process before relinquishing thread\n")
3826 atomic_store_explicit(&zrouter
.packets_to_process
,
3827 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3828 memory_order_relaxed
);
3833 DEFUN_HIDDEN (zebra_workqueue_timer
,
3834 zebra_workqueue_timer_cmd
,
3835 "zebra work-queue (0-10000)",
3838 "Time in milliseconds\n")
3840 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3841 zrouter
.ribq
->spec
.hold
= timer
;
3846 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3847 no_zebra_workqueue_timer_cmd
,
3848 "no zebra work-queue [(0-10000)]",
3852 "Time in milliseconds\n")
3854 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3859 DEFUN (no_ip_zebra_import_table
,
3860 no_ip_zebra_import_table_cmd
,
3861 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3864 "import routes from non-main kernel table\n"
3865 "kernel routing table id\n"
3866 "Distance for imported routes\n"
3867 "Default distance value\n"
3868 "route-map for filtering\n"
3871 uint32_t table_id
= 0;
3872 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3874 if (!is_zebra_valid_kernel_table(table_id
)) {
3876 "Invalid routing table ID. Must be in range 1-252\n");
3880 if (is_zebra_main_routing_table(table_id
)) {
3882 "Invalid routing table ID, %d. Must be non-default table\n",
3887 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3890 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3893 DEFPY (zebra_nexthop_group_keep
,
3894 zebra_nexthop_group_keep_cmd
,
3895 "[no] zebra nexthop-group keep (1-3600)",
3899 "How long to keep\n"
3900 "Time in seconds from 1-3600\n")
3903 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3905 zrouter
.nhg_keep
= keep
;
3910 static int config_write_protocol(struct vty
*vty
)
3912 if (zrouter
.allow_delete
)
3913 vty_out(vty
, "allow-external-route-update\n");
3915 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3916 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3918 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3919 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3921 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3922 vty_out(vty
, "zebra zapi-packets %u\n",
3923 zrouter
.packets_to_process
);
3925 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3927 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3928 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3929 ipv4_multicast_mode
== MCAST_URIB_ONLY
3931 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3933 : ipv4_multicast_mode
3934 == MCAST_MIX_MRIB_FIRST
3936 : ipv4_multicast_mode
3937 == MCAST_MIX_DISTANCE
3941 /* Include dataplane info */
3942 dplane_config_write_helper(vty
);
3944 zebra_evpn_mh_config_write(vty
);
3946 zebra_pbr_config_write(vty
);
3948 /* Include nexthop-group config */
3949 if (!zebra_nhg_kernel_nexthops_enabled())
3950 vty_out(vty
, "no zebra nexthop kernel enable\n");
3952 if (zebra_nhg_proto_nexthops_only())
3953 vty_out(vty
, "zebra nexthop proto only\n");
3955 if (!zebra_nhg_recursive_use_backups())
3956 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3958 if (rnh_get_hide_backups())
3959 vty_out(vty
, "ip nht hide-backup-events\n");
3962 /* Include netlink info */
3963 netlink_config_write_helper(vty
);
3964 #endif /* HAVE_NETLINK */
3976 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3979 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3980 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3981 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3982 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3983 ttable_add_row(table
, "v6 Forwarding|%s",
3984 ipforward_ipv6() ? "On" : "Off");
3985 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3986 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3987 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3991 if (!vrf_is_backend_netns())
3992 ttable_add_row(table
, "VRF|l3mdev Available");
3994 ttable_add_row(table
, "VRF|Namespaces");
3996 ttable_add_row(table
, "VRF|Not Available");
3999 ttable_add_row(table
, "ASIC offload|%s",
4000 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4002 ttable_add_row(table
, "RA|%s",
4003 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4004 ttable_add_row(table
, "RFC 5549|%s",
4005 rtadv_get_interfaces_configured_from_bgp()
4007 : "BGP is not using");
4009 ttable_add_row(table
, "Kernel NHG|%s",
4010 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4012 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4013 zrouter
.allow_delete
? "Yes" : "No");
4014 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4015 zrouter
.all_linkdownv4
? "On" : "Off");
4016 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4017 zrouter
.default_linkdownv4
? "On" : "Off");
4018 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4019 zrouter
.all_linkdownv6
? "On" : "Off");
4020 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4021 zrouter
.default_linkdownv6
? "On" : "Off");
4023 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4024 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4025 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4026 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4027 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4028 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4029 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4030 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4032 out
= ttable_dump(table
, "\n");
4033 vty_out(vty
, "%s\n", out
);
4034 XFREE(MTYPE_TMP
, out
);
4037 " Route Route Neighbor LSP LSP\n");
4039 "VRF Installs Removals Updates Installs Removals\n");
4041 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4042 struct zebra_vrf
*zvrf
= vrf
->info
;
4044 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4045 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4046 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4047 zvrf
->lsp_removals
);
4053 DEFUN (ip_forwarding
,
4057 "Turn on IP forwarding\n")
4063 ret
= ipforward_on();
4066 vty_out(vty
, "Can't turn on IP forwarding\n");
4067 return CMD_WARNING_CONFIG_FAILED
;
4073 DEFUN (no_ip_forwarding
,
4074 no_ip_forwarding_cmd
,
4078 "Turn off IP forwarding\n")
4084 ret
= ipforward_off();
4087 vty_out(vty
, "Can't turn off IP forwarding\n");
4088 return CMD_WARNING_CONFIG_FAILED
;
4094 /* Only display ip forwarding is enabled or not. */
4095 DEFUN (show_ip_forwarding
,
4096 show_ip_forwarding_cmd
,
4097 "show ip forwarding",
4100 "IP forwarding status\n")
4107 vty_out(vty
, "IP forwarding is off\n");
4109 vty_out(vty
, "IP forwarding is on\n");
4113 /* Only display ipv6 forwarding is enabled or not. */
4114 DEFUN (show_ipv6_forwarding
,
4115 show_ipv6_forwarding_cmd
,
4116 "show ipv6 forwarding",
4118 "IPv6 information\n"
4119 "Forwarding status\n")
4123 ret
= ipforward_ipv6();
4127 vty_out(vty
, "ipv6 forwarding is unknown\n");
4130 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4133 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4136 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4142 DEFUN (ipv6_forwarding
,
4143 ipv6_forwarding_cmd
,
4146 "Turn on IPv6 forwarding\n")
4150 ret
= ipforward_ipv6();
4152 ret
= ipforward_ipv6_on();
4155 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4156 return CMD_WARNING_CONFIG_FAILED
;
4162 DEFUN (no_ipv6_forwarding
,
4163 no_ipv6_forwarding_cmd
,
4164 "no ipv6 forwarding",
4167 "Turn off IPv6 forwarding\n")
4171 ret
= ipforward_ipv6();
4173 ret
= ipforward_ipv6_off();
4176 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4177 return CMD_WARNING_CONFIG_FAILED
;
4183 /* Display dataplane info */
4184 DEFUN (show_dataplane
,
4186 "show zebra dplane [detailed]",
4189 "Zebra dataplane information\n"
4190 "Detailed output\n")
4193 bool detailed
= false;
4195 if (argv_find(argv
, argc
, "detailed", &idx
))
4198 return dplane_show_helper(vty
, detailed
);
4201 /* Display dataplane providers info */
4202 DEFUN (show_dataplane_providers
,
4203 show_dataplane_providers_cmd
,
4204 "show zebra dplane providers [detailed]",
4207 "Zebra dataplane information\n"
4208 "Zebra dataplane provider information\n"
4209 "Detailed output\n")
4212 bool detailed
= false;
4214 if (argv_find(argv
, argc
, "detailed", &idx
))
4217 return dplane_show_provs_helper(vty
, detailed
);
4220 /* Configure dataplane incoming queue limit */
4221 DEFUN (zebra_dplane_queue_limit
,
4222 zebra_dplane_queue_limit_cmd
,
4223 "zebra dplane limit (0-10000)",
4226 "Limit incoming queued updates\n"
4227 "Number of queued updates\n")
4231 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4233 dplane_set_in_queue_limit(limit
, true);
4238 /* Reset dataplane queue limit to default value */
4239 DEFUN (no_zebra_dplane_queue_limit
,
4240 no_zebra_dplane_queue_limit_cmd
,
4241 "no zebra dplane limit [(0-10000)]",
4245 "Limit incoming queued updates\n"
4246 "Number of queued updates\n")
4248 dplane_set_in_queue_limit(0, false);
4253 DEFUN (zebra_show_routing_tables_summary
,
4254 zebra_show_routing_tables_summary_cmd
,
4255 "show zebra router table summary",
4258 "The Zebra Router Information\n"
4259 "Table Information about this Zebra Router\n"
4260 "Summary Information\n")
4262 zebra_router_show_table_summary(vty
);
4267 /* Table configuration write function. */
4268 static int config_write_table(struct vty
*vty
)
4273 /* IPForwarding configuration write function. */
4274 static int config_write_forwarding(struct vty
*vty
)
4277 vty_out(vty
, "no ip forwarding\n");
4278 if (!ipforward_ipv6())
4279 vty_out(vty
, "no ipv6 forwarding\n");
4280 vty_out(vty
, "!\n");
4284 DEFUN_HIDDEN (show_frr
,
4290 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4291 vty_out(vty
, ".............................7777:..............................................\n");
4292 vty_out(vty
, ".............................777777,............................................\n");
4293 vty_out(vty
, "... .........................77777777,..........................................\n");
4294 vty_out(vty
, "............................=7777777777:........................................\n");
4295 vty_out(vty
, "........................:7777777777777777,......................................\n");
4296 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4297 vty_out(vty
, "...................I7777777777+.................................................\n");
4298 vty_out(vty
, "................,777777777?............ .......................................\n");
4299 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4300 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4301 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4302 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4303 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4304 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4305 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4306 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4307 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4308 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4309 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4310 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4311 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4312 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4313 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4314 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4315 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4316 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4317 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4318 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4319 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4320 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4321 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4322 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4323 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4324 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4325 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4326 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4327 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4328 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4329 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4330 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4331 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4332 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4333 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4334 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4335 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4336 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4337 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4338 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4339 vty_out(vty
, "................................~77777777...............=777777.................\n");
4340 vty_out(vty
, ".....................................:=?I................~777777................\n");
4341 vty_out(vty
, "..........................................................:777777,..............\n");
4342 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4348 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4349 zebra_kernel_netlink_batch_tx_buf_cmd
,
4350 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4352 "Zebra kernel interface\n"
4353 "Set Netlink parameters\n"
4354 "Set batch buffer size and send threshold\n"
4355 "Size of the buffer\n"
4358 uint32_t bufsize
= 0, threshold
= 0;
4360 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4361 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4363 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4368 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4369 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4370 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4372 "Zebra kernel interface\n"
4373 "Set Netlink parameters\n"
4374 "Set batch buffer size and send threshold\n"
4375 "Size of the buffer\n"
4378 netlink_set_batch_buffer_size(0, 0, false);
4383 DEFPY (zebra_protodown_bit
,
4384 zebra_protodown_bit_cmd
,
4385 "zebra protodown reason-bit (0-31)$bit",
4387 "Protodown Configuration\n"
4388 "Reason Bit used in the kernel for application\n"
4389 "Reason Bit range\n")
4391 if_netlink_set_frr_protodown_r_bit(bit
);
4395 DEFPY (no_zebra_protodown_bit
,
4396 no_zebra_protodown_bit_cmd
,
4397 "no zebra protodown reason-bit [(0-31)$bit]",
4400 "Protodown Configuration\n"
4401 "Reason Bit used in the kernel for setting protodown\n"
4402 "Reason Bit Range\n")
4404 if_netlink_unset_frr_protodown_r_bit();
4408 #endif /* HAVE_NETLINK */
4410 DEFUN(ip_table_range
, ip_table_range_cmd
,
4411 "[no] ip table range (1-4294967295) (1-4294967295)",
4413 "table configuration\n"
4414 "Configure table range\n"
4415 "Start Routing Table\n"
4416 "End Routing Table\n")
4418 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4423 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4425 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4429 if (strmatch(argv
[0]->text
, "no"))
4430 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4432 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4435 #ifdef HAVE_SCRIPTING
4437 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4438 "zebra on-rib-process script SCRIPT",
4440 "on_rib_process_dplane_results hook call\n"
4442 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4445 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4448 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4449 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4451 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4452 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4457 #endif /* HAVE_SCRIPTING */
4459 /* IP node for static routes. */
4460 static int zebra_ip_config(struct vty
*vty
);
4461 static struct cmd_node ip_node
= {
4462 .name
= "static ip",
4465 .config_write
= zebra_ip_config
,
4467 static int config_write_protocol(struct vty
*vty
);
4468 static struct cmd_node protocol_node
= {
4470 .node
= PROTOCOL_NODE
,
4472 .config_write
= config_write_protocol
,
4474 /* table node for routing tables. */
4475 static int config_write_table(struct vty
*vty
);
4476 static struct cmd_node table_node
= {
4480 .config_write
= config_write_table
,
4482 static int config_write_forwarding(struct vty
*vty
);
4483 static struct cmd_node forwarding_node
= {
4484 .name
= "forwarding",
4485 .node
= FORWARDING_NODE
,
4487 .config_write
= config_write_forwarding
,
4491 void zebra_vty_init(void)
4493 /* Install configuration write function. */
4494 install_node(&table_node
);
4495 install_node(&forwarding_node
);
4497 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4498 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4499 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4500 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4502 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4503 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4504 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4507 zebra_route_map_init();
4509 install_node(&ip_node
);
4510 install_node(&protocol_node
);
4512 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4513 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4515 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4516 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4518 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4519 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4520 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4521 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4522 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4523 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4524 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4525 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4526 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4527 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4529 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4530 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4532 install_element(VIEW_NODE
, &show_vrf_cmd
);
4533 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4534 install_element(VIEW_NODE
, &show_route_cmd
);
4535 install_element(VIEW_NODE
, &show_ro_cmd
);
4536 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4537 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4538 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4540 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4541 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4543 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4544 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4545 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4546 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4547 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4548 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4549 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4550 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4551 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4553 install_element(VIEW_NODE
, &show_frr_cmd
);
4554 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4555 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4556 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4557 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4558 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4574 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4575 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4576 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4577 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4578 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4579 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4580 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4581 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4582 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4583 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4585 install_element(VIEW_NODE
, &show_neigh_cmd
);
4587 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4588 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4589 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4590 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4591 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4593 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4594 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4595 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4596 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4597 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4598 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4599 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4600 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4602 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4603 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4604 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4605 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4607 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4608 install_element(VRF_NODE
, &ip_table_range_cmd
);
4611 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4612 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4613 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4614 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4615 #endif /* HAVE_NETLINK */
4617 #ifdef HAVE_SCRIPTING
4618 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4619 #endif /* HAVE_SCRIPTING */
4621 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);