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
, show_evpn_access_vlan_cmd
,
3020 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3025 "Detailed information\n" JSON_STR
)
3029 if (if_name
&& vid
) {
3032 struct interface
*ifp
;
3034 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3036 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
3038 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
,
3046 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
3051 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3053 zebra_evpn_acc_vl_show(vty
, uj
);
3059 DEFUN (show_evpn_vni
,
3061 "show evpn vni [json]",
3064 "VxLAN Network Identifier\n"
3067 struct zebra_vrf
*zvrf
;
3068 bool uj
= use_json(argc
, argv
);
3070 zvrf
= zebra_vrf_get_evpn();
3071 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3075 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3076 "show evpn vni detail [json]",
3079 "VxLAN Network Identifier\n"
3080 "Detailed Information On Each VNI\n"
3083 struct zebra_vrf
*zvrf
;
3084 bool uj
= use_json(argc
, argv
);
3086 zvrf
= zebra_vrf_get_evpn();
3087 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3091 DEFUN (show_evpn_vni_vni
,
3092 show_evpn_vni_vni_cmd
,
3093 "show evpn vni " CMD_VNI_RANGE
"[json]",
3096 "VxLAN Network Identifier\n"
3100 struct zebra_vrf
*zvrf
;
3102 bool uj
= use_json(argc
, argv
);
3104 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3105 zvrf
= zebra_vrf_get_evpn();
3106 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3110 DEFUN (show_evpn_rmac_vni_mac
,
3111 show_evpn_rmac_vni_mac_cmd
,
3112 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3119 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3124 bool uj
= use_json(argc
, argv
);
3126 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3127 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3128 vty_out(vty
, "%% Malformed MAC address\n");
3131 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3135 DEFUN (show_evpn_rmac_vni
,
3136 show_evpn_rmac_vni_cmd
,
3137 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3146 bool uj
= use_json(argc
, argv
);
3148 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3149 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3154 DEFUN (show_evpn_rmac_vni_all
,
3155 show_evpn_rmac_vni_all_cmd
,
3156 "show evpn rmac vni all [json]",
3164 bool uj
= use_json(argc
, argv
);
3166 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3171 DEFUN (show_evpn_nh_vni_ip
,
3172 show_evpn_nh_vni_ip_cmd
,
3173 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3180 "Host address (ipv4 or ipv6)\n"
3185 bool uj
= use_json(argc
, argv
);
3187 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3188 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3190 vty_out(vty
, "%% Malformed Neighbor address\n");
3193 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3198 DEFUN (show_evpn_nh_vni
,
3199 show_evpn_nh_vni_cmd
,
3200 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3209 bool uj
= use_json(argc
, argv
);
3211 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3212 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3217 DEFUN (show_evpn_nh_vni_all
,
3218 show_evpn_nh_vni_all_cmd
,
3219 "show evpn next-hops vni all [json]",
3227 bool uj
= use_json(argc
, argv
);
3229 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3234 DEFUN (show_evpn_mac_vni
,
3235 show_evpn_mac_vni_cmd
,
3236 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3240 "VxLAN Network Identifier\n"
3244 struct zebra_vrf
*zvrf
;
3246 bool uj
= use_json(argc
, argv
);
3248 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3249 zvrf
= zebra_vrf_get_evpn();
3250 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3254 DEFPY (show_evpn_mac_vni_detail
,
3255 show_evpn_mac_vni_detail_cmd
,
3256 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3260 "VXLAN Network Identifier\n"
3262 "Detailed Information On Each VNI MAC\n"
3265 struct zebra_vrf
*zvrf
;
3266 bool uj
= use_json(argc
, argv
);
3268 zvrf
= zebra_vrf_get_evpn();
3269 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3273 DEFUN (show_evpn_mac_vni_all
,
3274 show_evpn_mac_vni_all_cmd
,
3275 "show evpn mac vni all [json]",
3279 "VxLAN Network Identifier\n"
3283 struct zebra_vrf
*zvrf
;
3284 bool uj
= use_json(argc
, argv
);
3286 zvrf
= zebra_vrf_get_evpn();
3287 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3291 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3292 "show evpn mac vni all detail [json]",
3296 "VxLAN Network Identifier\n"
3298 "Detailed Information On Each VNI MAC\n"
3301 struct zebra_vrf
*zvrf
;
3302 bool uj
= use_json(argc
, argv
);
3304 zvrf
= zebra_vrf_get_evpn();
3305 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3309 DEFUN (show_evpn_mac_vni_all_vtep
,
3310 show_evpn_mac_vni_all_vtep_cmd
,
3311 "show evpn mac vni all vtep A.B.C.D [json]",
3315 "VxLAN Network Identifier\n"
3318 "Remote VTEP IP address\n"
3321 struct zebra_vrf
*zvrf
;
3322 struct in_addr vtep_ip
;
3323 bool uj
= use_json(argc
, argv
);
3325 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3327 vty_out(vty
, "%% Malformed VTEP IP address\n");
3330 zvrf
= zebra_vrf_get_evpn();
3331 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3337 DEFUN (show_evpn_mac_vni_mac
,
3338 show_evpn_mac_vni_mac_cmd
,
3339 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3343 "VxLAN Network Identifier\n"
3346 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3350 struct zebra_vrf
*zvrf
;
3353 bool uj
= use_json(argc
, argv
);
3355 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3356 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3357 vty_out(vty
, "%% Malformed MAC address\n");
3360 zvrf
= zebra_vrf_get_evpn();
3361 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3365 DEFUN (show_evpn_mac_vni_vtep
,
3366 show_evpn_mac_vni_vtep_cmd
,
3367 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3371 "VxLAN Network Identifier\n"
3374 "Remote VTEP IP address\n"
3377 struct zebra_vrf
*zvrf
;
3379 struct in_addr vtep_ip
;
3380 bool uj
= use_json(argc
, argv
);
3382 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3383 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3385 vty_out(vty
, "%% Malformed VTEP IP address\n");
3389 zvrf
= zebra_vrf_get_evpn();
3390 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3394 DEFPY (show_evpn_mac_vni_all_dad
,
3395 show_evpn_mac_vni_all_dad_cmd
,
3396 "show evpn mac vni all duplicate [json]",
3400 "VxLAN Network Identifier\n"
3402 "Duplicate address list\n"
3405 struct zebra_vrf
*zvrf
;
3406 bool uj
= use_json(argc
, argv
);
3408 zvrf
= zebra_vrf_get_evpn();
3409 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3414 DEFPY (show_evpn_mac_vni_dad
,
3415 show_evpn_mac_vni_dad_cmd
,
3416 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3420 "VxLAN Network Identifier\n"
3422 "Duplicate address list\n"
3425 struct zebra_vrf
*zvrf
;
3426 bool uj
= use_json(argc
, argv
);
3428 zvrf
= zebra_vrf_get_evpn();
3430 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3435 DEFPY (show_evpn_neigh_vni_dad
,
3436 show_evpn_neigh_vni_dad_cmd
,
3437 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3440 "ARP and ND cache\n"
3441 "VxLAN Network Identifier\n"
3443 "Duplicate address list\n"
3446 struct zebra_vrf
*zvrf
;
3447 bool uj
= use_json(argc
, argv
);
3449 zvrf
= zebra_vrf_get_evpn();
3450 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3454 DEFPY (show_evpn_neigh_vni_all_dad
,
3455 show_evpn_neigh_vni_all_dad_cmd
,
3456 "show evpn arp-cache vni all duplicate [json]",
3459 "ARP and ND cache\n"
3460 "VxLAN Network Identifier\n"
3462 "Duplicate address list\n"
3465 struct zebra_vrf
*zvrf
;
3466 bool uj
= use_json(argc
, argv
);
3468 zvrf
= zebra_vrf_get_evpn();
3469 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3474 DEFUN (show_evpn_neigh_vni
,
3475 show_evpn_neigh_vni_cmd
,
3476 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3479 "ARP and ND cache\n"
3480 "VxLAN Network Identifier\n"
3484 struct zebra_vrf
*zvrf
;
3486 bool uj
= use_json(argc
, argv
);
3488 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3489 zvrf
= zebra_vrf_get_evpn();
3490 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3494 DEFUN (show_evpn_neigh_vni_all
,
3495 show_evpn_neigh_vni_all_cmd
,
3496 "show evpn arp-cache vni all [json]",
3499 "ARP and ND cache\n"
3500 "VxLAN Network Identifier\n"
3504 struct zebra_vrf
*zvrf
;
3505 bool uj
= use_json(argc
, argv
);
3507 zvrf
= zebra_vrf_get_evpn();
3508 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3512 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3513 "show evpn arp-cache vni all detail [json]",
3516 "ARP and ND cache\n"
3517 "VxLAN Network Identifier\n"
3519 "Neighbor details for all vnis in detail\n" JSON_STR
)
3521 struct zebra_vrf
*zvrf
;
3522 bool uj
= use_json(argc
, argv
);
3524 zvrf
= zebra_vrf_get_evpn();
3525 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3529 DEFUN (show_evpn_neigh_vni_neigh
,
3530 show_evpn_neigh_vni_neigh_cmd
,
3531 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3534 "ARP and ND cache\n"
3535 "VxLAN Network Identifier\n"
3538 "Neighbor address (IPv4 or IPv6 address)\n"
3541 struct zebra_vrf
*zvrf
;
3544 bool uj
= use_json(argc
, argv
);
3546 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3547 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3549 vty_out(vty
, "%% Malformed Neighbor address\n");
3552 zvrf
= zebra_vrf_get_evpn();
3553 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3557 DEFUN (show_evpn_neigh_vni_vtep
,
3558 show_evpn_neigh_vni_vtep_cmd
,
3559 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3562 "ARP and ND cache\n"
3563 "VxLAN Network Identifier\n"
3566 "Remote VTEP IP address\n"
3569 struct zebra_vrf
*zvrf
;
3571 struct in_addr vtep_ip
;
3572 bool uj
= use_json(argc
, argv
);
3574 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3575 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3577 vty_out(vty
, "%% Malformed VTEP IP address\n");
3581 zvrf
= zebra_vrf_get_evpn();
3582 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3586 /* policy routing contexts */
3587 DEFUN (show_pbr_ipset
,
3589 "show pbr ipset [WORD]",
3591 "Policy-Based Routing\n"
3592 "IPset Context information\n"
3593 "IPset Name information\n")
3597 found
= argv_find(argv
, argc
, "WORD", &idx
);
3599 zebra_pbr_show_ipset_list(vty
, NULL
);
3601 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3605 /* policy routing contexts */
3606 DEFUN (show_pbr_iptable
,
3607 show_pbr_iptable_cmd
,
3608 "show pbr iptable [WORD]",
3610 "Policy-Based Routing\n"
3611 "IPtable Context information\n"
3612 "IPtable Name information\n")
3617 found
= argv_find(argv
, argc
, "WORD", &idx
);
3619 zebra_pbr_show_iptable(vty
, NULL
);
3621 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3625 /* policy routing contexts */
3626 DEFPY (show_pbr_rule
,
3630 "Policy-Based Routing\n"
3633 zebra_pbr_show_rule(vty
);
3637 DEFPY (pbr_nexthop_resolve
,
3638 pbr_nexthop_resolve_cmd
,
3639 "[no$no] pbr nexthop-resolve",
3641 "Policy Based Routing\n"
3642 "Resolve nexthop for dataplane programming\n")
3644 zebra_pbr_expand_action_update(!no
);
3648 DEFPY (clear_evpn_dup_addr
,
3649 clear_evpn_dup_addr_cmd
,
3650 "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>]>",
3653 "Duplicate address \n"
3654 "VxLAN Network Identifier\n"
3658 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3663 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3664 int ret
= CMD_SUCCESS
;
3666 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3667 *yang_dup_mac
= NULL
;
3672 yang_dup
= yang_data_new(
3673 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3676 yang_dup
= yang_data_new_uint32(
3677 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3679 if (!is_zero_mac(&mac
->eth_addr
)) {
3680 yang_dup_mac
= yang_data_new_mac(
3681 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3684 listnode_add(input
, yang_dup_mac
);
3686 if (sockunion_family(ip
) == AF_INET
) {
3687 host_ip
.ipa_type
= IPADDR_V4
;
3688 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3690 host_ip
.ipa_type
= IPADDR_V6
;
3691 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3692 sizeof(struct in6_addr
));
3695 yang_dup_ip
= yang_data_new_ip(
3696 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3700 listnode_add(input
, yang_dup_ip
);
3705 listnode_add(input
, yang_dup
);
3706 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3710 list_delete(&input
);
3715 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3716 evpn_accept_bgp_seq_cmd
,
3717 "evpn accept-bgp-seq",
3719 "Accept all sequence numbers from BGP\n")
3721 zebra_vxlan_set_accept_bgp_seq(true);
3725 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3726 no_evpn_accept_bgp_seq_cmd
,
3727 "no evpn accept-bgp-seq",
3730 "Accept all sequence numbers from BGP\n")
3732 zebra_vxlan_set_accept_bgp_seq(false);
3736 /* Static ip route configuration write function. */
3737 static int zebra_ip_config(struct vty
*vty
)
3741 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3746 DEFUN (ip_zebra_import_table_distance
,
3747 ip_zebra_import_table_distance_cmd
,
3748 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3750 "import routes from non-main kernel table\n"
3751 "kernel routing table id\n"
3752 "Distance for imported routes\n"
3753 "Default distance value\n"
3754 "route-map for filtering\n"
3757 uint32_t table_id
= 0;
3759 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3760 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3762 strmatch(argv
[argc
- 2]->text
, "route-map")
3763 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3767 if (argc
== 7 || (argc
== 5 && !rmap
))
3768 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3770 if (!is_zebra_valid_kernel_table(table_id
)) {
3772 "Invalid routing table ID, %d. Must be in range 1-252\n",
3775 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3779 if (is_zebra_main_routing_table(table_id
)) {
3781 "Invalid routing table ID, %d. Must be non-default table\n",
3784 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3788 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3791 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3796 DEFUN_HIDDEN (zebra_packet_process
,
3797 zebra_packet_process_cmd
,
3798 "zebra zapi-packets (1-10000)",
3801 "Number of packets to process before relinquishing thread\n")
3803 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3805 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3806 memory_order_relaxed
);
3811 DEFUN_HIDDEN (no_zebra_packet_process
,
3812 no_zebra_packet_process_cmd
,
3813 "no zebra zapi-packets [(1-10000)]",
3817 "Number of packets to process before relinquishing thread\n")
3819 atomic_store_explicit(&zrouter
.packets_to_process
,
3820 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3821 memory_order_relaxed
);
3826 DEFUN_HIDDEN (zebra_workqueue_timer
,
3827 zebra_workqueue_timer_cmd
,
3828 "zebra work-queue (0-10000)",
3831 "Time in milliseconds\n")
3833 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3834 zrouter
.ribq
->spec
.hold
= timer
;
3839 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3840 no_zebra_workqueue_timer_cmd
,
3841 "no zebra work-queue [(0-10000)]",
3845 "Time in milliseconds\n")
3847 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3852 DEFUN (no_ip_zebra_import_table
,
3853 no_ip_zebra_import_table_cmd
,
3854 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3857 "import routes from non-main kernel table\n"
3858 "kernel routing table id\n"
3859 "Distance for imported routes\n"
3860 "Default distance value\n"
3861 "route-map for filtering\n"
3864 uint32_t table_id
= 0;
3865 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3867 if (!is_zebra_valid_kernel_table(table_id
)) {
3869 "Invalid routing table ID. Must be in range 1-252\n");
3873 if (is_zebra_main_routing_table(table_id
)) {
3875 "Invalid routing table ID, %d. Must be non-default table\n",
3880 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3883 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3886 DEFPY (zebra_nexthop_group_keep
,
3887 zebra_nexthop_group_keep_cmd
,
3888 "[no] zebra nexthop-group keep (1-3600)",
3892 "How long to keep\n"
3893 "Time in seconds from 1-3600\n")
3896 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3898 zrouter
.nhg_keep
= keep
;
3903 static int config_write_protocol(struct vty
*vty
)
3905 if (zrouter
.allow_delete
)
3906 vty_out(vty
, "allow-external-route-update\n");
3908 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3909 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3911 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3912 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3914 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3915 vty_out(vty
, "zebra zapi-packets %u\n",
3916 zrouter
.packets_to_process
);
3918 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3920 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3921 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3922 ipv4_multicast_mode
== MCAST_URIB_ONLY
3924 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3926 : ipv4_multicast_mode
3927 == MCAST_MIX_MRIB_FIRST
3929 : ipv4_multicast_mode
3930 == MCAST_MIX_DISTANCE
3934 /* Include dataplane info */
3935 dplane_config_write_helper(vty
);
3937 zebra_evpn_mh_config_write(vty
);
3939 zebra_pbr_config_write(vty
);
3941 if (!zebra_vxlan_get_accept_bgp_seq())
3942 vty_out(vty
, "no evpn accept-bgp-seq\n");
3944 /* Include nexthop-group config */
3945 if (!zebra_nhg_kernel_nexthops_enabled())
3946 vty_out(vty
, "no zebra nexthop kernel enable\n");
3948 if (zebra_nhg_proto_nexthops_only())
3949 vty_out(vty
, "zebra nexthop proto only\n");
3951 if (!zebra_nhg_recursive_use_backups())
3952 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3954 if (rnh_get_hide_backups())
3955 vty_out(vty
, "ip nht hide-backup-events\n");
3958 /* Include netlink info */
3959 netlink_config_write_helper(vty
);
3960 #endif /* HAVE_NETLINK */
3972 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3975 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3976 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3977 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3978 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3979 ttable_add_row(table
, "v6 Forwarding|%s",
3980 ipforward_ipv6() ? "On" : "Off");
3981 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3982 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3983 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3987 if (!vrf_is_backend_netns())
3988 ttable_add_row(table
, "VRF|l3mdev Available");
3990 ttable_add_row(table
, "VRF|Namespaces");
3992 ttable_add_row(table
, "VRF|Not Available");
3995 ttable_add_row(table
, "ASIC offload|%s",
3996 zrouter
.asic_offloaded
? "Used" : "Unavailable");
3999 * Do not display this unless someone is actually using it
4001 * Why this distinction? I think this is effectively dead code
4002 * and should not be exposed. Maybe someone proves me wrong.
4004 if (zrouter
.asic_notification_nexthop_control
)
4005 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4007 ttable_add_row(table
, "RA|%s",
4008 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4009 ttable_add_row(table
, "RFC 5549|%s",
4010 rtadv_get_interfaces_configured_from_bgp()
4012 : "BGP is not using");
4014 ttable_add_row(table
, "Kernel NHG|%s",
4015 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4017 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4018 zrouter
.allow_delete
? "Yes" : "No");
4019 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4020 zrouter
.all_linkdownv4
? "On" : "Off");
4021 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4022 zrouter
.default_linkdownv4
? "On" : "Off");
4023 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4024 zrouter
.all_linkdownv6
? "On" : "Off");
4025 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4026 zrouter
.default_linkdownv6
? "On" : "Off");
4028 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4029 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4030 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4031 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4032 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4033 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4034 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4035 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4037 out
= ttable_dump(table
, "\n");
4038 vty_out(vty
, "%s\n", out
);
4039 XFREE(MTYPE_TMP
, out
);
4043 " Route Route Neighbor LSP LSP\n");
4045 "VRF Installs Removals Updates Installs Removals\n");
4047 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4048 struct zebra_vrf
*zvrf
= vrf
->info
;
4050 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4051 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4052 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4053 zvrf
->lsp_removals
);
4059 DEFUN (ip_forwarding
,
4063 "Turn on IP forwarding\n")
4069 ret
= ipforward_on();
4072 vty_out(vty
, "Can't turn on IP forwarding\n");
4073 return CMD_WARNING_CONFIG_FAILED
;
4079 DEFUN (no_ip_forwarding
,
4080 no_ip_forwarding_cmd
,
4084 "Turn off IP forwarding\n")
4090 ret
= ipforward_off();
4093 vty_out(vty
, "Can't turn off IP forwarding\n");
4094 return CMD_WARNING_CONFIG_FAILED
;
4100 /* Only display ip forwarding is enabled or not. */
4101 DEFUN (show_ip_forwarding
,
4102 show_ip_forwarding_cmd
,
4103 "show ip forwarding",
4106 "IP forwarding status\n")
4113 vty_out(vty
, "IP forwarding is off\n");
4115 vty_out(vty
, "IP forwarding is on\n");
4119 /* Only display ipv6 forwarding is enabled or not. */
4120 DEFUN (show_ipv6_forwarding
,
4121 show_ipv6_forwarding_cmd
,
4122 "show ipv6 forwarding",
4124 "IPv6 information\n"
4125 "Forwarding status\n")
4129 ret
= ipforward_ipv6();
4133 vty_out(vty
, "ipv6 forwarding is unknown\n");
4136 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4139 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4142 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4148 DEFUN (ipv6_forwarding
,
4149 ipv6_forwarding_cmd
,
4152 "Turn on IPv6 forwarding\n")
4156 ret
= ipforward_ipv6();
4158 ret
= ipforward_ipv6_on();
4161 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4162 return CMD_WARNING_CONFIG_FAILED
;
4168 DEFUN (no_ipv6_forwarding
,
4169 no_ipv6_forwarding_cmd
,
4170 "no ipv6 forwarding",
4173 "Turn off IPv6 forwarding\n")
4177 ret
= ipforward_ipv6();
4179 ret
= ipforward_ipv6_off();
4182 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4183 return CMD_WARNING_CONFIG_FAILED
;
4189 /* Display dataplane info */
4190 DEFUN (show_dataplane
,
4192 "show zebra dplane [detailed]",
4195 "Zebra dataplane information\n"
4196 "Detailed output\n")
4199 bool detailed
= false;
4201 if (argv_find(argv
, argc
, "detailed", &idx
))
4204 return dplane_show_helper(vty
, detailed
);
4207 /* Display dataplane providers info */
4208 DEFUN (show_dataplane_providers
,
4209 show_dataplane_providers_cmd
,
4210 "show zebra dplane providers [detailed]",
4213 "Zebra dataplane information\n"
4214 "Zebra dataplane provider information\n"
4215 "Detailed output\n")
4218 bool detailed
= false;
4220 if (argv_find(argv
, argc
, "detailed", &idx
))
4223 return dplane_show_provs_helper(vty
, detailed
);
4226 /* Configure dataplane incoming queue limit */
4227 DEFUN (zebra_dplane_queue_limit
,
4228 zebra_dplane_queue_limit_cmd
,
4229 "zebra dplane limit (0-10000)",
4232 "Limit incoming queued updates\n"
4233 "Number of queued updates\n")
4237 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4239 dplane_set_in_queue_limit(limit
, true);
4244 /* Reset dataplane queue limit to default value */
4245 DEFUN (no_zebra_dplane_queue_limit
,
4246 no_zebra_dplane_queue_limit_cmd
,
4247 "no zebra dplane limit [(0-10000)]",
4251 "Limit incoming queued updates\n"
4252 "Number of queued updates\n")
4254 dplane_set_in_queue_limit(0, false);
4259 DEFUN (zebra_show_routing_tables_summary
,
4260 zebra_show_routing_tables_summary_cmd
,
4261 "show zebra router table summary",
4264 "The Zebra Router Information\n"
4265 "Table Information about this Zebra Router\n"
4266 "Summary Information\n")
4268 zebra_router_show_table_summary(vty
);
4273 /* Table configuration write function. */
4274 static int config_write_table(struct vty
*vty
)
4279 /* IPForwarding configuration write function. */
4280 static int config_write_forwarding(struct vty
*vty
)
4283 vty_out(vty
, "no ip forwarding\n");
4284 if (!ipforward_ipv6())
4285 vty_out(vty
, "no ipv6 forwarding\n");
4286 vty_out(vty
, "!\n");
4290 DEFUN_HIDDEN (show_frr
,
4296 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4297 vty_out(vty
, ".............................7777:..............................................\n");
4298 vty_out(vty
, ".............................777777,............................................\n");
4299 vty_out(vty
, "... .........................77777777,..........................................\n");
4300 vty_out(vty
, "............................=7777777777:........................................\n");
4301 vty_out(vty
, "........................:7777777777777777,......................................\n");
4302 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4303 vty_out(vty
, "...................I7777777777+.................................................\n");
4304 vty_out(vty
, "................,777777777?............ .......................................\n");
4305 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4306 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4307 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4308 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4309 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4310 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4311 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4312 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4313 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4314 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4315 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4316 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4317 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4318 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4319 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4320 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4321 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4322 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4323 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4324 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4325 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4326 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4327 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4328 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4329 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4330 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4331 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4332 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4333 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4334 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4335 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4336 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4337 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4338 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4339 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4340 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4341 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4342 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4343 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4344 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4345 vty_out(vty
, "................................~77777777...............=777777.................\n");
4346 vty_out(vty
, ".....................................:=?I................~777777................\n");
4347 vty_out(vty
, "..........................................................:777777,..............\n");
4348 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4354 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4355 zebra_kernel_netlink_batch_tx_buf_cmd
,
4356 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4358 "Zebra kernel interface\n"
4359 "Set Netlink parameters\n"
4360 "Set batch buffer size and send threshold\n"
4361 "Size of the buffer\n"
4364 uint32_t bufsize
= 0, threshold
= 0;
4366 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4367 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4369 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4374 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4375 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4376 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4378 "Zebra kernel interface\n"
4379 "Set Netlink parameters\n"
4380 "Set batch buffer size and send threshold\n"
4381 "Size of the buffer\n"
4384 netlink_set_batch_buffer_size(0, 0, false);
4389 DEFPY (zebra_protodown_bit
,
4390 zebra_protodown_bit_cmd
,
4391 "zebra protodown reason-bit (0-31)$bit",
4393 "Protodown Configuration\n"
4394 "Reason Bit used in the kernel for application\n"
4395 "Reason Bit range\n")
4397 if_netlink_set_frr_protodown_r_bit(bit
);
4401 DEFPY (no_zebra_protodown_bit
,
4402 no_zebra_protodown_bit_cmd
,
4403 "no zebra protodown reason-bit [(0-31)$bit]",
4406 "Protodown Configuration\n"
4407 "Reason Bit used in the kernel for setting protodown\n"
4408 "Reason Bit Range\n")
4410 if_netlink_unset_frr_protodown_r_bit();
4414 #endif /* HAVE_NETLINK */
4416 DEFUN(ip_table_range
, ip_table_range_cmd
,
4417 "[no] ip table range (1-4294967295) (1-4294967295)",
4419 "table configuration\n"
4420 "Configure table range\n"
4421 "Start Routing Table\n"
4422 "End Routing Table\n")
4424 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4429 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4431 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4435 if (strmatch(argv
[0]->text
, "no"))
4436 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4438 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4441 #ifdef HAVE_SCRIPTING
4443 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4444 "zebra on-rib-process script SCRIPT",
4446 "on_rib_process_dplane_results hook call\n"
4448 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4451 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4454 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4455 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4457 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4458 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4463 #endif /* HAVE_SCRIPTING */
4465 /* IP node for static routes. */
4466 static int zebra_ip_config(struct vty
*vty
);
4467 static struct cmd_node ip_node
= {
4468 .name
= "static ip",
4471 .config_write
= zebra_ip_config
,
4473 static int config_write_protocol(struct vty
*vty
);
4474 static struct cmd_node protocol_node
= {
4476 .node
= PROTOCOL_NODE
,
4478 .config_write
= config_write_protocol
,
4480 /* table node for routing tables. */
4481 static int config_write_table(struct vty
*vty
);
4482 static struct cmd_node table_node
= {
4486 .config_write
= config_write_table
,
4488 static int config_write_forwarding(struct vty
*vty
);
4489 static struct cmd_node forwarding_node
= {
4490 .name
= "forwarding",
4491 .node
= FORWARDING_NODE
,
4493 .config_write
= config_write_forwarding
,
4497 void zebra_vty_init(void)
4499 /* Install configuration write function. */
4500 install_node(&table_node
);
4501 install_node(&forwarding_node
);
4503 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4504 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4505 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4506 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4508 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4509 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4510 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4513 zebra_route_map_init();
4515 install_node(&ip_node
);
4516 install_node(&protocol_node
);
4518 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4519 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4521 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4522 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4524 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4525 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4526 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4527 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4528 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4529 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4530 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4531 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4532 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4533 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4535 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4536 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4538 install_element(VIEW_NODE
, &show_vrf_cmd
);
4539 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4540 install_element(VIEW_NODE
, &show_route_cmd
);
4541 install_element(VIEW_NODE
, &show_ro_cmd
);
4542 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4543 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4544 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4546 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4547 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4549 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4550 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4551 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4552 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4553 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4554 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4555 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4556 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4557 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4559 install_element(VIEW_NODE
, &show_frr_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4574 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4575 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4576 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4577 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4578 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4579 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4580 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4581 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4582 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4583 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4584 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4585 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4586 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4587 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4588 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4589 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4590 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4591 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4592 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4594 install_element(VIEW_NODE
, &show_neigh_cmd
);
4596 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4597 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4598 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4599 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4600 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4602 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4603 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4604 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4605 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4606 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4607 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4608 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4609 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4611 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4612 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4613 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4614 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4616 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4617 install_element(VRF_NODE
, &ip_table_range_cmd
);
4620 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4621 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4622 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4623 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4624 #endif /* HAVE_NETLINK */
4626 #ifdef HAVE_SCRIPTING
4627 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4628 #endif /* HAVE_SCRIPTING */
4630 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);