2 * Copyright (C) 2002 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "srcdest_table.h"
36 #include "termtable.h"
38 #include "zebra/zebra_router.h"
39 #include "zebra/zserv.h"
40 #include "zebra/zebra_vrf.h"
41 #include "zebra/zebra_mpls.h"
42 #include "zebra/zebra_rnh.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/zebra_routemap.h"
46 #include "lib/route_opaque.h"
47 #include "zebra/zebra_vxlan.h"
48 #include "zebra/zebra_evpn_mh.h"
49 #include "zebra/zebra_vty_clippy.c"
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_pbr.h"
55 #include "zebra/zebra_nhg.h"
56 #include "zebra/zebra_evpn_mh.h"
57 #include "zebra/interface.h"
58 #include "northbound_cli.h"
59 #include "zebra/zebra_nb.h"
60 #include "zebra/kernel_netlink.h"
61 #include "zebra/if_netlink.h"
62 #include "zebra/table_manager.h"
63 #include "zebra/zebra_script.h"
64 #include "zebra/rtadv.h"
65 #include "zebra/zebra_neigh.h"
67 /* context to manage dumps in multiple tables or vrfs */
68 struct route_show_ctx
{
69 bool multi
; /* dump multiple tables or vrf */
70 bool header_done
; /* common header already displayed */
73 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
74 safi_t safi
, bool use_fib
, bool use_json
,
76 const struct prefix
*longer_prefix_p
,
77 bool supernets_only
, int type
,
78 unsigned short ospf_instance_id
, uint32_t tableid
,
79 bool show_ng
, struct route_show_ctx
*ctx
);
80 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
81 int mcast
, bool use_fib
, bool show_ng
);
82 static void vty_show_ip_route_summary(struct vty
*vty
,
83 struct route_table
*table
, bool use_json
);
84 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
85 struct route_table
*table
,
87 /* Helper api to format a nexthop in the 'detailed' output path. */
88 static void show_nexthop_detail_helper(struct vty
*vty
,
89 const struct route_entry
*re
,
90 const struct nexthop
*nexthop
,
93 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
94 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
95 struct route_entry
*re
, unsigned int num
);
97 DEFUN (ip_multicast_mode
,
98 ip_multicast_mode_cmd
,
99 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
101 "Multicast options\n"
102 "RPF lookup behavior\n"
103 "Lookup in unicast RIB only\n"
104 "Lookup in multicast RIB only\n"
105 "Try multicast RIB first, fall back to unicast RIB\n"
106 "Lookup both, use entry with lower distance\n"
107 "Lookup both, use entry with longer prefix\n")
109 char *mode
= argv
[3]->text
;
111 if (strmatch(mode
, "urib-only"))
112 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
113 else if (strmatch(mode
, "mrib-only"))
114 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
115 else if (strmatch(mode
, "mrib-then-urib"))
116 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
117 else if (strmatch(mode
, "lower-distance"))
118 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
119 else if (strmatch(mode
, "longer-prefix"))
120 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
122 vty_out(vty
, "Invalid mode specified\n");
123 return CMD_WARNING_CONFIG_FAILED
;
129 DEFUN (no_ip_multicast_mode
,
130 no_ip_multicast_mode_cmd
,
131 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
134 "Multicast options\n"
135 "RPF lookup behavior\n"
136 "Lookup in unicast RIB only\n"
137 "Lookup in multicast RIB only\n"
138 "Try multicast RIB first, fall back to unicast RIB\n"
139 "Lookup both, use entry with lower distance\n"
140 "Lookup both, use entry with longer prefix\n")
142 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
149 "show ip rpf [json]",
152 "Display RPF information for multicast source\n"
155 bool uj
= use_json(argc
, argv
);
156 struct route_show_ctx ctx
= {
160 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
161 false, uj
, 0, NULL
, false, 0, 0, 0, false,
165 DEFUN (show_ip_rpf_addr
,
166 show_ip_rpf_addr_cmd
,
167 "show ip rpf A.B.C.D",
170 "Display RPF information for multicast source\n"
171 "IP multicast source address (e.g. 10.0.0.0)\n")
175 struct route_node
*rn
;
176 struct route_entry
*re
;
179 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
181 vty_out(vty
, "%% Malformed address\n");
185 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
188 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
190 vty_out(vty
, "%% No match for RPF lookup\n");
195 static char re_status_output_char(const struct route_entry
*re
,
196 const struct nexthop
*nhop
,
199 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
203 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
204 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
205 /* More-specific test for 'fib' output */
207 star_p
= !!CHECK_FLAG(nhop
->flags
,
213 if (zrouter
.asic_offloaded
&&
214 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
217 if (zrouter
.asic_offloaded
218 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
221 if (zrouter
.asic_offloaded
222 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
225 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
234 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
235 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
241 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
248 * Show backup nexthop info, in the 'detailed' output path
250 static void show_nh_backup_helper(struct vty
*vty
,
251 const struct route_entry
*re
,
252 const struct nexthop
*nexthop
)
254 const struct nexthop
*start
, *backup
, *temp
;
257 /* Double-check that there _is_ a backup */
258 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
259 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
260 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
263 /* Locate the backup nexthop(s) */
264 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
265 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
266 /* Format the backup(s) (indented) */
268 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
269 backup
= backup
->next
;
274 /* It's possible for backups to be recursive too,
275 * so walk the recursive resolution list if present.
280 show_nexthop_detail_helper(vty
, re
, backup
,
284 if (backup
->resolved
&& temp
== backup
)
285 backup
= backup
->resolved
;
287 backup
= nexthop_next(backup
);
289 if (backup
== temp
->next
)
297 * Helper api to format output for a nexthop, used in the 'detailed'
300 static void show_nexthop_detail_helper(struct vty
*vty
,
301 const struct route_entry
*re
,
302 const struct nexthop
*nexthop
,
306 char buf
[MPLS_LABEL_STRLEN
];
311 nexthop
->rparent
? " " : "");
313 vty_out(vty
, " %c%s",
314 re_status_output_char(re
, nexthop
, false),
315 nexthop
->rparent
? " " : "");
317 switch (nexthop
->type
) {
318 case NEXTHOP_TYPE_IPV4
:
319 case NEXTHOP_TYPE_IPV4_IFINDEX
:
320 vty_out(vty
, " %pI4",
321 &nexthop
->gate
.ipv4
);
322 if (nexthop
->ifindex
)
323 vty_out(vty
, ", via %s",
328 case NEXTHOP_TYPE_IPV6
:
329 case NEXTHOP_TYPE_IPV6_IFINDEX
:
331 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
333 if (nexthop
->ifindex
)
334 vty_out(vty
, ", via %s",
340 case NEXTHOP_TYPE_IFINDEX
:
341 vty_out(vty
, " directly connected, %s",
342 ifindex2ifname(nexthop
->ifindex
,
345 case NEXTHOP_TYPE_BLACKHOLE
:
346 vty_out(vty
, " unreachable");
347 switch (nexthop
->bh_type
) {
348 case BLACKHOLE_REJECT
:
349 vty_out(vty
, " (ICMP unreachable)");
351 case BLACKHOLE_ADMINPROHIB
:
353 " (ICMP admin-prohibited)");
356 vty_out(vty
, " (blackhole)");
358 case BLACKHOLE_UNSPEC
:
364 if (re
->vrf_id
!= nexthop
->vrf_id
) {
365 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
367 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
370 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
371 vty_out(vty
, " (duplicate nexthop removed)");
373 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
374 vty_out(vty
, " inactive");
376 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
377 vty_out(vty
, " onlink");
379 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
380 vty_out(vty
, " linkdown");
382 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
383 vty_out(vty
, " (recursive)");
385 /* Source specified? */
386 switch (nexthop
->type
) {
387 case NEXTHOP_TYPE_IPV4
:
388 case NEXTHOP_TYPE_IPV4_IFINDEX
:
389 if (nexthop
->src
.ipv4
.s_addr
) {
390 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
391 addrstr
, sizeof(addrstr
)))
392 vty_out(vty
, ", src %s",
397 case NEXTHOP_TYPE_IPV6
:
398 case NEXTHOP_TYPE_IPV6_IFINDEX
:
399 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
401 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
402 addrstr
, sizeof(addrstr
)))
403 vty_out(vty
, ", src %s",
408 case NEXTHOP_TYPE_IFINDEX
:
409 case NEXTHOP_TYPE_BLACKHOLE
:
414 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
416 /* Label information */
417 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
418 vty_out(vty
, ", label %s",
419 mpls_label2str(nexthop
->nh_label
->num_labels
,
420 nexthop
->nh_label
->label
, buf
,
421 sizeof(buf
), 1 /*pretty*/));
425 vty_out(vty
, ", weight %u", nexthop
->weight
);
427 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
428 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
430 for (i
= 1; i
< nexthop
->backup_num
; i
++)
431 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
435 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
436 struct json_object
*json
)
438 struct bgp_zebra_opaque bzo
= {};
439 struct ospf_zebra_opaque ozo
= {};
445 case ZEBRA_ROUTE_SHARP
:
447 json_object_string_add(json
, "opaque",
448 (char *)re
->opaque
->data
);
450 vty_out(vty
, " Opaque Data: %s",
451 (char *)re
->opaque
->data
);
454 case ZEBRA_ROUTE_BGP
:
455 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
458 json_object_string_add(json
, "asPath", bzo
.aspath
);
459 json_object_string_add(json
, "communities",
461 json_object_string_add(json
, "largeCommunities",
463 json_object_string_add(json
, "selectionReason",
464 bzo
.selection_reason
);
466 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
468 if (bzo
.community
[0] != '\0')
469 vty_out(vty
, " Communities : %s\n",
472 if (bzo
.lcommunity
[0] != '\0')
473 vty_out(vty
, " Large-Communities: %s\n",
476 vty_out(vty
, " Selection reason : %s\n",
477 bzo
.selection_reason
);
480 case ZEBRA_ROUTE_OSPF
:
481 case ZEBRA_ROUTE_OSPF6
:
482 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
485 json_object_string_add(json
, "ospfPathType",
487 if (ozo
.area_id
[0] != '\0')
488 json_object_string_add(json
, "ospfAreaId",
490 if (ozo
.tag
[0] != '\0')
491 json_object_string_add(json
, "ospfTag",
494 vty_out(vty
, " OSPF path type : %s\n",
496 if (ozo
.area_id
[0] != '\0')
497 vty_out(vty
, " OSPF area ID : %s\n",
499 if (ozo
.tag
[0] != '\0')
500 vty_out(vty
, " OSPF tag : %s\n",
509 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
513 cur
= monotime(NULL
);
516 frrtime_to_interval(cur
, buf
, bufsize
);
519 /* New RIB. Detailed information for IPv4 route. */
520 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
521 int mcast
, bool use_fib
, bool show_ng
)
523 struct route_entry
*re
;
524 struct nexthop
*nexthop
;
525 char buf
[SRCDEST2STR_BUFFER
];
526 struct zebra_vrf
*zvrf
;
529 dest
= rib_dest_from_rnode(rn
);
531 RNODE_FOREACH_RE (rn
, re
) {
533 * If re not selected for forwarding, skip re
534 * for "show ip/ipv6 fib <prefix>"
536 if (use_fib
&& re
!= dest
->selected_fib
)
539 const char *mcast_info
= "";
541 struct rib_table_info
*info
=
542 srcdest_rnode_table_info(rn
);
543 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
544 ? " using Multicast RIB"
545 : " using Unicast RIB";
548 vty_out(vty
, "Routing entry for %s%s\n",
549 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
550 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
552 vty_out(vty
, "[%d]", re
->instance
);
554 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
557 vty_out(vty
, ", tag %u", re
->tag
);
558 #if defined(SUPPORT_REALMS)
559 if (re
->tag
> 0 && re
->tag
<= 255)
560 vty_out(vty
, "(realm)");
564 vty_out(vty
, ", mtu %u", re
->mtu
);
565 if (re
->vrf_id
!= VRF_DEFAULT
) {
566 zvrf
= vrf_info_lookup(re
->vrf_id
);
567 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
569 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
570 vty_out(vty
, ", best");
573 uptime2str(re
->uptime
, buf
, sizeof(buf
));
575 vty_out(vty
, " Last update %s ago\n", buf
);
578 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
579 if (re
->nhe_installed_id
!= 0
580 && re
->nhe_id
!= re
->nhe_installed_id
)
582 " Installed Nexthop Group ID: %u\n",
583 re
->nhe_installed_id
);
586 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
587 /* Use helper to format each nexthop */
588 show_nexthop_detail_helper(vty
, re
, nexthop
,
589 false /*not backup*/);
592 /* Include backup(s), if present */
593 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
594 show_nh_backup_helper(vty
, re
, nexthop
);
596 zebra_show_ip_route_opaque(vty
, re
, NULL
);
602 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
603 struct route_entry
*re
, json_object
*json
,
604 bool is_fib
, bool show_ng
)
606 const struct nexthop
*nexthop
;
608 char buf
[SRCDEST2STR_BUFFER
];
609 json_object
*json_nexthops
= NULL
;
610 json_object
*json_nexthop
= NULL
;
611 json_object
*json_route
= NULL
;
612 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
613 const struct nexthop_group
*nhg
;
614 char up_str
[MONOTIME_STRLEN
];
616 bool nhg_from_backup
= false;
618 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
620 /* If showing fib information, use the fib view of the
624 nhg
= rib_get_fib_nhg(re
);
626 nhg
= &(re
->nhe
->nhg
);
629 json_route
= json_object_new_object();
630 json_nexthops
= json_object_new_array();
632 json_object_string_add(json_route
, "prefix",
633 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
634 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
635 json_object_string_add(json_route
, "protocol",
636 zebra_route_string(re
->type
));
639 json_object_int_add(json_route
, "instance",
642 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
643 json_object_string_add(json_route
, "vrfName",
644 vrf_id_to_name(re
->vrf_id
));
646 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
647 json_object_boolean_true_add(json_route
, "selected");
649 if (dest
->selected_fib
== re
)
650 json_object_boolean_true_add(json_route
,
653 json_object_int_add(json_route
, "distance",
655 json_object_int_add(json_route
, "metric", re
->metric
);
657 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
658 json_object_boolean_true_add(json_route
, "installed");
660 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
661 json_object_boolean_true_add(json_route
, "failed");
663 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
664 json_object_boolean_true_add(json_route
, "queued");
666 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
667 json_object_boolean_true_add(json_route
, "trapped");
669 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
670 json_object_boolean_true_add(json_route
, "offloaded");
672 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
673 json_object_boolean_false_add(json_route
, "offloaded");
676 json_object_int_add(json_route
, "tag", re
->tag
);
679 json_object_int_add(json_route
, "table", re
->table
);
681 json_object_int_add(json_route
, "internalStatus",
683 json_object_int_add(json_route
, "internalFlags",
685 json_object_int_add(json_route
, "internalNextHopNum",
686 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
687 json_object_int_add(json_route
, "internalNextHopActiveNum",
688 nexthop_group_active_nexthop_num(
690 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
692 if (re
->nhe_installed_id
!= 0)
693 json_object_int_add(json_route
,
694 "installedNexthopGroupId",
695 re
->nhe_installed_id
);
697 json_object_string_add(json_route
, "uptime", up_str
);
699 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
700 json_nexthop
= json_object_new_object();
701 show_nexthop_json_helper(json_nexthop
,
704 json_object_array_add(json_nexthops
,
708 json_object_object_add(json_route
, "nexthops", json_nexthops
);
710 /* If there are backup nexthops, include them */
712 nhg
= rib_get_fib_backup_nhg(re
);
714 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
716 if (nhg
&& nhg
->nexthop
) {
717 json_nexthops
= json_object_new_array();
719 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
720 json_nexthop
= json_object_new_object();
722 show_nexthop_json_helper(json_nexthop
,
724 json_object_array_add(json_nexthops
,
728 json_object_object_add(json_route
, "backupNexthops",
731 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
733 json_object_array_add(json
, json_route
);
737 /* Prefix information, and first nexthop. If we're showing 'fib',
738 * and there are no installed primary nexthops, see if there are any
739 * backup nexthops and start with those.
741 if (is_fib
&& nhg
->nexthop
== NULL
) {
742 nhg
= rib_get_fib_backup_nhg(re
);
743 nhg_from_backup
= true;
746 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
748 len
+= vty_out(vty
, "[%d]", re
->instance
);
749 if (nhg_from_backup
&& nhg
->nexthop
) {
752 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
753 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
754 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
758 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
759 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
760 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
763 /* Distance and metric display. */
764 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
765 (re
->distance
|| re
->metric
)) ||
766 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
767 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
771 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
773 /* Nexthop information. */
774 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
777 } else if (nhg_from_backup
) {
778 vty_out(vty
, " b%c%*c",
779 re_status_output_char(re
, nexthop
, is_fib
),
780 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
782 vty_out(vty
, " %c%*c",
783 re_status_output_char(re
, nexthop
, is_fib
),
784 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
787 show_route_nexthop_helper(vty
, re
, nexthop
);
788 vty_out(vty
, ", %s\n", up_str
);
791 /* If we only had backup nexthops, we're done */
795 /* Check for backup nexthop info if present */
797 nhg
= rib_get_fib_backup_nhg(re
);
799 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
804 /* Print backup info */
805 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
809 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
811 /* TODO -- it'd be nice to be able to include
812 * the entire list of backups, *and* include the
813 * real installation state.
815 vty_out(vty
, " b%c %*c",
816 (star_p
? '*' : ' '),
817 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
818 show_route_nexthop_helper(vty
, re
, nexthop
);
824 static void vty_show_ip_route_detail_json(struct vty
*vty
,
825 struct route_node
*rn
, bool use_fib
)
827 json_object
*json
= NULL
;
828 json_object
*json_prefix
= NULL
;
829 struct route_entry
*re
;
833 dest
= rib_dest_from_rnode(rn
);
835 json
= json_object_new_object();
836 json_prefix
= json_object_new_array();
838 RNODE_FOREACH_RE (rn
, re
) {
840 * If re not selected for forwarding, skip re
841 * for "show ip/ipv6 fib <prefix> json"
843 if (use_fib
&& re
!= dest
->selected_fib
)
845 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
848 prefix2str(&rn
->p
, buf
, sizeof(buf
));
849 json_object_object_add(json
, buf
, json_prefix
);
853 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
854 struct route_table
*table
, afi_t afi
,
855 bool use_fib
, route_tag_t tag
,
856 const struct prefix
*longer_prefix_p
,
857 bool supernets_only
, int type
,
858 unsigned short ospf_instance_id
, bool use_json
,
859 uint32_t tableid
, bool show_ng
,
860 struct route_show_ctx
*ctx
)
862 struct route_node
*rn
;
863 struct route_entry
*re
;
866 json_object
*json
= NULL
;
867 json_object
*json_prefix
= NULL
;
872 * ctx->multi indicates if we are dumping multiple tables or vrfs.
874 * => display the common header at most once
875 * => add newline at each call except first
876 * => always display the VRF and table
878 * => display the common header if at least one entry is found
879 * => display the VRF and table if specific
883 json
= json_object_new_object();
885 /* Show all routes. */
886 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
887 dest
= rib_dest_from_rnode(rn
);
889 RNODE_FOREACH_RE (rn
, re
) {
890 if (use_fib
&& re
!= dest
->selected_fib
)
893 if (tag
&& re
->tag
!= tag
)
897 && !prefix_match(longer_prefix_p
, &rn
->p
))
900 /* This can only be true when the afi is IPv4 */
901 if (supernets_only
) {
902 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
904 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
907 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
910 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
914 if (type
&& re
->type
!= type
)
918 && (re
->type
!= ZEBRA_ROUTE_OSPF
919 || re
->instance
!= ospf_instance_id
))
924 json_prefix
= json_object_new_array();
926 if (!ctx
->header_done
) {
929 SHOW_ROUTE_V4_HEADER
);
932 SHOW_ROUTE_V6_HEADER
);
934 if (ctx
->multi
&& ctx
->header_done
)
936 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
939 vty_out(vty
, "VRF %s:\n",
943 "VRF %s table %u:\n",
947 ctx
->header_done
= true;
951 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
956 prefix2str(&rn
->p
, buf
, sizeof(buf
));
957 json_object_object_add(json
, buf
, json_prefix
);
966 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
967 afi_t afi
, bool use_fib
, bool use_json
,
969 const struct prefix
*longer_prefix_p
,
970 bool supernets_only
, int type
,
971 unsigned short ospf_instance_id
, bool show_ng
,
972 struct route_show_ctx
*ctx
)
974 struct zebra_router_table
*zrt
;
975 struct rib_table_info
*info
;
977 RB_FOREACH (zrt
, zebra_router_table_head
,
979 info
= route_table_get_info(zrt
->table
);
981 if (zvrf
!= info
->zvrf
)
983 if (zrt
->afi
!= afi
||
984 zrt
->safi
!= SAFI_UNICAST
)
987 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
988 use_fib
, use_json
, tag
, longer_prefix_p
,
989 supernets_only
, type
, ospf_instance_id
,
990 zrt
->tableid
, show_ng
, ctx
);
994 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
995 safi_t safi
, bool use_fib
, bool use_json
,
997 const struct prefix
*longer_prefix_p
,
998 bool supernets_only
, int type
,
999 unsigned short ospf_instance_id
, uint32_t tableid
,
1000 bool show_ng
, struct route_show_ctx
*ctx
)
1002 struct route_table
*table
;
1003 struct zebra_vrf
*zvrf
= NULL
;
1005 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1007 vty_out(vty
, "{}\n");
1009 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1013 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1015 vty_out(vty
, "{}\n");
1017 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1022 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1024 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1027 vty_out(vty
, "{}\n");
1031 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1032 longer_prefix_p
, supernets_only
, type
,
1033 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1040 "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
1044 "IP nexthop tracking table\n"
1045 "IP import check tracking table\n"
1051 VRF_ALL_CMD_HELP_STR
1052 "Show Multicast (MRIB) NHT state\n"
1055 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1056 vrf_id_t vrf_id
= VRF_DEFAULT
;
1057 struct prefix prefix
, *p
= NULL
;
1058 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1059 bool uj
= use_json(argc
, argv
);
1060 json_object
*json
= NULL
;
1061 json_object
*json_vrf
= NULL
;
1062 json_object
*json_nexthop
= NULL
;
1065 json
= json_object_new_object();
1069 struct zebra_vrf
*zvrf
;
1071 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1072 if ((zvrf
= vrf
->info
) != NULL
) {
1074 json_vrf
= json_object_new_object();
1075 json_nexthop
= json_object_new_object();
1076 json_object_object_add(json
,
1079 json_object_object_add(json_vrf
,
1085 vty_out(vty
, "\nVRF %s:\n",
1088 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1089 vty
, NULL
, json_nexthop
);
1094 vty_json(vty
, json
);
1099 VRF_GET_ID(vrf_id
, vrf_name
, false);
1101 memset(&prefix
, 0, sizeof(prefix
));
1103 p
= sockunion2hostprefix(addr
, &prefix
);
1106 json_object_free(json
);
1112 json_vrf
= json_object_new_object();
1113 json_nexthop
= json_object_new_object();
1115 json_object_object_add(json
, vrf_name
, json_vrf
);
1117 json_object_object_add(json
, "default", json_vrf
);
1119 json_object_object_add(json_vrf
,
1120 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1124 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1127 vty_json(vty
, json
);
1132 DEFUN (ip_nht_default_route
,
1133 ip_nht_default_route_cmd
,
1134 "ip nht resolve-via-default",
1136 "Filter Next Hop tracking route resolution\n"
1137 "Resolve via default route\n")
1139 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1144 if (zvrf
->zebra_rnh_ip_default_route
)
1147 zvrf
->zebra_rnh_ip_default_route
= true;
1149 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1153 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1154 json_object
*json_nhe_hdr
)
1156 struct nexthop
*nexthop
= NULL
;
1157 struct nhg_connected
*rb_node_dep
= NULL
;
1158 struct nexthop_group
*backup_nhg
;
1159 char up_str
[MONOTIME_STRLEN
];
1160 char time_left
[MONOTIME_STRLEN
];
1161 json_object
*json_dependants
= NULL
;
1162 json_object
*json_depends
= NULL
;
1163 json_object
*json_nexthop_array
= NULL
;
1164 json_object
*json_nexthops
= NULL
;
1165 json_object
*json
= NULL
;
1166 json_object
*json_backup_nexthop_array
= NULL
;
1167 json_object
*json_backup_nexthops
= NULL
;
1170 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1173 json
= json_object_new_object();
1176 json_object_string_add(json
, "type",
1177 zebra_route_string(nhe
->type
));
1178 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1179 if (thread_is_scheduled(nhe
->timer
))
1180 json_object_string_add(
1181 json
, "timeToDeletion",
1182 thread_timer_to_hhmmss(time_left
,
1185 json_object_string_add(json
, "uptime", up_str
);
1186 json_object_string_add(json
, "vrf",
1187 vrf_id_to_name(nhe
->vrf_id
));
1190 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1191 zebra_route_string(nhe
->type
));
1192 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1193 if (thread_is_scheduled(nhe
->timer
))
1194 vty_out(vty
, " Time to Deletion: %s",
1195 thread_timer_to_hhmmss(time_left
,
1200 vty_out(vty
, " Uptime: %s\n", up_str
);
1201 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1204 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1206 json_object_boolean_true_add(json
, "valid");
1208 vty_out(vty
, " Valid");
1210 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1212 json_object_boolean_true_add(json
, "installed");
1214 vty_out(vty
, ", Installed");
1221 json_object_int_add(json
, "interfaceIndex",
1224 vty_out(vty
, " Interface Index: %d\n",
1228 if (!zebra_nhg_depends_is_empty(nhe
)) {
1230 json_depends
= json_object_new_array();
1232 vty_out(vty
, " Depends:");
1233 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1235 json_object_array_add(
1237 json_object_new_int(
1238 rb_node_dep
->nhe
->id
));
1240 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1245 json_object_object_add(json
, "depends", json_depends
);
1248 /* Output nexthops */
1250 json_nexthop_array
= json_object_new_array();
1253 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1254 if (json_nexthop_array
) {
1255 json_nexthops
= json_object_new_object();
1256 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1258 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1261 /* Make recursive nexthops a bit more clear */
1263 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1266 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1267 if (CHECK_FLAG(nexthop
->flags
,
1268 NEXTHOP_FLAG_HAS_BACKUP
)) {
1270 json_object_int_add(
1271 json_nexthops
, "backup",
1272 nexthop
->backup_idx
[0]);
1274 vty_out(vty
, " [backup %d]",
1275 nexthop
->backup_idx
[0]);
1281 json_object_array_add(json_nexthop_array
,
1288 /* TODO -- print more useful backup info */
1289 if (CHECK_FLAG(nexthop
->flags
,
1290 NEXTHOP_FLAG_HAS_BACKUP
)) {
1293 vty_out(vty
, "[backup");
1294 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1296 nexthop
->backup_idx
[i
]);
1301 json_object_array_add(json_nexthop_array
,
1307 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1309 /* Output backup nexthops (if any) */
1310 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1313 json_backup_nexthop_array
= json_object_new_array();
1315 vty_out(vty
, " Backups:\n");
1317 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1318 if (json_backup_nexthop_array
) {
1319 json_backup_nexthops
= json_object_new_object();
1320 show_nexthop_json_helper(json_backup_nexthops
,
1322 json_object_array_add(json_backup_nexthop_array
,
1323 json_backup_nexthops
);
1326 if (!CHECK_FLAG(nexthop
->flags
,
1327 NEXTHOP_FLAG_RECURSIVE
))
1330 /* Make recursive nexthops a bit more
1334 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1340 json_object_object_add(json
, "backupNexthops",
1341 json_backup_nexthop_array
);
1344 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1346 json_dependants
= json_object_new_array();
1348 vty_out(vty
, " Dependents:");
1349 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1352 json_object_array_add(
1354 json_object_new_int(
1355 rb_node_dep
->nhe
->id
));
1357 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1360 json_object_object_add(json
, "dependents",
1366 if (nhe
->nhg
.nhgr
.buckets
) {
1368 json_object_int_add(json
, "buckets",
1369 nhe
->nhg
.nhgr
.buckets
);
1370 json_object_int_add(json
, "idleTimer",
1371 nhe
->nhg
.nhgr
.idle_timer
);
1372 json_object_int_add(json
, "unbalancedTimer",
1373 nhe
->nhg
.nhgr
.unbalanced_timer
);
1374 json_object_int_add(json
, "unbalancedTime",
1375 nhe
->nhg
.nhgr
.unbalanced_time
);
1378 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1380 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1381 nhe
->nhg
.nhgr
.unbalanced_timer
,
1382 nhe
->nhg
.nhgr
.unbalanced_time
);
1387 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1390 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1393 struct nhg_hash_entry
*nhe
= NULL
;
1395 nhe
= zebra_nhg_lookup_id(id
);
1398 show_nexthop_group_out(vty
, nhe
, json
);
1401 vty_json(vty
, json
);
1403 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1409 vty_json(vty
, json
);
1414 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1416 struct nhe_show_context
{
1424 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1426 struct nhe_show_context
*ctx
= arg
;
1427 struct nhg_hash_entry
*nhe
;
1429 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1431 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1434 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1437 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1440 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1443 return HASHWALK_CONTINUE
;
1446 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1447 struct zebra_vrf
*zvrf
, afi_t afi
,
1448 int type
, json_object
*json
)
1450 struct nhe_show_context ctx
;
1454 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1458 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1461 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1463 struct zebra_if
*zebra_if
= NULL
;
1464 struct nhg_connected
*rb_node_dep
= NULL
;
1466 zebra_if
= ifp
->info
;
1468 if (!if_nhg_dependents_is_empty(ifp
)) {
1469 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1471 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1474 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1479 DEFPY (show_interface_nexthop_group
,
1480 show_interface_nexthop_group_cmd
,
1481 "show interface [IFNAME$if_name] nexthop-group",
1483 "Interface status and configuration\n"
1485 "Show Nexthop Groups\n")
1487 struct vrf
*vrf
= NULL
;
1488 struct interface
*ifp
= NULL
;
1491 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1493 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1495 if_nexthop_group_dump_vty(vty
, ifp
);
1499 FOR_ALL_INTERFACES (vrf
, ifp
)
1500 if_nexthop_group_dump_vty(vty
, ifp
);
1506 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1513 DEFPY(show_nexthop_group
,
1514 show_nexthop_group_cmd
,
1515 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]",
1517 "Show Nexthop Groups\n"
1519 "Nexthop Group ID\n"
1520 "Show Singleton Nexthop-Groups\n"
1523 "Kernel (not installed via the zebra RIB)\n"
1524 "Zebra (implicitly created by zebra)\n"
1525 "Border Gateway Protocol (BGP)\n"
1526 "Super Happy Advanced Routing Protocol (SHARP)\n"
1527 VRF_FULL_CMD_HELP_STR
1531 struct zebra_vrf
*zvrf
= NULL
;
1532 afi_t afi
= AFI_UNSPEC
;
1534 bool uj
= use_json(argc
, argv
);
1535 json_object
*json
= NULL
;
1536 json_object
*json_vrf
= NULL
;
1539 json
= json_object_new_object();
1542 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1550 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1553 type
= ZEBRA_ROUTE_NHG
;
1557 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1559 vty_json(vty
, json
);
1562 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1569 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1570 struct zebra_vrf
*zvrf
;
1576 json_vrf
= json_object_new_object();
1578 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1580 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1583 json_object_object_add(json
, vrf
->name
,
1588 vty_json(vty
, json
);
1594 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1596 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1600 vty_json(vty
, json
);
1602 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1607 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1610 vty_json(vty
, json
);
1615 DEFPY_HIDDEN(nexthop_group_use_enable
,
1616 nexthop_group_use_enable_cmd
,
1617 "[no] zebra nexthop kernel enable",
1620 "Nexthop configuration \n"
1621 "Configure use of kernel nexthops\n"
1622 "Enable kernel nexthops\n")
1624 zebra_nhg_enable_kernel_nexthops(!no
);
1628 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1629 "[no] zebra nexthop proto only",
1631 "Nexthop configuration\n"
1632 "Configure exclusive use of proto nexthops\n"
1633 "Only use proto nexthops\n")
1635 zebra_nhg_set_proto_nexthops_only(!no
);
1639 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1640 backup_nexthop_recursive_use_enable_cmd
,
1641 "[no] zebra nexthop resolve-via-backup",
1644 "Nexthop configuration \n"
1645 "Configure use of backup nexthops in recursive resolution\n")
1647 zebra_nhg_set_recursive_use_backups(!no
);
1651 DEFUN (no_ip_nht_default_route
,
1652 no_ip_nht_default_route_cmd
,
1653 "no ip nht resolve-via-default",
1656 "Filter Next Hop tracking route resolution\n"
1657 "Resolve via default route\n")
1659 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1664 if (!zvrf
->zebra_rnh_ip_default_route
)
1667 zvrf
->zebra_rnh_ip_default_route
= false;
1668 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1672 DEFUN (ipv6_nht_default_route
,
1673 ipv6_nht_default_route_cmd
,
1674 "ipv6 nht resolve-via-default",
1676 "Filter Next Hop tracking route resolution\n"
1677 "Resolve via default route\n")
1679 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1684 if (zvrf
->zebra_rnh_ipv6_default_route
)
1687 zvrf
->zebra_rnh_ipv6_default_route
= true;
1688 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1692 DEFUN (no_ipv6_nht_default_route
,
1693 no_ipv6_nht_default_route_cmd
,
1694 "no ipv6 nht resolve-via-default",
1697 "Filter Next Hop tracking route resolution\n"
1698 "Resolve via default route\n")
1700 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1705 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1708 zvrf
->zebra_rnh_ipv6_default_route
= false;
1709 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1713 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1714 "[no] ip nht hide-backup-events",
1717 "Nexthop-tracking configuration\n"
1718 "Hide notification about backup nexthops\n")
1720 rnh_set_hide_backups(!no
);
1728 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1729 [vrf <NAME$vrf_name|all$vrf_all>]\
1732 |A.B.C.D/M$prefix longer-prefixes\
1733 |supernets-only$supernets_only\
1736 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1737 |ospf$type_str (1-65535)$ospf_instance_id\
1739 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1740 [vrf <NAME$vrf_name|all$vrf_all>]\
1743 |X:X::X:X/M$prefix longer-prefixes\
1745 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1747 [<json$json|nexthop-group$ng>]",
1750 "IP forwarding table\n"
1751 "IP routing table\n"
1752 "Table to display\n"
1753 "The table number to display\n"
1755 VRF_FULL_CMD_HELP_STR
1756 "Show only routes with tag\n"
1758 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1759 "Show route matching the specified Network/Mask pair only\n"
1760 "Show supernet entries only\n"
1761 FRR_IP_REDIST_HELP_STR_ZEBRA
1762 "Open Shortest Path First (OSPFv2)\n"
1765 "IP forwarding table\n"
1766 "IP routing table\n"
1767 "Table to display\n"
1768 "The table number to display\n"
1770 VRF_FULL_CMD_HELP_STR
1771 "Show only routes with tag\n"
1774 "Show route matching the specified Network/Mask pair only\n"
1775 FRR_IP6_REDIST_HELP_STR_ZEBRA
1777 "Nexthop Group Information\n")
1779 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1782 struct zebra_vrf
*zvrf
;
1783 struct route_show_ctx ctx
= {
1784 .multi
= vrf_all
|| table_all
,
1787 if (!vrf_is_backend_netns()) {
1788 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1790 vty_out(vty
, "{}\n");
1792 vty_out(vty
, "Linux vrf backend already points to table id\n");
1793 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1799 type
= proto_redistnum(afi
, type_str
);
1801 vty_out(vty
, "Unknown route type\n");
1807 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1808 if ((zvrf
= vrf
->info
) == NULL
1809 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1813 do_show_ip_route_all(
1814 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1815 prefix_str
? prefix
: NULL
,
1816 !!supernets_only
, type
,
1817 ospf_instance_id
, !!ng
, &ctx
);
1820 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1822 prefix_str
? prefix
: NULL
,
1823 !!supernets_only
, type
,
1824 ospf_instance_id
, table
, !!ng
, &ctx
);
1827 vrf_id_t vrf_id
= VRF_DEFAULT
;
1830 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1831 vrf
= vrf_lookup_by_id(vrf_id
);
1840 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1841 prefix_str
? prefix
: NULL
,
1842 !!supernets_only
, type
,
1843 ospf_instance_id
, !!ng
, &ctx
);
1845 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1847 prefix_str
? prefix
: NULL
,
1848 !!supernets_only
, type
,
1849 ospf_instance_id
, table
, !!ng
, &ctx
);
1855 ALIAS_HIDDEN (show_route
,
1857 "show <ip$ipv4|ipv6$ipv6> ro",
1861 "IP routing table\n");
1864 DEFPY (show_route_detail
,
1865 show_route_detail_cmd
,
1868 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1873 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1879 [json$json] [nexthop-group$ng]",
1882 "IP forwarding table\n"
1883 "IP routing table\n"
1884 VRF_FULL_CMD_HELP_STR
1885 "Network in the IP routing table to display\n"
1886 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1888 "IPv6 forwarding table\n"
1889 "IPv6 routing table\n"
1890 VRF_FULL_CMD_HELP_STR
1894 "Nexthop Group Information\n")
1896 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1897 struct route_table
*table
;
1899 struct route_node
*rn
;
1900 bool use_fib
= !!fib
;
1902 bool network_found
= false;
1903 bool show_ng
= !!ng
;
1906 prefix_str
= address_str
;
1907 if (str2prefix(prefix_str
, &p
) < 0) {
1908 vty_out(vty
, "%% Malformed address\n");
1914 struct zebra_vrf
*zvrf
;
1916 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1917 if ((zvrf
= vrf
->info
) == NULL
1918 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1921 rn
= route_node_match(table
, &p
);
1924 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1925 route_unlock_node(rn
);
1929 dest
= rib_dest_from_rnode(rn
);
1930 if (use_fib
&& !dest
->selected_fib
) {
1931 route_unlock_node(rn
);
1935 network_found
= true;
1937 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1939 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1942 route_unlock_node(rn
);
1945 if (!network_found
) {
1947 vty_out(vty
, "{}\n");
1951 "%% Network not in FIB\n");
1954 "%% Network not in RIB\n");
1959 vrf_id_t vrf_id
= VRF_DEFAULT
;
1962 VRF_GET_ID(vrf_id
, vrf_name
, false);
1964 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1968 rn
= route_node_match(table
, &p
);
1970 dest
= rib_dest_from_rnode(rn
);
1972 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1973 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1975 vty_out(vty
, "{}\n");
1979 "%% Network not in FIB\n");
1982 "%% Network not in table\n");
1985 route_unlock_node(rn
);
1990 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1992 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1994 route_unlock_node(rn
);
2000 DEFPY (show_route_summary
,
2001 show_route_summary_cmd
,
2002 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2003 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2007 "IP routing table\n"
2008 VRF_FULL_CMD_HELP_STR
2009 "Summary of all routes\n"
2010 "Table to display summary for\n"
2011 "The table number\n"
2015 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2016 struct route_table
*table
;
2017 bool uj
= use_json(argc
, argv
);
2021 struct zebra_vrf
*zvrf
;
2023 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2024 if ((zvrf
= vrf
->info
) == NULL
)
2028 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2031 table
= zebra_vrf_lookup_table_with_table_id(
2032 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2039 vty_show_ip_route_summary_prefix(vty
, table
,
2042 vty_show_ip_route_summary(vty
, table
, uj
);
2045 vrf_id_t vrf_id
= VRF_DEFAULT
;
2048 VRF_GET_ID(vrf_id
, vrf_name
, false);
2051 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2053 table
= zebra_vrf_lookup_table_with_table_id(
2054 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2059 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2061 vty_show_ip_route_summary(vty
, table
, uj
);
2067 DEFUN_HIDDEN (show_route_zebra_dump
,
2068 show_route_zebra_dump_cmd
,
2069 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2079 struct route_table
*table
;
2080 const char *vrf_name
= NULL
;
2083 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2085 if (argv_find(argv
, argc
, "vrf", &idx
))
2086 vrf_name
= argv
[++idx
]->arg
;
2090 struct zebra_vrf
*zvrf
;
2092 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2095 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2098 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2099 show_ip_route_dump_vty(vty
, table
);
2102 vrf_id_t vrf_id
= VRF_DEFAULT
;
2104 VRF_GET_ID(vrf_id
, vrf_name
, true);
2106 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2110 show_ip_route_dump_vty(vty
, table
);
2116 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2117 struct route_entry
*re
, unsigned int num
)
2120 char buf
[SRCDEST2STR_BUFFER
];
2122 vty_out(vty
, " Nexthop %u:\n", num
);
2123 vty_out(vty
, " type: %u\n", nexthop
->type
);
2124 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2125 switch (nexthop
->type
) {
2126 case NEXTHOP_TYPE_IPV4
:
2127 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2128 vty_out(vty
, " ip address: %s\n",
2129 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2131 vty_out(vty
, " afi: ipv4\n");
2133 if (nexthop
->ifindex
) {
2134 vty_out(vty
, " interface index: %d\n",
2136 vty_out(vty
, " interface name: %s\n",
2137 ifindex2ifname(nexthop
->ifindex
,
2141 if (nexthop
->src
.ipv4
.s_addr
2142 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2144 vty_out(vty
, " source: %s\n", buf
);
2146 case NEXTHOP_TYPE_IPV6
:
2147 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2148 vty_out(vty
, " ip: %s\n",
2149 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2151 vty_out(vty
, " afi: ipv6\n");
2153 if (nexthop
->ifindex
) {
2154 vty_out(vty
, " interface index: %d\n",
2156 vty_out(vty
, " interface name: %s\n",
2157 ifindex2ifname(nexthop
->ifindex
,
2161 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2162 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2164 vty_out(vty
, " source: %s\n", buf
);
2167 case NEXTHOP_TYPE_IFINDEX
:
2169 " Nexthop is an interface (directly connected).\n");
2170 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2171 vty_out(vty
, " interface name: %s\n",
2172 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2174 case NEXTHOP_TYPE_BLACKHOLE
:
2175 vty_out(vty
, " Nexthop type is blackhole.\n");
2177 switch (nexthop
->bh_type
) {
2178 case BLACKHOLE_REJECT
:
2179 vty_out(vty
, " Blackhole type: reject\n");
2181 case BLACKHOLE_ADMINPROHIB
:
2183 " Blackhole type: admin-prohibited\n");
2185 case BLACKHOLE_NULL
:
2186 vty_out(vty
, " Blackhole type: NULL0\n");
2188 case BLACKHOLE_UNSPEC
:
2195 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2197 struct route_node
*rn
;
2198 struct route_entry
*re
;
2199 char buf
[SRCDEST2STR_BUFFER
];
2204 struct nexthop
*nexthop
= NULL
;
2205 int nexthop_num
= 0;
2207 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2208 vty_out(vty
, "----------------------------\n");
2210 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2211 RNODE_FOREACH_RE (rn
, re
) {
2212 vty_out(vty
, "Route: %s\n",
2213 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2214 vty_out(vty
, " protocol: %s\n",
2215 zebra_route_string(re
->type
));
2216 vty_out(vty
, " instance: %u\n", re
->instance
);
2217 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2218 vty_out(vty
, " VRF name: %s\n",
2219 vrf_id_to_name(re
->vrf_id
));
2220 vty_out(vty
, " flags: %u\n", re
->flags
);
2222 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2223 vty_out(vty
, " distance: %u\n", re
->distance
);
2224 vty_out(vty
, " metric: %u\n", re
->metric
);
2227 vty_out(vty
, " tag: %u\n", re
->tag
);
2229 uptime
= monotime(&tv
);
2230 uptime
-= re
->uptime
;
2231 gmtime_r(&uptime
, &tm
);
2233 if (uptime
< ONE_DAY_SECOND
)
2234 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2235 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2236 else if (uptime
< ONE_WEEK_SECOND
)
2237 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2238 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2240 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2242 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2245 vty_out(vty
, " status: %u\n", re
->status
);
2246 vty_out(vty
, " nexthop_num: %u\n",
2247 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2248 vty_out(vty
, " nexthop_active_num: %u\n",
2249 nexthop_group_active_nexthop_num(
2251 vty_out(vty
, " table: %u\n", re
->table
);
2252 vty_out(vty
, " uptime: %s\n", time
);
2254 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2256 show_ip_route_nht_dump(vty
, nexthop
, re
,
2266 static void vty_show_ip_route_summary(struct vty
*vty
,
2267 struct route_table
*table
, bool use_json
)
2269 struct route_node
*rn
;
2270 struct route_entry
*re
;
2271 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2272 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2273 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2274 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2275 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2276 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2279 json_object
*json_route_summary
= NULL
;
2280 json_object
*json_route_routes
= NULL
;
2282 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2283 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2284 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2285 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2288 json_route_summary
= json_object_new_object();
2289 json_route_routes
= json_object_new_array();
2290 json_object_object_add(json_route_summary
, "routes",
2294 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2295 RNODE_FOREACH_RE (rn
, re
) {
2296 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2297 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2299 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2301 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2303 rib_cnt
[re
->type
]++;
2305 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2306 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2309 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2311 fib_cnt
[re
->type
]++;
2314 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2316 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2318 trap_cnt
[re
->type
]++;
2321 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2323 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2325 offload_cnt
[re
->type
]++;
2330 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2332 zvrf_name(((struct rib_table_info
*)
2333 route_table_get_info(table
))
2336 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2337 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2338 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2339 if (i
== ZEBRA_ROUTE_BGP
) {
2341 json_object
*json_route_ebgp
=
2342 json_object_new_object();
2344 json_object_int_add(
2345 json_route_ebgp
, "fib",
2346 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2347 json_object_int_add(
2348 json_route_ebgp
, "rib",
2349 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2350 json_object_int_add(
2351 json_route_ebgp
, "fibOffLoaded",
2352 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2353 json_object_int_add(
2354 json_route_ebgp
, "fibTrapped",
2355 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2357 json_object_string_add(json_route_ebgp
,
2359 json_object_array_add(json_route_routes
,
2362 json_object
*json_route_ibgp
=
2363 json_object_new_object();
2365 json_object_int_add(
2366 json_route_ibgp
, "fib",
2367 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2368 json_object_int_add(
2369 json_route_ibgp
, "rib",
2370 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2371 json_object_int_add(
2372 json_route_ibgp
, "fibOffLoaded",
2373 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2374 json_object_int_add(
2375 json_route_ibgp
, "fibTrapped",
2376 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2377 json_object_string_add(json_route_ibgp
,
2379 json_object_array_add(json_route_routes
,
2382 vty_out(vty
, "%-20s %-20d %-20d \n",
2384 rib_cnt
[ZEBRA_ROUTE_BGP
],
2385 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2386 vty_out(vty
, "%-20s %-20d %-20d \n",
2388 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2389 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2393 json_object
*json_route_type
=
2394 json_object_new_object();
2396 json_object_int_add(json_route_type
,
2398 json_object_int_add(json_route_type
,
2401 json_object_int_add(json_route_type
,
2404 json_object_int_add(json_route_type
,
2407 json_object_string_add(
2408 json_route_type
, "type",
2409 zebra_route_string(i
));
2410 json_object_array_add(json_route_routes
,
2413 vty_out(vty
, "%-20s %-20d %-20d \n",
2414 zebra_route_string(i
),
2415 rib_cnt
[i
], fib_cnt
[i
]);
2421 json_object_int_add(json_route_summary
, "routesTotal",
2422 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2423 json_object_int_add(json_route_summary
, "routesTotalFib",
2424 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2426 vty_json(vty
, json_route_summary
);
2428 vty_out(vty
, "------\n");
2429 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2430 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2436 * Implementation of the ip route summary prefix command.
2438 * This command prints the primary prefixes that have been installed by various
2439 * protocols on the box.
2442 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2443 struct route_table
*table
,
2446 struct route_node
*rn
;
2447 struct route_entry
*re
;
2448 struct nexthop
*nexthop
;
2449 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2450 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2451 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2452 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2455 json_object
*json_route_summary
= NULL
;
2456 json_object
*json_route_routes
= NULL
;
2458 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2459 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2462 json_route_summary
= json_object_new_object();
2463 json_route_routes
= json_object_new_array();
2464 json_object_object_add(json_route_summary
, "prefixRoutes",
2468 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2469 RNODE_FOREACH_RE (rn
, re
) {
2472 * In case of ECMP, count only once.
2475 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2476 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2477 fib_cnt
[re
->type
]++;
2479 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2480 nexthop
= nexthop
->next
) {
2482 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2483 rib_cnt
[re
->type
]++;
2484 if (re
->type
== ZEBRA_ROUTE_BGP
2485 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2486 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2487 if (CHECK_FLAG(re
->status
,
2488 ROUTE_ENTRY_INSTALLED
))
2489 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2495 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2496 "Prefix Routes", "FIB",
2497 zvrf_name(((struct rib_table_info
*)
2498 route_table_get_info(table
))
2501 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2502 if (rib_cnt
[i
] > 0) {
2503 if (i
== ZEBRA_ROUTE_BGP
) {
2505 json_object
*json_route_ebgp
=
2506 json_object_new_object();
2508 json_object_int_add(
2509 json_route_ebgp
, "fib",
2510 fib_cnt
[ZEBRA_ROUTE_BGP
]
2511 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2512 json_object_int_add(
2513 json_route_ebgp
, "rib",
2514 rib_cnt
[ZEBRA_ROUTE_BGP
]
2515 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2516 json_object_string_add(json_route_ebgp
,
2518 json_object_array_add(json_route_routes
,
2521 json_object
*json_route_ibgp
=
2522 json_object_new_object();
2524 json_object_int_add(
2525 json_route_ibgp
, "fib",
2526 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2527 json_object_int_add(
2528 json_route_ibgp
, "rib",
2529 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2530 json_object_string_add(json_route_ibgp
,
2532 json_object_array_add(json_route_routes
,
2535 vty_out(vty
, "%-20s %-20d %-20d \n",
2537 rib_cnt
[ZEBRA_ROUTE_BGP
]
2538 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2539 fib_cnt
[ZEBRA_ROUTE_BGP
]
2540 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2541 vty_out(vty
, "%-20s %-20d %-20d \n",
2543 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2544 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2548 json_object
*json_route_type
=
2549 json_object_new_object();
2551 json_object_int_add(json_route_type
,
2553 json_object_int_add(json_route_type
,
2555 json_object_string_add(
2556 json_route_type
, "type",
2557 zebra_route_string(i
));
2558 json_object_array_add(json_route_routes
,
2561 vty_out(vty
, "%-20s %-20d %-20d \n",
2562 zebra_route_string(i
),
2563 rib_cnt
[i
], fib_cnt
[i
]);
2569 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2570 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2571 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2572 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2574 vty_json(vty
, json_route_summary
);
2576 vty_out(vty
, "------\n");
2577 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2578 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2583 DEFUN (allow_external_route_update
,
2584 allow_external_route_update_cmd
,
2585 "allow-external-route-update",
2586 "Allow FRR routes to be overwritten by external processes\n")
2588 zrouter
.allow_delete
= true;
2593 DEFUN (no_allow_external_route_update
,
2594 no_allow_external_route_update_cmd
,
2595 "no allow-external-route-update",
2597 "Allow FRR routes to be overwritten by external processes\n")
2599 zrouter
.allow_delete
= false;
2612 struct zebra_vrf
*zvrf
;
2614 if (vrf_is_backend_netns())
2615 vty_out(vty
, "netns-based vrfs\n");
2617 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2618 if (!(zvrf
= vrf
->info
))
2620 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2623 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2624 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2625 vty_out(vty
, "inactive");
2626 else if (zvrf_ns_name(zvrf
))
2627 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2628 zvrf_ns_name(zvrf
));
2630 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2632 if (vrf_is_user_cfged(vrf
))
2633 vty_out(vty
, " (configured)");
2640 DEFPY (evpn_mh_mac_holdtime
,
2641 evpn_mh_mac_holdtime_cmd
,
2642 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2647 "Duration in seconds\n")
2649 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2653 DEFPY (evpn_mh_neigh_holdtime
,
2654 evpn_mh_neigh_holdtime_cmd
,
2655 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2659 "Neighbor entry hold time\n"
2660 "Duration in seconds\n")
2663 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2667 DEFPY (evpn_mh_startup_delay
,
2668 evpn_mh_startup_delay_cmd
,
2669 "[no] evpn mh startup-delay(0-3600)$duration",
2674 "duration in seconds\n")
2677 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2681 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2682 "[no$no] evpn mh redirect-off",
2686 "ES bond redirect for fast-failover off\n")
2690 redirect_off
= no
? false : true;
2692 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2695 DEFUN (default_vrf_vni_mapping
,
2696 default_vrf_vni_mapping_cmd
,
2697 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2698 "VNI corresponding to the DEFAULT VRF\n"
2700 "Prefix routes only \n")
2702 char xpath
[XPATH_MAXLEN
];
2703 struct zebra_vrf
*zvrf
= NULL
;
2706 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2713 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2715 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2717 snprintf(xpath
, sizeof(xpath
),
2718 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2720 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2723 snprintf(xpath
, sizeof(xpath
),
2724 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2726 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2729 return nb_cli_apply_changes(vty
, NULL
);
2732 DEFUN (no_default_vrf_vni_mapping
,
2733 no_default_vrf_vni_mapping_cmd
,
2734 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2736 "VNI corresponding to DEFAULT VRF\n"
2738 "Prefix routes only \n")
2740 char xpath
[XPATH_MAXLEN
];
2742 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2743 struct zebra_vrf
*zvrf
= NULL
;
2745 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2752 if (zvrf
->l3vni
!= vni
) {
2753 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2758 snprintf(xpath
, sizeof(xpath
),
2759 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2761 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2764 snprintf(xpath
, sizeof(xpath
),
2765 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2767 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2770 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2772 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2774 return nb_cli_apply_changes(vty
, NULL
);
2777 DEFUN (vrf_vni_mapping
,
2778 vrf_vni_mapping_cmd
,
2779 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2780 "VNI corresponding to tenant VRF\n"
2782 "prefix-routes-only\n")
2786 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2794 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2795 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2799 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2800 NB_OP_MODIFY
, "true");
2802 return nb_cli_apply_changes(vty
, NULL
);
2805 DEFUN (no_vrf_vni_mapping
,
2806 no_vrf_vni_mapping_cmd
,
2807 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2809 "VNI corresponding to tenant VRF\n"
2811 "prefix-routes-only\n")
2815 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2816 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2824 if (zvrf
->l3vni
!= vni
) {
2825 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2830 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2834 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2835 NB_OP_DESTROY
, "true");
2837 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2839 return nb_cli_apply_changes(vty
, NULL
);
2843 DEFPY (show_vrf_vni
,
2845 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2847 VRF_FULL_CMD_HELP_STR
2852 struct zebra_vrf
*zvrf
;
2853 json_object
*json
= NULL
;
2854 json_object
*json_vrfs
= NULL
;
2855 bool uj
= use_json(argc
, argv
);
2856 bool use_vrf
= false;
2859 json
= json_object_new_object();
2861 /* show vrf vni used to display across all vrfs
2862 * This is enhanced to support only for specific
2865 if (vrf_all
|| !vrf_name
) {
2866 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2877 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2878 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2881 json_vrfs
= json_object_new_array();
2884 vty_json(vty
, json
);
2886 vty_out(vty
, "%% VRF does not exist\n");
2893 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2898 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2900 } else if (vrf_name
) {
2901 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2904 vty_json(vty
, json
);
2907 "%% VRF '%s' specified does not exist\n",
2914 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2915 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2918 json_vrfs
= json_object_new_array();
2920 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2924 json_object_object_add(json
, "vrfs", json_vrfs
);
2925 vty_json(vty
, json
);
2931 DEFUN (show_evpn_global
,
2932 show_evpn_global_cmd
,
2938 bool uj
= use_json(argc
, argv
);
2940 zebra_vxlan_print_evpn(vty
, uj
);
2944 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2945 SHOW_STR IP_STR
"neighbors\n")
2948 zebra_neigh_show(vty
);
2953 DEFPY(show_evpn_l2_nh
,
2954 show_evpn_l2_nh_cmd
,
2955 "show evpn l2-nh [json$json]",
2963 zebra_evpn_l2_nh_show(vty
, uj
);
2970 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2973 "Ethernet Segment\n"
2975 "Detailed information\n"
2982 if (!str_to_esi(esi_str
, &esi
)) {
2983 vty_out(vty
, "%% Malformed ESI\n");
2986 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2989 zebra_evpn_es_show_detail(vty
, uj
);
2991 zebra_evpn_es_show(vty
, uj
);
2997 DEFPY(show_evpn_es_evi
,
2998 show_evpn_es_evi_cmd
,
2999 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3002 "Ethernet Segment per EVI\n"
3003 "VxLAN Network Identifier\n"
3005 "Detailed information\n"
3012 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3014 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3019 DEFPY(show_evpn_access_vlan
,
3020 show_evpn_access_vlan_cmd
,
3021 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3026 "Detailed information\n"
3032 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3035 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3037 zebra_evpn_acc_vl_show(vty
, uj
);
3043 DEFUN (show_evpn_vni
,
3045 "show evpn vni [json]",
3048 "VxLAN Network Identifier\n"
3051 struct zebra_vrf
*zvrf
;
3052 bool uj
= use_json(argc
, argv
);
3054 zvrf
= zebra_vrf_get_evpn();
3055 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3059 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3060 "show evpn vni detail [json]",
3063 "VxLAN Network Identifier\n"
3064 "Detailed Information On Each VNI\n"
3067 struct zebra_vrf
*zvrf
;
3068 bool uj
= use_json(argc
, argv
);
3070 zvrf
= zebra_vrf_get_evpn();
3071 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3075 DEFUN (show_evpn_vni_vni
,
3076 show_evpn_vni_vni_cmd
,
3077 "show evpn vni " CMD_VNI_RANGE
"[json]",
3080 "VxLAN Network Identifier\n"
3084 struct zebra_vrf
*zvrf
;
3086 bool uj
= use_json(argc
, argv
);
3088 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3089 zvrf
= zebra_vrf_get_evpn();
3090 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3094 DEFUN (show_evpn_rmac_vni_mac
,
3095 show_evpn_rmac_vni_mac_cmd
,
3096 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3103 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3108 bool uj
= use_json(argc
, argv
);
3110 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3111 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3112 vty_out(vty
, "%% Malformed MAC address\n");
3115 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3119 DEFUN (show_evpn_rmac_vni
,
3120 show_evpn_rmac_vni_cmd
,
3121 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3130 bool uj
= use_json(argc
, argv
);
3132 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3133 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3138 DEFUN (show_evpn_rmac_vni_all
,
3139 show_evpn_rmac_vni_all_cmd
,
3140 "show evpn rmac vni all [json]",
3148 bool uj
= use_json(argc
, argv
);
3150 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3155 DEFUN (show_evpn_nh_vni_ip
,
3156 show_evpn_nh_vni_ip_cmd
,
3157 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3164 "Host address (ipv4 or ipv6)\n"
3169 bool uj
= use_json(argc
, argv
);
3171 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3172 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3174 vty_out(vty
, "%% Malformed Neighbor address\n");
3177 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3182 DEFUN (show_evpn_nh_vni
,
3183 show_evpn_nh_vni_cmd
,
3184 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3193 bool uj
= use_json(argc
, argv
);
3195 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3196 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3201 DEFUN (show_evpn_nh_vni_all
,
3202 show_evpn_nh_vni_all_cmd
,
3203 "show evpn next-hops vni all [json]",
3211 bool uj
= use_json(argc
, argv
);
3213 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3218 DEFUN (show_evpn_mac_vni
,
3219 show_evpn_mac_vni_cmd
,
3220 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3224 "VxLAN Network Identifier\n"
3228 struct zebra_vrf
*zvrf
;
3230 bool uj
= use_json(argc
, argv
);
3232 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3233 zvrf
= zebra_vrf_get_evpn();
3234 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3238 DEFPY (show_evpn_mac_vni_detail
,
3239 show_evpn_mac_vni_detail_cmd
,
3240 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3244 "VXLAN Network Identifier\n"
3246 "Detailed Information On Each VNI MAC\n"
3249 struct zebra_vrf
*zvrf
;
3250 bool uj
= use_json(argc
, argv
);
3252 zvrf
= zebra_vrf_get_evpn();
3253 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3257 DEFUN (show_evpn_mac_vni_all
,
3258 show_evpn_mac_vni_all_cmd
,
3259 "show evpn mac vni all [json]",
3263 "VxLAN Network Identifier\n"
3267 struct zebra_vrf
*zvrf
;
3268 bool uj
= use_json(argc
, argv
);
3270 zvrf
= zebra_vrf_get_evpn();
3271 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3275 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3276 "show evpn mac vni all detail [json]",
3280 "VxLAN Network Identifier\n"
3282 "Detailed Information On Each VNI MAC\n"
3285 struct zebra_vrf
*zvrf
;
3286 bool uj
= use_json(argc
, argv
);
3288 zvrf
= zebra_vrf_get_evpn();
3289 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3293 DEFUN (show_evpn_mac_vni_all_vtep
,
3294 show_evpn_mac_vni_all_vtep_cmd
,
3295 "show evpn mac vni all vtep A.B.C.D [json]",
3299 "VxLAN Network Identifier\n"
3302 "Remote VTEP IP address\n"
3305 struct zebra_vrf
*zvrf
;
3306 struct in_addr vtep_ip
;
3307 bool uj
= use_json(argc
, argv
);
3309 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3311 vty_out(vty
, "%% Malformed VTEP IP address\n");
3314 zvrf
= zebra_vrf_get_evpn();
3315 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3321 DEFUN (show_evpn_mac_vni_mac
,
3322 show_evpn_mac_vni_mac_cmd
,
3323 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3327 "VxLAN Network Identifier\n"
3330 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3334 struct zebra_vrf
*zvrf
;
3337 bool uj
= use_json(argc
, argv
);
3339 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3340 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3341 vty_out(vty
, "%% Malformed MAC address\n");
3344 zvrf
= zebra_vrf_get_evpn();
3345 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3349 DEFUN (show_evpn_mac_vni_vtep
,
3350 show_evpn_mac_vni_vtep_cmd
,
3351 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3355 "VxLAN Network Identifier\n"
3358 "Remote VTEP IP address\n"
3361 struct zebra_vrf
*zvrf
;
3363 struct in_addr vtep_ip
;
3364 bool uj
= use_json(argc
, argv
);
3366 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3367 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3369 vty_out(vty
, "%% Malformed VTEP IP address\n");
3373 zvrf
= zebra_vrf_get_evpn();
3374 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3378 DEFPY (show_evpn_mac_vni_all_dad
,
3379 show_evpn_mac_vni_all_dad_cmd
,
3380 "show evpn mac vni all duplicate [json]",
3384 "VxLAN Network Identifier\n"
3386 "Duplicate address list\n"
3389 struct zebra_vrf
*zvrf
;
3390 bool uj
= use_json(argc
, argv
);
3392 zvrf
= zebra_vrf_get_evpn();
3393 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3398 DEFPY (show_evpn_mac_vni_dad
,
3399 show_evpn_mac_vni_dad_cmd
,
3400 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3404 "VxLAN Network Identifier\n"
3406 "Duplicate address list\n"
3409 struct zebra_vrf
*zvrf
;
3410 bool uj
= use_json(argc
, argv
);
3412 zvrf
= zebra_vrf_get_evpn();
3414 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3419 DEFPY (show_evpn_neigh_vni_dad
,
3420 show_evpn_neigh_vni_dad_cmd
,
3421 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3424 "ARP and ND cache\n"
3425 "VxLAN Network Identifier\n"
3427 "Duplicate address list\n"
3430 struct zebra_vrf
*zvrf
;
3431 bool uj
= use_json(argc
, argv
);
3433 zvrf
= zebra_vrf_get_evpn();
3434 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3438 DEFPY (show_evpn_neigh_vni_all_dad
,
3439 show_evpn_neigh_vni_all_dad_cmd
,
3440 "show evpn arp-cache vni all duplicate [json]",
3443 "ARP and ND cache\n"
3444 "VxLAN Network Identifier\n"
3446 "Duplicate address list\n"
3449 struct zebra_vrf
*zvrf
;
3450 bool uj
= use_json(argc
, argv
);
3452 zvrf
= zebra_vrf_get_evpn();
3453 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3458 DEFUN (show_evpn_neigh_vni
,
3459 show_evpn_neigh_vni_cmd
,
3460 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3463 "ARP and ND cache\n"
3464 "VxLAN Network Identifier\n"
3468 struct zebra_vrf
*zvrf
;
3470 bool uj
= use_json(argc
, argv
);
3472 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3473 zvrf
= zebra_vrf_get_evpn();
3474 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3478 DEFUN (show_evpn_neigh_vni_all
,
3479 show_evpn_neigh_vni_all_cmd
,
3480 "show evpn arp-cache vni all [json]",
3483 "ARP and ND cache\n"
3484 "VxLAN Network Identifier\n"
3488 struct zebra_vrf
*zvrf
;
3489 bool uj
= use_json(argc
, argv
);
3491 zvrf
= zebra_vrf_get_evpn();
3492 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3496 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3497 "show evpn arp-cache vni all detail [json]",
3500 "ARP and ND cache\n"
3501 "VxLAN Network Identifier\n"
3503 "Neighbor details for all vnis in detail\n" JSON_STR
)
3505 struct zebra_vrf
*zvrf
;
3506 bool uj
= use_json(argc
, argv
);
3508 zvrf
= zebra_vrf_get_evpn();
3509 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3513 DEFUN (show_evpn_neigh_vni_neigh
,
3514 show_evpn_neigh_vni_neigh_cmd
,
3515 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3522 "Neighbor address (IPv4 or IPv6 address)\n"
3525 struct zebra_vrf
*zvrf
;
3528 bool uj
= use_json(argc
, argv
);
3530 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3531 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3533 vty_out(vty
, "%% Malformed Neighbor address\n");
3536 zvrf
= zebra_vrf_get_evpn();
3537 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3541 DEFUN (show_evpn_neigh_vni_vtep
,
3542 show_evpn_neigh_vni_vtep_cmd
,
3543 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3546 "ARP and ND cache\n"
3547 "VxLAN Network Identifier\n"
3550 "Remote VTEP IP address\n"
3553 struct zebra_vrf
*zvrf
;
3555 struct in_addr vtep_ip
;
3556 bool uj
= use_json(argc
, argv
);
3558 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3559 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3561 vty_out(vty
, "%% Malformed VTEP IP address\n");
3565 zvrf
= zebra_vrf_get_evpn();
3566 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3570 /* policy routing contexts */
3571 DEFUN (show_pbr_ipset
,
3573 "show pbr ipset [WORD]",
3575 "Policy-Based Routing\n"
3576 "IPset Context information\n"
3577 "IPset Name information\n")
3581 found
= argv_find(argv
, argc
, "WORD", &idx
);
3583 zebra_pbr_show_ipset_list(vty
, NULL
);
3585 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3589 /* policy routing contexts */
3590 DEFUN (show_pbr_iptable
,
3591 show_pbr_iptable_cmd
,
3592 "show pbr iptable [WORD]",
3594 "Policy-Based Routing\n"
3595 "IPtable Context information\n"
3596 "IPtable Name information\n")
3601 found
= argv_find(argv
, argc
, "WORD", &idx
);
3603 zebra_pbr_show_iptable(vty
, NULL
);
3605 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3609 /* policy routing contexts */
3610 DEFPY (show_pbr_rule
,
3614 "Policy-Based Routing\n"
3617 zebra_pbr_show_rule(vty
);
3621 DEFPY (pbr_nexthop_resolve
,
3622 pbr_nexthop_resolve_cmd
,
3623 "[no$no] pbr nexthop-resolve",
3625 "Policy Based Routing\n"
3626 "Resolve nexthop for dataplane programming\n")
3628 zebra_pbr_expand_action_update(!no
);
3632 DEFPY (clear_evpn_dup_addr
,
3633 clear_evpn_dup_addr_cmd
,
3634 "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>]>",
3637 "Duplicate address \n"
3638 "VxLAN Network Identifier\n"
3642 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3647 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3648 int ret
= CMD_SUCCESS
;
3650 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3651 *yang_dup_mac
= NULL
;
3656 yang_dup
= yang_data_new(
3657 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3660 yang_dup
= yang_data_new_uint32(
3661 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3663 if (!is_zero_mac(&mac
->eth_addr
)) {
3664 yang_dup_mac
= yang_data_new_mac(
3665 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3668 listnode_add(input
, yang_dup_mac
);
3670 if (sockunion_family(ip
) == AF_INET
) {
3671 host_ip
.ipa_type
= IPADDR_V4
;
3672 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3674 host_ip
.ipa_type
= IPADDR_V6
;
3675 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3676 sizeof(struct in6_addr
));
3679 yang_dup_ip
= yang_data_new_ip(
3680 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3684 listnode_add(input
, yang_dup_ip
);
3689 listnode_add(input
, yang_dup
);
3690 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3694 list_delete(&input
);
3699 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3700 evpn_accept_bgp_seq_cmd
,
3701 "evpn accept-bgp-seq",
3703 "Accept all sequence numbers from BGP\n")
3705 zebra_vxlan_set_accept_bgp_seq(true);
3709 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3710 no_evpn_accept_bgp_seq_cmd
,
3711 "no evpn accept-bgp-seq",
3714 "Accept all sequence numbers from BGP\n")
3716 zebra_vxlan_set_accept_bgp_seq(false);
3720 /* Static ip route configuration write function. */
3721 static int zebra_ip_config(struct vty
*vty
)
3725 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3730 DEFUN (ip_zebra_import_table_distance
,
3731 ip_zebra_import_table_distance_cmd
,
3732 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3734 "import routes from non-main kernel table\n"
3735 "kernel routing table id\n"
3736 "Distance for imported routes\n"
3737 "Default distance value\n"
3738 "route-map for filtering\n"
3741 uint32_t table_id
= 0;
3743 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3744 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3746 strmatch(argv
[argc
- 2]->text
, "route-map")
3747 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3751 if (argc
== 7 || (argc
== 5 && !rmap
))
3752 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3754 if (!is_zebra_valid_kernel_table(table_id
)) {
3756 "Invalid routing table ID, %d. Must be in range 1-252\n",
3759 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3763 if (is_zebra_main_routing_table(table_id
)) {
3765 "Invalid routing table ID, %d. Must be non-default table\n",
3768 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3772 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3775 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3780 DEFUN_HIDDEN (zebra_packet_process
,
3781 zebra_packet_process_cmd
,
3782 "zebra zapi-packets (1-10000)",
3785 "Number of packets to process before relinquishing thread\n")
3787 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3789 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3790 memory_order_relaxed
);
3795 DEFUN_HIDDEN (no_zebra_packet_process
,
3796 no_zebra_packet_process_cmd
,
3797 "no zebra zapi-packets [(1-10000)]",
3801 "Number of packets to process before relinquishing thread\n")
3803 atomic_store_explicit(&zrouter
.packets_to_process
,
3804 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3805 memory_order_relaxed
);
3810 DEFUN_HIDDEN (zebra_workqueue_timer
,
3811 zebra_workqueue_timer_cmd
,
3812 "zebra work-queue (0-10000)",
3815 "Time in milliseconds\n")
3817 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3818 zrouter
.ribq
->spec
.hold
= timer
;
3823 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3824 no_zebra_workqueue_timer_cmd
,
3825 "no zebra work-queue [(0-10000)]",
3829 "Time in milliseconds\n")
3831 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3836 DEFUN (no_ip_zebra_import_table
,
3837 no_ip_zebra_import_table_cmd
,
3838 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3841 "import routes from non-main kernel table\n"
3842 "kernel routing table id\n"
3843 "Distance for imported routes\n"
3844 "Default distance value\n"
3845 "route-map for filtering\n"
3848 uint32_t table_id
= 0;
3849 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3851 if (!is_zebra_valid_kernel_table(table_id
)) {
3853 "Invalid routing table ID. Must be in range 1-252\n");
3857 if (is_zebra_main_routing_table(table_id
)) {
3859 "Invalid routing table ID, %d. Must be non-default table\n",
3864 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3867 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3870 DEFPY (zebra_nexthop_group_keep
,
3871 zebra_nexthop_group_keep_cmd
,
3872 "[no] zebra nexthop-group keep (1-3600)",
3876 "How long to keep\n"
3877 "Time in seconds from 1-3600\n")
3880 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3882 zrouter
.nhg_keep
= keep
;
3887 static int config_write_protocol(struct vty
*vty
)
3889 if (zrouter
.allow_delete
)
3890 vty_out(vty
, "allow-external-route-update\n");
3892 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3893 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3895 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3896 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3898 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3899 vty_out(vty
, "zebra zapi-packets %u\n",
3900 zrouter
.packets_to_process
);
3902 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3904 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3905 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3906 ipv4_multicast_mode
== MCAST_URIB_ONLY
3908 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3910 : ipv4_multicast_mode
3911 == MCAST_MIX_MRIB_FIRST
3913 : ipv4_multicast_mode
3914 == MCAST_MIX_DISTANCE
3918 /* Include dataplane info */
3919 dplane_config_write_helper(vty
);
3921 zebra_evpn_mh_config_write(vty
);
3923 zebra_pbr_config_write(vty
);
3925 if (!zebra_vxlan_get_accept_bgp_seq())
3926 vty_out(vty
, "no evpn accept-bgp-seq\n");
3928 /* Include nexthop-group config */
3929 if (!zebra_nhg_kernel_nexthops_enabled())
3930 vty_out(vty
, "no zebra nexthop kernel enable\n");
3932 if (zebra_nhg_proto_nexthops_only())
3933 vty_out(vty
, "zebra nexthop proto only\n");
3935 if (!zebra_nhg_recursive_use_backups())
3936 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3938 if (rnh_get_hide_backups())
3939 vty_out(vty
, "ip nht hide-backup-events\n");
3942 /* Include netlink info */
3943 netlink_config_write_helper(vty
);
3944 #endif /* HAVE_NETLINK */
3956 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3959 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3960 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3961 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3962 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3963 ttable_add_row(table
, "v6 Forwarding|%s",
3964 ipforward_ipv6() ? "On" : "Off");
3965 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3966 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3967 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3971 if (!vrf_is_backend_netns())
3972 ttable_add_row(table
, "VRF|l3mdev Available");
3974 ttable_add_row(table
, "VRF|Namespaces");
3976 ttable_add_row(table
, "VRF|Not Available");
3979 ttable_add_row(table
, "ASIC offload|%s",
3980 zrouter
.asic_offloaded
? "Used" : "Unavailable");
3983 * Do not display this unless someone is actually using it
3985 * Why this distinction? I think this is effectively dead code
3986 * and should not be exposed. Maybe someone proves me wrong.
3988 if (zrouter
.asic_notification_nexthop_control
)
3989 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
3991 ttable_add_row(table
, "RA|%s",
3992 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
3993 ttable_add_row(table
, "RFC 5549|%s",
3994 rtadv_get_interfaces_configured_from_bgp()
3996 : "BGP is not using");
3998 ttable_add_row(table
, "Kernel NHG|%s",
3999 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4001 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4002 zrouter
.allow_delete
? "Yes" : "No");
4003 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4004 zrouter
.all_linkdownv4
? "On" : "Off");
4005 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4006 zrouter
.default_linkdownv4
? "On" : "Off");
4007 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4008 zrouter
.all_linkdownv6
? "On" : "Off");
4009 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4010 zrouter
.default_linkdownv6
? "On" : "Off");
4012 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4013 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4014 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4015 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4016 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4017 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4018 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4019 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4021 out
= ttable_dump(table
, "\n");
4022 vty_out(vty
, "%s\n", out
);
4023 XFREE(MTYPE_TMP
, out
);
4027 " Route Route Neighbor LSP LSP\n");
4029 "VRF Installs Removals Updates Installs Removals\n");
4031 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4032 struct zebra_vrf
*zvrf
= vrf
->info
;
4034 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4035 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4036 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4037 zvrf
->lsp_removals
);
4043 DEFUN (ip_forwarding
,
4047 "Turn on IP forwarding\n")
4053 ret
= ipforward_on();
4056 vty_out(vty
, "Can't turn on IP forwarding\n");
4057 return CMD_WARNING_CONFIG_FAILED
;
4063 DEFUN (no_ip_forwarding
,
4064 no_ip_forwarding_cmd
,
4068 "Turn off IP forwarding\n")
4074 ret
= ipforward_off();
4077 vty_out(vty
, "Can't turn off IP forwarding\n");
4078 return CMD_WARNING_CONFIG_FAILED
;
4084 /* Only display ip forwarding is enabled or not. */
4085 DEFUN (show_ip_forwarding
,
4086 show_ip_forwarding_cmd
,
4087 "show ip forwarding",
4090 "IP forwarding status\n")
4097 vty_out(vty
, "IP forwarding is off\n");
4099 vty_out(vty
, "IP forwarding is on\n");
4103 /* Only display ipv6 forwarding is enabled or not. */
4104 DEFUN (show_ipv6_forwarding
,
4105 show_ipv6_forwarding_cmd
,
4106 "show ipv6 forwarding",
4108 "IPv6 information\n"
4109 "Forwarding status\n")
4113 ret
= ipforward_ipv6();
4117 vty_out(vty
, "ipv6 forwarding is unknown\n");
4120 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4123 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4126 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4132 DEFUN (ipv6_forwarding
,
4133 ipv6_forwarding_cmd
,
4136 "Turn on IPv6 forwarding\n")
4140 ret
= ipforward_ipv6();
4142 ret
= ipforward_ipv6_on();
4145 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4146 return CMD_WARNING_CONFIG_FAILED
;
4152 DEFUN (no_ipv6_forwarding
,
4153 no_ipv6_forwarding_cmd
,
4154 "no ipv6 forwarding",
4157 "Turn off IPv6 forwarding\n")
4161 ret
= ipforward_ipv6();
4163 ret
= ipforward_ipv6_off();
4166 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4167 return CMD_WARNING_CONFIG_FAILED
;
4173 /* Display dataplane info */
4174 DEFUN (show_dataplane
,
4176 "show zebra dplane [detailed]",
4179 "Zebra dataplane information\n"
4180 "Detailed output\n")
4183 bool detailed
= false;
4185 if (argv_find(argv
, argc
, "detailed", &idx
))
4188 return dplane_show_helper(vty
, detailed
);
4191 /* Display dataplane providers info */
4192 DEFUN (show_dataplane_providers
,
4193 show_dataplane_providers_cmd
,
4194 "show zebra dplane providers [detailed]",
4197 "Zebra dataplane information\n"
4198 "Zebra dataplane provider information\n"
4199 "Detailed output\n")
4202 bool detailed
= false;
4204 if (argv_find(argv
, argc
, "detailed", &idx
))
4207 return dplane_show_provs_helper(vty
, detailed
);
4210 /* Configure dataplane incoming queue limit */
4211 DEFUN (zebra_dplane_queue_limit
,
4212 zebra_dplane_queue_limit_cmd
,
4213 "zebra dplane limit (0-10000)",
4216 "Limit incoming queued updates\n"
4217 "Number of queued updates\n")
4221 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4223 dplane_set_in_queue_limit(limit
, true);
4228 /* Reset dataplane queue limit to default value */
4229 DEFUN (no_zebra_dplane_queue_limit
,
4230 no_zebra_dplane_queue_limit_cmd
,
4231 "no zebra dplane limit [(0-10000)]",
4235 "Limit incoming queued updates\n"
4236 "Number of queued updates\n")
4238 dplane_set_in_queue_limit(0, false);
4243 DEFUN (zebra_show_routing_tables_summary
,
4244 zebra_show_routing_tables_summary_cmd
,
4245 "show zebra router table summary",
4248 "The Zebra Router Information\n"
4249 "Table Information about this Zebra Router\n"
4250 "Summary Information\n")
4252 zebra_router_show_table_summary(vty
);
4257 /* Table configuration write function. */
4258 static int config_write_table(struct vty
*vty
)
4263 /* IPForwarding configuration write function. */
4264 static int config_write_forwarding(struct vty
*vty
)
4267 vty_out(vty
, "no ip forwarding\n");
4268 if (!ipforward_ipv6())
4269 vty_out(vty
, "no ipv6 forwarding\n");
4270 vty_out(vty
, "!\n");
4274 DEFUN_HIDDEN (show_frr
,
4280 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4281 vty_out(vty
, ".............................7777:..............................................\n");
4282 vty_out(vty
, ".............................777777,............................................\n");
4283 vty_out(vty
, "... .........................77777777,..........................................\n");
4284 vty_out(vty
, "............................=7777777777:........................................\n");
4285 vty_out(vty
, "........................:7777777777777777,......................................\n");
4286 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4287 vty_out(vty
, "...................I7777777777+.................................................\n");
4288 vty_out(vty
, "................,777777777?............ .......................................\n");
4289 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4290 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4291 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4292 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4293 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4294 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4295 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4296 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4297 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4298 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4299 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4300 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4301 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4302 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4303 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4304 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4305 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4306 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4307 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4308 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4309 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4310 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4311 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4312 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4313 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4314 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4315 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4316 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4317 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4318 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4319 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4320 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4321 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4322 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4323 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4324 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4325 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4326 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4327 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4328 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4329 vty_out(vty
, "................................~77777777...............=777777.................\n");
4330 vty_out(vty
, ".....................................:=?I................~777777................\n");
4331 vty_out(vty
, "..........................................................:777777,..............\n");
4332 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4338 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4339 zebra_kernel_netlink_batch_tx_buf_cmd
,
4340 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4342 "Zebra kernel interface\n"
4343 "Set Netlink parameters\n"
4344 "Set batch buffer size and send threshold\n"
4345 "Size of the buffer\n"
4348 uint32_t bufsize
= 0, threshold
= 0;
4350 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4351 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4353 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4358 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4359 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4360 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4362 "Zebra kernel interface\n"
4363 "Set Netlink parameters\n"
4364 "Set batch buffer size and send threshold\n"
4365 "Size of the buffer\n"
4368 netlink_set_batch_buffer_size(0, 0, false);
4373 DEFPY (zebra_protodown_bit
,
4374 zebra_protodown_bit_cmd
,
4375 "zebra protodown reason-bit (0-31)$bit",
4377 "Protodown Configuration\n"
4378 "Reason Bit used in the kernel for application\n"
4379 "Reason Bit range\n")
4381 if_netlink_set_frr_protodown_r_bit(bit
);
4385 DEFPY (no_zebra_protodown_bit
,
4386 no_zebra_protodown_bit_cmd
,
4387 "no zebra protodown reason-bit [(0-31)$bit]",
4390 "Protodown Configuration\n"
4391 "Reason Bit used in the kernel for setting protodown\n"
4392 "Reason Bit Range\n")
4394 if_netlink_unset_frr_protodown_r_bit();
4398 #endif /* HAVE_NETLINK */
4400 DEFUN(ip_table_range
, ip_table_range_cmd
,
4401 "[no] ip table range (1-4294967295) (1-4294967295)",
4403 "table configuration\n"
4404 "Configure table range\n"
4405 "Start Routing Table\n"
4406 "End Routing Table\n")
4408 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4413 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4415 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4419 if (strmatch(argv
[0]->text
, "no"))
4420 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4422 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4425 #ifdef HAVE_SCRIPTING
4427 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4428 "zebra on-rib-process script SCRIPT",
4430 "on_rib_process_dplane_results hook call\n"
4432 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4435 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4438 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4439 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4441 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4442 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4447 #endif /* HAVE_SCRIPTING */
4449 /* IP node for static routes. */
4450 static int zebra_ip_config(struct vty
*vty
);
4451 static struct cmd_node ip_node
= {
4452 .name
= "static ip",
4455 .config_write
= zebra_ip_config
,
4457 static int config_write_protocol(struct vty
*vty
);
4458 static struct cmd_node protocol_node
= {
4460 .node
= PROTOCOL_NODE
,
4462 .config_write
= config_write_protocol
,
4464 /* table node for routing tables. */
4465 static int config_write_table(struct vty
*vty
);
4466 static struct cmd_node table_node
= {
4470 .config_write
= config_write_table
,
4472 static int config_write_forwarding(struct vty
*vty
);
4473 static struct cmd_node forwarding_node
= {
4474 .name
= "forwarding",
4475 .node
= FORWARDING_NODE
,
4477 .config_write
= config_write_forwarding
,
4481 void zebra_vty_init(void)
4483 /* Install configuration write function. */
4484 install_node(&table_node
);
4485 install_node(&forwarding_node
);
4487 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4488 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4489 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4490 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4492 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4493 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4494 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4497 zebra_route_map_init();
4499 install_node(&ip_node
);
4500 install_node(&protocol_node
);
4502 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4503 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4505 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4506 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4508 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4509 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4510 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4511 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4512 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4513 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4514 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4515 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4516 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4517 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4519 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4520 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4522 install_element(VIEW_NODE
, &show_vrf_cmd
);
4523 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4524 install_element(VIEW_NODE
, &show_route_cmd
);
4525 install_element(VIEW_NODE
, &show_ro_cmd
);
4526 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4527 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4528 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4530 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4531 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4533 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4534 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4535 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4536 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4537 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4538 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4539 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4540 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4541 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4543 install_element(VIEW_NODE
, &show_frr_cmd
);
4544 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4545 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4546 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4547 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4548 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4549 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4550 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4551 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4552 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4553 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4554 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4555 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4556 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4557 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4558 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4574 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4575 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4576 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4578 install_element(VIEW_NODE
, &show_neigh_cmd
);
4580 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4581 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4582 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4583 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4584 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4586 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4587 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4588 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4589 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4590 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4591 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4592 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4593 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4595 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4596 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4597 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4598 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4600 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4601 install_element(VRF_NODE
, &ip_table_range_cmd
);
4604 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4605 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4606 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4607 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4608 #endif /* HAVE_NETLINK */
4610 #ifdef HAVE_SCRIPTING
4611 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4612 #endif /* HAVE_SCRIPTING */
4614 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);