1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2002 Kunihiro Ishiguro
19 #include "srcdest_table.h"
21 #include "termtable.h"
22 #include "affinitymap.h"
24 #include "zebra/zebra_router.h"
25 #include "zebra/zserv.h"
26 #include "zebra/zebra_vrf.h"
27 #include "zebra/zebra_mpls.h"
28 #include "zebra/zebra_rnh.h"
29 #include "zebra/redistribute.h"
30 #include "zebra/zebra_affinitymap.h"
31 #include "zebra/zebra_routemap.h"
33 #include "lib/route_opaque.h"
34 #include "zebra/zebra_vxlan.h"
35 #include "zebra/zebra_evpn_mh.h"
36 #include "zebra/zebra_vty_clippy.c"
37 #include "zebra/zserv.h"
38 #include "zebra/router-id.h"
39 #include "zebra/ipforward.h"
40 #include "zebra/zebra_vxlan_private.h"
41 #include "zebra/zebra_pbr.h"
42 #include "zebra/zebra_nhg.h"
43 #include "zebra/zebra_evpn_mh.h"
44 #include "zebra/interface.h"
45 #include "northbound_cli.h"
46 #include "zebra/zebra_nb.h"
47 #include "zebra/kernel_netlink.h"
48 #include "zebra/if_netlink.h"
49 #include "zebra/table_manager.h"
50 #include "zebra/zebra_script.h"
51 #include "zebra/rtadv.h"
52 #include "zebra/zebra_neigh.h"
54 /* context to manage dumps in multiple tables or vrfs */
55 struct route_show_ctx
{
56 bool multi
; /* dump multiple tables or vrf */
57 bool header_done
; /* common header already displayed */
60 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
61 safi_t safi
, bool use_fib
, bool use_json
,
63 const struct prefix
*longer_prefix_p
,
64 bool supernets_only
, int type
,
65 unsigned short ospf_instance_id
, uint32_t tableid
,
66 bool show_ng
, struct route_show_ctx
*ctx
);
67 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
68 int mcast
, bool use_fib
, bool show_ng
);
69 static void vty_show_ip_route_summary(struct vty
*vty
,
70 struct route_table
*table
, bool use_json
);
71 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
72 struct route_table
*table
,
74 /* Helper api to format a nexthop in the 'detailed' output path. */
75 static void show_nexthop_detail_helper(struct vty
*vty
,
76 const struct route_entry
*re
,
77 const struct nexthop
*nexthop
,
80 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
81 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
82 struct route_entry
*re
, unsigned int num
);
84 DEFUN (ip_multicast_mode
,
85 ip_multicast_mode_cmd
,
86 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
89 "RPF lookup behavior\n"
90 "Lookup in unicast RIB only\n"
91 "Lookup in multicast RIB only\n"
92 "Try multicast RIB first, fall back to unicast RIB\n"
93 "Lookup both, use entry with lower distance\n"
94 "Lookup both, use entry with longer prefix\n")
96 char *mode
= argv
[3]->text
;
98 if (strmatch(mode
, "urib-only"))
99 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
100 else if (strmatch(mode
, "mrib-only"))
101 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
102 else if (strmatch(mode
, "mrib-then-urib"))
103 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
104 else if (strmatch(mode
, "lower-distance"))
105 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
106 else if (strmatch(mode
, "longer-prefix"))
107 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
109 vty_out(vty
, "Invalid mode specified\n");
110 return CMD_WARNING_CONFIG_FAILED
;
116 DEFUN (no_ip_multicast_mode
,
117 no_ip_multicast_mode_cmd
,
118 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
121 "Multicast options\n"
122 "RPF lookup behavior\n"
123 "Lookup in unicast RIB only\n"
124 "Lookup in multicast RIB only\n"
125 "Try multicast RIB first, fall back to unicast RIB\n"
126 "Lookup both, use entry with lower distance\n"
127 "Lookup both, use entry with longer prefix\n")
129 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
136 "show ip rpf [json]",
139 "Display RPF information for multicast source\n"
142 bool uj
= use_json(argc
, argv
);
143 struct route_show_ctx ctx
= {
147 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
148 false, uj
, 0, NULL
, false, 0, 0, 0, false,
152 DEFUN (show_ip_rpf_addr
,
153 show_ip_rpf_addr_cmd
,
154 "show ip rpf A.B.C.D",
157 "Display RPF information for multicast source\n"
158 "IP multicast source address (e.g. 10.0.0.0)\n")
162 struct route_node
*rn
;
163 struct route_entry
*re
;
166 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
168 vty_out(vty
, "%% Malformed address\n");
172 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
175 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
177 vty_out(vty
, "%% No match for RPF lookup\n");
182 static char re_status_output_char(const struct route_entry
*re
,
183 const struct nexthop
*nhop
,
186 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
190 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
191 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
192 /* More-specific test for 'fib' output */
194 star_p
= !!CHECK_FLAG(nhop
->flags
,
200 if (zrouter
.asic_offloaded
&&
201 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
204 if (zrouter
.asic_offloaded
205 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
208 if (zrouter
.asic_offloaded
209 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
212 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
221 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
222 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
228 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
235 * Show backup nexthop info, in the 'detailed' output path
237 static void show_nh_backup_helper(struct vty
*vty
,
238 const struct route_entry
*re
,
239 const struct nexthop
*nexthop
)
241 const struct nexthop
*start
, *backup
, *temp
;
244 /* Double-check that there _is_ a backup */
245 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
246 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
247 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
250 /* Locate the backup nexthop(s) */
251 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
252 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
253 /* Format the backup(s) (indented) */
255 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
256 backup
= backup
->next
;
261 /* It's possible for backups to be recursive too,
262 * so walk the recursive resolution list if present.
267 show_nexthop_detail_helper(vty
, re
, backup
,
271 if (backup
->resolved
&& temp
== backup
)
272 backup
= backup
->resolved
;
274 backup
= nexthop_next(backup
);
276 if (backup
== temp
->next
)
284 * Helper api to format output for a nexthop, used in the 'detailed'
287 static void show_nexthop_detail_helper(struct vty
*vty
,
288 const struct route_entry
*re
,
289 const struct nexthop
*nexthop
,
293 char buf
[MPLS_LABEL_STRLEN
];
298 nexthop
->rparent
? " " : "");
300 vty_out(vty
, " %c%s",
301 re_status_output_char(re
, nexthop
, false),
302 nexthop
->rparent
? " " : "");
304 switch (nexthop
->type
) {
305 case NEXTHOP_TYPE_IPV4
:
306 case NEXTHOP_TYPE_IPV4_IFINDEX
:
307 vty_out(vty
, " %pI4",
308 &nexthop
->gate
.ipv4
);
309 if (nexthop
->ifindex
)
310 vty_out(vty
, ", via %s",
315 case NEXTHOP_TYPE_IPV6
:
316 case NEXTHOP_TYPE_IPV6_IFINDEX
:
318 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
320 if (nexthop
->ifindex
)
321 vty_out(vty
, ", via %s",
327 case NEXTHOP_TYPE_IFINDEX
:
328 vty_out(vty
, " directly connected, %s",
329 ifindex2ifname(nexthop
->ifindex
,
332 case NEXTHOP_TYPE_BLACKHOLE
:
333 vty_out(vty
, " unreachable");
334 switch (nexthop
->bh_type
) {
335 case BLACKHOLE_REJECT
:
336 vty_out(vty
, " (ICMP unreachable)");
338 case BLACKHOLE_ADMINPROHIB
:
340 " (ICMP admin-prohibited)");
343 vty_out(vty
, " (blackhole)");
345 case BLACKHOLE_UNSPEC
:
351 if (re
->vrf_id
!= nexthop
->vrf_id
) {
352 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
354 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
357 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
358 vty_out(vty
, " (duplicate nexthop removed)");
360 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
361 vty_out(vty
, " inactive");
363 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
364 vty_out(vty
, " onlink");
366 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
367 vty_out(vty
, " linkdown");
369 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
370 vty_out(vty
, " (recursive)");
372 /* Source specified? */
373 switch (nexthop
->type
) {
374 case NEXTHOP_TYPE_IPV4
:
375 case NEXTHOP_TYPE_IPV4_IFINDEX
:
376 if (nexthop
->src
.ipv4
.s_addr
) {
377 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
378 addrstr
, sizeof(addrstr
)))
379 vty_out(vty
, ", src %s",
384 case NEXTHOP_TYPE_IPV6
:
385 case NEXTHOP_TYPE_IPV6_IFINDEX
:
386 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
388 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
389 addrstr
, sizeof(addrstr
)))
390 vty_out(vty
, ", src %s",
395 case NEXTHOP_TYPE_IFINDEX
:
396 case NEXTHOP_TYPE_BLACKHOLE
:
401 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
403 /* Label information */
404 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
405 vty_out(vty
, ", label %s",
406 mpls_label2str(nexthop
->nh_label
->num_labels
,
407 nexthop
->nh_label
->label
, buf
,
408 sizeof(buf
), nexthop
->nh_label_type
,
413 vty_out(vty
, ", weight %u", nexthop
->weight
);
415 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
416 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
418 for (i
= 1; i
< nexthop
->backup_num
; i
++)
419 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
423 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
424 struct json_object
*json
)
426 struct bgp_zebra_opaque bzo
= {};
427 struct ospf_zebra_opaque ozo
= {};
433 case ZEBRA_ROUTE_SHARP
:
435 json_object_string_add(json
, "opaque",
436 (char *)re
->opaque
->data
);
438 vty_out(vty
, " Opaque Data: %s",
439 (char *)re
->opaque
->data
);
442 case ZEBRA_ROUTE_BGP
:
443 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
446 json_object_string_add(json
, "asPath", bzo
.aspath
);
447 json_object_string_add(json
, "communities",
449 json_object_string_add(json
, "largeCommunities",
451 json_object_string_add(json
, "selectionReason",
452 bzo
.selection_reason
);
454 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
456 if (bzo
.community
[0] != '\0')
457 vty_out(vty
, " Communities : %s\n",
460 if (bzo
.lcommunity
[0] != '\0')
461 vty_out(vty
, " Large-Communities: %s\n",
464 vty_out(vty
, " Selection reason : %s\n",
465 bzo
.selection_reason
);
468 case ZEBRA_ROUTE_OSPF
:
469 case ZEBRA_ROUTE_OSPF6
:
470 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
473 json_object_string_add(json
, "ospfPathType",
475 if (ozo
.area_id
[0] != '\0')
476 json_object_string_add(json
, "ospfAreaId",
478 if (ozo
.tag
[0] != '\0')
479 json_object_string_add(json
, "ospfTag",
482 vty_out(vty
, " OSPF path type : %s\n",
484 if (ozo
.area_id
[0] != '\0')
485 vty_out(vty
, " OSPF area ID : %s\n",
487 if (ozo
.tag
[0] != '\0')
488 vty_out(vty
, " OSPF tag : %s\n",
497 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
501 cur
= monotime(NULL
);
504 frrtime_to_interval(cur
, buf
, bufsize
);
507 /* New RIB. Detailed information for IPv4 route. */
508 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
509 int mcast
, bool use_fib
, bool show_ng
)
511 struct route_entry
*re
;
512 struct nexthop
*nexthop
;
513 char buf
[SRCDEST2STR_BUFFER
];
514 struct zebra_vrf
*zvrf
;
517 dest
= rib_dest_from_rnode(rn
);
519 RNODE_FOREACH_RE (rn
, re
) {
521 * If re not selected for forwarding, skip re
522 * for "show ip/ipv6 fib <prefix>"
524 if (use_fib
&& re
!= dest
->selected_fib
)
527 const char *mcast_info
= "";
529 struct rib_table_info
*info
=
530 srcdest_rnode_table_info(rn
);
531 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
532 ? " using Multicast RIB"
533 : " using Unicast RIB";
536 vty_out(vty
, "Routing entry for %s%s\n",
537 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
538 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
540 vty_out(vty
, "[%d]", re
->instance
);
542 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
545 vty_out(vty
, ", tag %u", re
->tag
);
546 #if defined(SUPPORT_REALMS)
547 if (re
->tag
> 0 && re
->tag
<= 255)
548 vty_out(vty
, "(realm)");
552 vty_out(vty
, ", mtu %u", re
->mtu
);
553 if (re
->vrf_id
!= VRF_DEFAULT
) {
554 zvrf
= vrf_info_lookup(re
->vrf_id
);
555 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
557 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
558 vty_out(vty
, ", best");
561 uptime2str(re
->uptime
, buf
, sizeof(buf
));
563 vty_out(vty
, " Last update %s ago\n", buf
);
566 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
567 if (re
->nhe_installed_id
!= 0
568 && re
->nhe_id
!= re
->nhe_installed_id
)
570 " Installed Nexthop Group ID: %u\n",
571 re
->nhe_installed_id
);
574 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
575 /* Use helper to format each nexthop */
576 show_nexthop_detail_helper(vty
, re
, nexthop
,
577 false /*not backup*/);
580 /* Include backup(s), if present */
581 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
582 show_nh_backup_helper(vty
, re
, nexthop
);
584 zebra_show_ip_route_opaque(vty
, re
, NULL
);
590 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
591 struct route_entry
*re
, json_object
*json
,
592 bool is_fib
, bool show_ng
)
594 const struct nexthop
*nexthop
;
596 char buf
[SRCDEST2STR_BUFFER
];
597 json_object
*json_nexthops
= NULL
;
598 json_object
*json_nexthop
= NULL
;
599 json_object
*json_route
= NULL
;
600 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
601 const struct nexthop_group
*nhg
;
602 char up_str
[MONOTIME_STRLEN
];
604 bool nhg_from_backup
= false;
606 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
608 /* If showing fib information, use the fib view of the
612 nhg
= rib_get_fib_nhg(re
);
614 nhg
= &(re
->nhe
->nhg
);
617 json_route
= json_object_new_object();
618 json_nexthops
= json_object_new_array();
620 json_object_string_add(json_route
, "prefix",
621 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
622 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
623 json_object_string_add(json_route
, "protocol",
624 zebra_route_string(re
->type
));
627 json_object_int_add(json_route
, "instance",
630 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
631 json_object_string_add(json_route
, "vrfName",
632 vrf_id_to_name(re
->vrf_id
));
634 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
635 json_object_boolean_true_add(json_route
, "selected");
637 if (dest
->selected_fib
== re
)
638 json_object_boolean_true_add(json_route
,
641 json_object_int_add(json_route
, "distance",
643 json_object_int_add(json_route
, "metric", re
->metric
);
645 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
646 json_object_boolean_true_add(json_route
, "installed");
648 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
649 json_object_boolean_true_add(json_route
, "failed");
651 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
652 json_object_boolean_true_add(json_route
, "queued");
654 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
655 json_object_boolean_true_add(json_route
, "trapped");
657 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
658 json_object_boolean_true_add(json_route
, "offloaded");
660 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
661 json_object_boolean_false_add(json_route
, "offloaded");
664 json_object_int_add(json_route
, "tag", re
->tag
);
667 json_object_int_add(json_route
, "table", re
->table
);
669 json_object_int_add(json_route
, "internalStatus",
671 json_object_int_add(json_route
, "internalFlags",
673 json_object_int_add(json_route
, "internalNextHopNum",
674 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
675 json_object_int_add(json_route
, "internalNextHopActiveNum",
676 nexthop_group_active_nexthop_num(
678 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
680 if (re
->nhe_installed_id
!= 0)
681 json_object_int_add(json_route
,
682 "installedNexthopGroupId",
683 re
->nhe_installed_id
);
685 json_object_string_add(json_route
, "uptime", up_str
);
687 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
688 json_nexthop
= json_object_new_object();
689 show_nexthop_json_helper(json_nexthop
,
692 json_object_array_add(json_nexthops
,
696 json_object_object_add(json_route
, "nexthops", json_nexthops
);
698 /* If there are backup nexthops, include them */
700 nhg
= rib_get_fib_backup_nhg(re
);
702 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
704 if (nhg
&& nhg
->nexthop
) {
705 json_nexthops
= json_object_new_array();
707 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
708 json_nexthop
= json_object_new_object();
710 show_nexthop_json_helper(json_nexthop
,
712 json_object_array_add(json_nexthops
,
716 json_object_object_add(json_route
, "backupNexthops",
719 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
721 json_object_array_add(json
, json_route
);
725 /* Prefix information, and first nexthop. If we're showing 'fib',
726 * and there are no installed primary nexthops, see if there are any
727 * backup nexthops and start with those.
729 if (is_fib
&& nhg
->nexthop
== NULL
) {
730 nhg
= rib_get_fib_backup_nhg(re
);
731 nhg_from_backup
= true;
734 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
736 len
+= vty_out(vty
, "[%d]", re
->instance
);
737 if (nhg_from_backup
&& nhg
->nexthop
) {
740 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
741 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
742 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
746 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
747 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
748 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
751 /* Distance and metric display. */
752 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
753 (re
->distance
|| re
->metric
)) ||
754 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
755 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
759 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
761 /* Nexthop information. */
762 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
765 } else if (nhg_from_backup
) {
766 vty_out(vty
, " b%c%*c",
767 re_status_output_char(re
, nexthop
, is_fib
),
768 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
770 vty_out(vty
, " %c%*c",
771 re_status_output_char(re
, nexthop
, is_fib
),
772 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
775 show_route_nexthop_helper(vty
, re
, nexthop
);
776 vty_out(vty
, ", %s\n", up_str
);
779 /* If we only had backup nexthops, we're done */
783 /* Check for backup nexthop info if present */
785 nhg
= rib_get_fib_backup_nhg(re
);
787 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
792 /* Print backup info */
793 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
797 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
799 /* TODO -- it'd be nice to be able to include
800 * the entire list of backups, *and* include the
801 * real installation state.
803 vty_out(vty
, " b%c %*c",
804 (star_p
? '*' : ' '),
805 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
806 show_route_nexthop_helper(vty
, re
, nexthop
);
812 static void vty_show_ip_route_detail_json(struct vty
*vty
,
813 struct route_node
*rn
, bool use_fib
)
815 json_object
*json
= NULL
;
816 json_object
*json_prefix
= NULL
;
817 struct route_entry
*re
;
821 dest
= rib_dest_from_rnode(rn
);
823 json
= json_object_new_object();
824 json_prefix
= json_object_new_array();
826 RNODE_FOREACH_RE (rn
, re
) {
828 * If re not selected for forwarding, skip re
829 * for "show ip/ipv6 fib <prefix> json"
831 if (use_fib
&& re
!= dest
->selected_fib
)
833 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
836 prefix2str(&rn
->p
, buf
, sizeof(buf
));
837 json_object_object_add(json
, buf
, json_prefix
);
841 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
842 struct route_table
*table
, afi_t afi
,
843 bool use_fib
, route_tag_t tag
,
844 const struct prefix
*longer_prefix_p
,
845 bool supernets_only
, int type
,
846 unsigned short ospf_instance_id
, bool use_json
,
847 uint32_t tableid
, bool show_ng
,
848 struct route_show_ctx
*ctx
)
850 struct route_node
*rn
;
851 struct route_entry
*re
;
854 json_object
*json
= NULL
;
855 json_object
*json_prefix
= NULL
;
860 * ctx->multi indicates if we are dumping multiple tables or vrfs.
862 * => display the common header at most once
863 * => add newline at each call except first
864 * => always display the VRF and table
866 * => display the common header if at least one entry is found
867 * => display the VRF and table if specific
871 json
= json_object_new_object();
873 /* Show all routes. */
874 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
875 dest
= rib_dest_from_rnode(rn
);
877 RNODE_FOREACH_RE (rn
, re
) {
878 if (use_fib
&& re
!= dest
->selected_fib
)
881 if (tag
&& re
->tag
!= tag
)
885 && !prefix_match(longer_prefix_p
, &rn
->p
))
888 /* This can only be true when the afi is IPv4 */
889 if (supernets_only
) {
890 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
892 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
895 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
898 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
902 if (type
&& re
->type
!= type
)
906 && (re
->type
!= ZEBRA_ROUTE_OSPF
907 || re
->instance
!= ospf_instance_id
))
912 json_prefix
= json_object_new_array();
914 if (!ctx
->header_done
) {
917 SHOW_ROUTE_V4_HEADER
);
920 SHOW_ROUTE_V6_HEADER
);
922 if (ctx
->multi
&& ctx
->header_done
)
924 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
927 vty_out(vty
, "VRF %s:\n",
931 "VRF %s table %u:\n",
935 ctx
->header_done
= true;
939 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
944 prefix2str(&rn
->p
, buf
, sizeof(buf
));
945 json_object_object_add(json
, buf
, json_prefix
);
954 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
955 afi_t afi
, bool use_fib
, bool use_json
,
957 const struct prefix
*longer_prefix_p
,
958 bool supernets_only
, int type
,
959 unsigned short ospf_instance_id
, bool show_ng
,
960 struct route_show_ctx
*ctx
)
962 struct zebra_router_table
*zrt
;
963 struct rib_table_info
*info
;
965 RB_FOREACH (zrt
, zebra_router_table_head
,
967 info
= route_table_get_info(zrt
->table
);
969 if (zvrf
!= info
->zvrf
)
971 if (zrt
->afi
!= afi
||
972 zrt
->safi
!= SAFI_UNICAST
)
975 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
976 use_fib
, use_json
, tag
, longer_prefix_p
,
977 supernets_only
, type
, ospf_instance_id
,
978 zrt
->tableid
, show_ng
, ctx
);
982 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
983 safi_t safi
, bool use_fib
, bool use_json
,
985 const struct prefix
*longer_prefix_p
,
986 bool supernets_only
, int type
,
987 unsigned short ospf_instance_id
, uint32_t tableid
,
988 bool show_ng
, struct route_show_ctx
*ctx
)
990 struct route_table
*table
;
991 struct zebra_vrf
*zvrf
= NULL
;
993 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
995 vty_out(vty
, "{}\n");
997 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1001 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1003 vty_out(vty
, "{}\n");
1005 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1010 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1012 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1015 vty_out(vty
, "{}\n");
1019 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1020 longer_prefix_p
, supernets_only
, type
,
1021 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1028 "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]",
1032 "IP nexthop tracking table\n"
1033 "IP import check tracking table\n"
1039 VRF_ALL_CMD_HELP_STR
1040 "Show Multicast (MRIB) NHT state\n"
1043 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1044 vrf_id_t vrf_id
= VRF_DEFAULT
;
1045 struct prefix prefix
, *p
= NULL
;
1046 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1047 bool uj
= use_json(argc
, argv
);
1048 json_object
*json
= NULL
;
1049 json_object
*json_vrf
= NULL
;
1050 json_object
*json_nexthop
= NULL
;
1053 json
= json_object_new_object();
1057 struct zebra_vrf
*zvrf
;
1059 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1060 if ((zvrf
= vrf
->info
) != NULL
) {
1062 json_vrf
= json_object_new_object();
1063 json_nexthop
= json_object_new_object();
1064 json_object_object_add(json
,
1067 json_object_object_add(json_vrf
,
1073 vty_out(vty
, "\nVRF %s:\n",
1076 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1077 vty
, NULL
, json_nexthop
);
1082 vty_json(vty
, json
);
1087 VRF_GET_ID(vrf_id
, vrf_name
, false);
1089 memset(&prefix
, 0, sizeof(prefix
));
1091 p
= sockunion2hostprefix(addr
, &prefix
);
1094 json_object_free(json
);
1100 json_vrf
= json_object_new_object();
1101 json_nexthop
= json_object_new_object();
1103 json_object_object_add(json
, vrf_name
, json_vrf
);
1105 json_object_object_add(json
, "default", json_vrf
);
1107 json_object_object_add(json_vrf
,
1108 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1112 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1115 vty_json(vty
, json
);
1120 DEFUN (ip_nht_default_route
,
1121 ip_nht_default_route_cmd
,
1122 "ip nht resolve-via-default",
1124 "Filter Next Hop tracking route resolution\n"
1125 "Resolve via default route\n")
1127 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1132 if (zvrf
->zebra_rnh_ip_default_route
)
1135 zvrf
->zebra_rnh_ip_default_route
= true;
1137 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1141 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1142 json_object
*json_nhe_hdr
)
1144 struct nexthop
*nexthop
= NULL
;
1145 struct nhg_connected
*rb_node_dep
= NULL
;
1146 struct nexthop_group
*backup_nhg
;
1147 char up_str
[MONOTIME_STRLEN
];
1148 char time_left
[MONOTIME_STRLEN
];
1149 json_object
*json_dependants
= NULL
;
1150 json_object
*json_depends
= NULL
;
1151 json_object
*json_nexthop_array
= NULL
;
1152 json_object
*json_nexthops
= NULL
;
1153 json_object
*json
= NULL
;
1154 json_object
*json_backup_nexthop_array
= NULL
;
1155 json_object
*json_backup_nexthops
= NULL
;
1158 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1161 json
= json_object_new_object();
1164 json_object_string_add(json
, "type",
1165 zebra_route_string(nhe
->type
));
1166 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1167 if (thread_is_scheduled(nhe
->timer
))
1168 json_object_string_add(
1169 json
, "timeToDeletion",
1170 thread_timer_to_hhmmss(time_left
,
1173 json_object_string_add(json
, "uptime", up_str
);
1174 json_object_string_add(json
, "vrf",
1175 vrf_id_to_name(nhe
->vrf_id
));
1178 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1179 zebra_route_string(nhe
->type
));
1180 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1181 if (thread_is_scheduled(nhe
->timer
))
1182 vty_out(vty
, " Time to Deletion: %s",
1183 thread_timer_to_hhmmss(time_left
,
1188 vty_out(vty
, " Uptime: %s\n", up_str
);
1189 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1192 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1194 json_object_boolean_true_add(json
, "valid");
1196 vty_out(vty
, " Valid");
1198 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1200 json_object_boolean_true_add(json
, "installed");
1202 vty_out(vty
, ", Installed");
1209 json_object_int_add(json
, "interfaceIndex",
1212 vty_out(vty
, " Interface Index: %d\n",
1216 if (!zebra_nhg_depends_is_empty(nhe
)) {
1218 json_depends
= json_object_new_array();
1220 vty_out(vty
, " Depends:");
1221 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1223 json_object_array_add(
1225 json_object_new_int(
1226 rb_node_dep
->nhe
->id
));
1228 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1233 json_object_object_add(json
, "depends", json_depends
);
1236 /* Output nexthops */
1238 json_nexthop_array
= json_object_new_array();
1241 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1242 if (json_nexthop_array
) {
1243 json_nexthops
= json_object_new_object();
1244 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1246 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1249 /* Make recursive nexthops a bit more clear */
1251 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1254 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1255 if (CHECK_FLAG(nexthop
->flags
,
1256 NEXTHOP_FLAG_HAS_BACKUP
)) {
1258 json_object_int_add(
1259 json_nexthops
, "backup",
1260 nexthop
->backup_idx
[0]);
1262 vty_out(vty
, " [backup %d]",
1263 nexthop
->backup_idx
[0]);
1269 json_object_array_add(json_nexthop_array
,
1276 /* TODO -- print more useful backup info */
1277 if (CHECK_FLAG(nexthop
->flags
,
1278 NEXTHOP_FLAG_HAS_BACKUP
)) {
1281 vty_out(vty
, "[backup");
1282 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1284 nexthop
->backup_idx
[i
]);
1289 json_object_array_add(json_nexthop_array
,
1295 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1297 /* Output backup nexthops (if any) */
1298 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1301 json_backup_nexthop_array
= json_object_new_array();
1303 vty_out(vty
, " Backups:\n");
1305 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1306 if (json_backup_nexthop_array
) {
1307 json_backup_nexthops
= json_object_new_object();
1308 show_nexthop_json_helper(json_backup_nexthops
,
1310 json_object_array_add(json_backup_nexthop_array
,
1311 json_backup_nexthops
);
1314 if (!CHECK_FLAG(nexthop
->flags
,
1315 NEXTHOP_FLAG_RECURSIVE
))
1318 /* Make recursive nexthops a bit more
1322 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1328 json_object_object_add(json
, "backupNexthops",
1329 json_backup_nexthop_array
);
1332 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1334 json_dependants
= json_object_new_array();
1336 vty_out(vty
, " Dependents:");
1337 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1340 json_object_array_add(
1342 json_object_new_int(
1343 rb_node_dep
->nhe
->id
));
1345 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1348 json_object_object_add(json
, "dependents",
1354 if (nhe
->nhg
.nhgr
.buckets
) {
1356 json_object_int_add(json
, "buckets",
1357 nhe
->nhg
.nhgr
.buckets
);
1358 json_object_int_add(json
, "idleTimer",
1359 nhe
->nhg
.nhgr
.idle_timer
);
1360 json_object_int_add(json
, "unbalancedTimer",
1361 nhe
->nhg
.nhgr
.unbalanced_timer
);
1362 json_object_int_add(json
, "unbalancedTime",
1363 nhe
->nhg
.nhgr
.unbalanced_time
);
1366 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1368 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1369 nhe
->nhg
.nhgr
.unbalanced_timer
,
1370 nhe
->nhg
.nhgr
.unbalanced_time
);
1375 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1378 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1381 struct nhg_hash_entry
*nhe
= NULL
;
1383 nhe
= zebra_nhg_lookup_id(id
);
1386 show_nexthop_group_out(vty
, nhe
, json
);
1389 vty_json(vty
, json
);
1391 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1397 vty_json(vty
, json
);
1402 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1404 struct nhe_show_context
{
1412 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1414 struct nhe_show_context
*ctx
= arg
;
1415 struct nhg_hash_entry
*nhe
;
1417 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1419 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1422 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1425 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1428 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1431 return HASHWALK_CONTINUE
;
1434 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1435 struct zebra_vrf
*zvrf
, afi_t afi
,
1436 int type
, json_object
*json
)
1438 struct nhe_show_context ctx
;
1442 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1446 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1449 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1451 struct zebra_if
*zebra_if
= NULL
;
1452 struct nhg_connected
*rb_node_dep
= NULL
;
1454 zebra_if
= ifp
->info
;
1456 if (!if_nhg_dependents_is_empty(ifp
)) {
1457 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1459 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1462 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1467 DEFPY (show_interface_nexthop_group
,
1468 show_interface_nexthop_group_cmd
,
1469 "show interface [IFNAME$if_name] nexthop-group",
1471 "Interface status and configuration\n"
1473 "Show Nexthop Groups\n")
1475 struct vrf
*vrf
= NULL
;
1476 struct interface
*ifp
= NULL
;
1479 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1481 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1483 if_nexthop_group_dump_vty(vty
, ifp
);
1487 FOR_ALL_INTERFACES (vrf
, ifp
)
1488 if_nexthop_group_dump_vty(vty
, ifp
);
1494 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1501 DEFPY(show_nexthop_group
,
1502 show_nexthop_group_cmd
,
1503 "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]",
1505 "Show Nexthop Groups\n"
1507 "Nexthop Group ID\n"
1508 "Show Singleton Nexthop-Groups\n"
1511 "Kernel (not installed via the zebra RIB)\n"
1512 "Zebra (implicitly created by zebra)\n"
1513 "Border Gateway Protocol (BGP)\n"
1514 "Super Happy Advanced Routing Protocol (SHARP)\n"
1515 VRF_FULL_CMD_HELP_STR
1519 struct zebra_vrf
*zvrf
= NULL
;
1520 afi_t afi
= AFI_UNSPEC
;
1522 bool uj
= use_json(argc
, argv
);
1523 json_object
*json
= NULL
;
1524 json_object
*json_vrf
= NULL
;
1527 json
= json_object_new_object();
1530 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1538 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1541 type
= ZEBRA_ROUTE_NHG
;
1545 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1547 vty_json(vty
, json
);
1550 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1557 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1558 struct zebra_vrf
*zvrf
;
1564 json_vrf
= json_object_new_object();
1566 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1568 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1571 json_object_object_add(json
, vrf
->name
,
1576 vty_json(vty
, json
);
1582 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1584 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1588 vty_json(vty
, json
);
1590 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1595 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1598 vty_json(vty
, json
);
1603 DEFPY_HIDDEN(nexthop_group_use_enable
,
1604 nexthop_group_use_enable_cmd
,
1605 "[no] zebra nexthop kernel enable",
1608 "Nexthop configuration \n"
1609 "Configure use of kernel nexthops\n"
1610 "Enable kernel nexthops\n")
1612 zebra_nhg_enable_kernel_nexthops(!no
);
1616 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1617 "[no] zebra nexthop proto only",
1619 "Nexthop configuration\n"
1620 "Configure exclusive use of proto nexthops\n"
1621 "Only use proto nexthops\n")
1623 zebra_nhg_set_proto_nexthops_only(!no
);
1627 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1628 backup_nexthop_recursive_use_enable_cmd
,
1629 "[no] zebra nexthop resolve-via-backup",
1632 "Nexthop configuration \n"
1633 "Configure use of backup nexthops in recursive resolution\n")
1635 zebra_nhg_set_recursive_use_backups(!no
);
1639 DEFUN (no_ip_nht_default_route
,
1640 no_ip_nht_default_route_cmd
,
1641 "no ip nht resolve-via-default",
1644 "Filter Next Hop tracking route resolution\n"
1645 "Resolve via default route\n")
1647 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1652 if (!zvrf
->zebra_rnh_ip_default_route
)
1655 zvrf
->zebra_rnh_ip_default_route
= false;
1656 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1660 DEFUN (ipv6_nht_default_route
,
1661 ipv6_nht_default_route_cmd
,
1662 "ipv6 nht resolve-via-default",
1664 "Filter Next Hop tracking route resolution\n"
1665 "Resolve via default route\n")
1667 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1672 if (zvrf
->zebra_rnh_ipv6_default_route
)
1675 zvrf
->zebra_rnh_ipv6_default_route
= true;
1676 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1680 DEFUN (no_ipv6_nht_default_route
,
1681 no_ipv6_nht_default_route_cmd
,
1682 "no ipv6 nht resolve-via-default",
1685 "Filter Next Hop tracking route resolution\n"
1686 "Resolve via default route\n")
1688 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1693 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1696 zvrf
->zebra_rnh_ipv6_default_route
= false;
1697 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1701 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1702 "[no] ip nht hide-backup-events",
1705 "Nexthop-tracking configuration\n"
1706 "Hide notification about backup nexthops\n")
1708 rnh_set_hide_backups(!no
);
1716 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1717 [vrf <NAME$vrf_name|all$vrf_all>]\
1720 |A.B.C.D/M$prefix longer-prefixes\
1721 |supernets-only$supernets_only\
1724 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1725 |ospf$type_str (1-65535)$ospf_instance_id\
1727 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1728 [vrf <NAME$vrf_name|all$vrf_all>]\
1731 |X:X::X:X/M$prefix longer-prefixes\
1733 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1735 [<json$json|nexthop-group$ng>]",
1738 "IP forwarding table\n"
1739 "IP routing table\n"
1740 "Table to display\n"
1741 "The table number to display\n"
1743 VRF_FULL_CMD_HELP_STR
1744 "Show only routes with tag\n"
1746 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1747 "Show route matching the specified Network/Mask pair only\n"
1748 "Show supernet entries only\n"
1749 FRR_IP_REDIST_HELP_STR_ZEBRA
1750 "Open Shortest Path First (OSPFv2)\n"
1753 "IP forwarding table\n"
1754 "IP routing table\n"
1755 "Table to display\n"
1756 "The table number to display\n"
1758 VRF_FULL_CMD_HELP_STR
1759 "Show only routes with tag\n"
1762 "Show route matching the specified Network/Mask pair only\n"
1763 FRR_IP6_REDIST_HELP_STR_ZEBRA
1765 "Nexthop Group Information\n")
1767 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1770 struct zebra_vrf
*zvrf
;
1771 struct route_show_ctx ctx
= {
1772 .multi
= vrf_all
|| table_all
,
1775 if (!vrf_is_backend_netns()) {
1776 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1778 vty_out(vty
, "{}\n");
1780 vty_out(vty
, "Linux vrf backend already points to table id\n");
1781 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1787 type
= proto_redistnum(afi
, type_str
);
1789 vty_out(vty
, "Unknown route type\n");
1795 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1796 if ((zvrf
= vrf
->info
) == NULL
1797 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1801 do_show_ip_route_all(
1802 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1803 prefix_str
? prefix
: NULL
,
1804 !!supernets_only
, type
,
1805 ospf_instance_id
, !!ng
, &ctx
);
1808 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1810 prefix_str
? prefix
: NULL
,
1811 !!supernets_only
, type
,
1812 ospf_instance_id
, table
, !!ng
, &ctx
);
1815 vrf_id_t vrf_id
= VRF_DEFAULT
;
1818 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1819 vrf
= vrf_lookup_by_id(vrf_id
);
1828 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1829 prefix_str
? prefix
: NULL
,
1830 !!supernets_only
, type
,
1831 ospf_instance_id
, !!ng
, &ctx
);
1833 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1835 prefix_str
? prefix
: NULL
,
1836 !!supernets_only
, type
,
1837 ospf_instance_id
, table
, !!ng
, &ctx
);
1843 ALIAS_HIDDEN (show_route
,
1845 "show <ip$ipv4|ipv6$ipv6> ro",
1849 "IP routing table\n");
1852 DEFPY (show_route_detail
,
1853 show_route_detail_cmd
,
1856 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1861 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1867 [json$json] [nexthop-group$ng]",
1870 "IP forwarding table\n"
1871 "IP routing table\n"
1872 VRF_FULL_CMD_HELP_STR
1873 "Network in the IP routing table to display\n"
1874 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1876 "IPv6 forwarding table\n"
1877 "IPv6 routing table\n"
1878 VRF_FULL_CMD_HELP_STR
1882 "Nexthop Group Information\n")
1884 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1885 struct route_table
*table
;
1887 struct route_node
*rn
;
1888 bool use_fib
= !!fib
;
1890 bool network_found
= false;
1891 bool show_ng
= !!ng
;
1894 prefix_str
= address_str
;
1895 if (str2prefix(prefix_str
, &p
) < 0) {
1896 vty_out(vty
, "%% Malformed address\n");
1902 struct zebra_vrf
*zvrf
;
1904 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1905 if ((zvrf
= vrf
->info
) == NULL
1906 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1909 rn
= route_node_match(table
, &p
);
1912 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1913 route_unlock_node(rn
);
1917 dest
= rib_dest_from_rnode(rn
);
1918 if (use_fib
&& !dest
->selected_fib
) {
1919 route_unlock_node(rn
);
1923 network_found
= true;
1925 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1927 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1930 route_unlock_node(rn
);
1933 if (!network_found
) {
1935 vty_out(vty
, "{}\n");
1939 "%% Network not in FIB\n");
1942 "%% Network not in RIB\n");
1947 vrf_id_t vrf_id
= VRF_DEFAULT
;
1950 VRF_GET_ID(vrf_id
, vrf_name
, false);
1952 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1956 rn
= route_node_match(table
, &p
);
1958 dest
= rib_dest_from_rnode(rn
);
1960 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1961 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1963 vty_out(vty
, "{}\n");
1967 "%% Network not in FIB\n");
1970 "%% Network not in table\n");
1973 route_unlock_node(rn
);
1978 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1980 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1982 route_unlock_node(rn
);
1988 DEFPY (show_route_summary
,
1989 show_route_summary_cmd
,
1990 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
1991 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
1995 "IP routing table\n"
1996 VRF_FULL_CMD_HELP_STR
1997 "Summary of all routes\n"
1998 "Table to display summary for\n"
1999 "The table number\n"
2003 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2004 struct route_table
*table
;
2005 bool uj
= use_json(argc
, argv
);
2009 struct zebra_vrf
*zvrf
;
2011 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2012 if ((zvrf
= vrf
->info
) == NULL
)
2016 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2019 table
= zebra_vrf_lookup_table_with_table_id(
2020 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2027 vty_show_ip_route_summary_prefix(vty
, table
,
2030 vty_show_ip_route_summary(vty
, table
, uj
);
2033 vrf_id_t vrf_id
= VRF_DEFAULT
;
2036 VRF_GET_ID(vrf_id
, vrf_name
, false);
2039 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2041 table
= zebra_vrf_lookup_table_with_table_id(
2042 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2047 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2049 vty_show_ip_route_summary(vty
, table
, uj
);
2055 DEFUN_HIDDEN (show_route_zebra_dump
,
2056 show_route_zebra_dump_cmd
,
2057 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2067 struct route_table
*table
;
2068 const char *vrf_name
= NULL
;
2071 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2073 if (argv_find(argv
, argc
, "vrf", &idx
))
2074 vrf_name
= argv
[++idx
]->arg
;
2078 struct zebra_vrf
*zvrf
;
2080 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2083 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2086 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2087 show_ip_route_dump_vty(vty
, table
);
2090 vrf_id_t vrf_id
= VRF_DEFAULT
;
2092 VRF_GET_ID(vrf_id
, vrf_name
, true);
2094 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2098 show_ip_route_dump_vty(vty
, table
);
2104 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2105 struct route_entry
*re
, unsigned int num
)
2108 char buf
[SRCDEST2STR_BUFFER
];
2110 vty_out(vty
, " Nexthop %u:\n", num
);
2111 vty_out(vty
, " type: %u\n", nexthop
->type
);
2112 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2113 switch (nexthop
->type
) {
2114 case NEXTHOP_TYPE_IPV4
:
2115 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2116 vty_out(vty
, " ip address: %s\n",
2117 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2119 vty_out(vty
, " afi: ipv4\n");
2121 if (nexthop
->ifindex
) {
2122 vty_out(vty
, " interface index: %d\n",
2124 vty_out(vty
, " interface name: %s\n",
2125 ifindex2ifname(nexthop
->ifindex
,
2129 if (nexthop
->src
.ipv4
.s_addr
2130 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2132 vty_out(vty
, " source: %s\n", buf
);
2134 case NEXTHOP_TYPE_IPV6
:
2135 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2136 vty_out(vty
, " ip: %s\n",
2137 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2139 vty_out(vty
, " afi: ipv6\n");
2141 if (nexthop
->ifindex
) {
2142 vty_out(vty
, " interface index: %d\n",
2144 vty_out(vty
, " interface name: %s\n",
2145 ifindex2ifname(nexthop
->ifindex
,
2149 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2150 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2152 vty_out(vty
, " source: %s\n", buf
);
2155 case NEXTHOP_TYPE_IFINDEX
:
2157 " Nexthop is an interface (directly connected).\n");
2158 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2159 vty_out(vty
, " interface name: %s\n",
2160 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2162 case NEXTHOP_TYPE_BLACKHOLE
:
2163 vty_out(vty
, " Nexthop type is blackhole.\n");
2165 switch (nexthop
->bh_type
) {
2166 case BLACKHOLE_REJECT
:
2167 vty_out(vty
, " Blackhole type: reject\n");
2169 case BLACKHOLE_ADMINPROHIB
:
2171 " Blackhole type: admin-prohibited\n");
2173 case BLACKHOLE_NULL
:
2174 vty_out(vty
, " Blackhole type: NULL0\n");
2176 case BLACKHOLE_UNSPEC
:
2183 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2185 struct route_node
*rn
;
2186 struct route_entry
*re
;
2187 char buf
[SRCDEST2STR_BUFFER
];
2192 struct nexthop
*nexthop
= NULL
;
2193 int nexthop_num
= 0;
2195 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2196 vty_out(vty
, "----------------------------\n");
2198 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2199 RNODE_FOREACH_RE (rn
, re
) {
2200 vty_out(vty
, "Route: %s\n",
2201 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2202 vty_out(vty
, " protocol: %s\n",
2203 zebra_route_string(re
->type
));
2204 vty_out(vty
, " instance: %u\n", re
->instance
);
2205 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2206 vty_out(vty
, " VRF name: %s\n",
2207 vrf_id_to_name(re
->vrf_id
));
2208 vty_out(vty
, " flags: %u\n", re
->flags
);
2210 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2211 vty_out(vty
, " distance: %u\n", re
->distance
);
2212 vty_out(vty
, " metric: %u\n", re
->metric
);
2215 vty_out(vty
, " tag: %u\n", re
->tag
);
2217 uptime
= monotime(&tv
);
2218 uptime
-= re
->uptime
;
2219 gmtime_r(&uptime
, &tm
);
2221 if (uptime
< ONE_DAY_SECOND
)
2222 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2223 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2224 else if (uptime
< ONE_WEEK_SECOND
)
2225 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2226 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2228 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2230 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2233 vty_out(vty
, " status: %u\n", re
->status
);
2234 vty_out(vty
, " nexthop_num: %u\n",
2235 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2236 vty_out(vty
, " nexthop_active_num: %u\n",
2237 nexthop_group_active_nexthop_num(
2239 vty_out(vty
, " table: %u\n", re
->table
);
2240 vty_out(vty
, " uptime: %s\n", time
);
2242 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2244 show_ip_route_nht_dump(vty
, nexthop
, re
,
2254 static void vty_show_ip_route_summary(struct vty
*vty
,
2255 struct route_table
*table
, bool use_json
)
2257 struct route_node
*rn
;
2258 struct route_entry
*re
;
2259 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2260 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2261 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2262 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2263 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2264 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2267 json_object
*json_route_summary
= NULL
;
2268 json_object
*json_route_routes
= NULL
;
2270 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2271 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2272 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2273 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2276 json_route_summary
= json_object_new_object();
2277 json_route_routes
= json_object_new_array();
2278 json_object_object_add(json_route_summary
, "routes",
2282 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2283 RNODE_FOREACH_RE (rn
, re
) {
2284 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2285 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2287 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2289 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2291 rib_cnt
[re
->type
]++;
2293 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2294 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2297 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2299 fib_cnt
[re
->type
]++;
2302 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2304 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2306 trap_cnt
[re
->type
]++;
2309 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2311 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2313 offload_cnt
[re
->type
]++;
2318 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2320 zvrf_name(((struct rib_table_info
*)
2321 route_table_get_info(table
))
2324 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2325 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2326 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2327 if (i
== ZEBRA_ROUTE_BGP
) {
2329 json_object
*json_route_ebgp
=
2330 json_object_new_object();
2332 json_object_int_add(
2333 json_route_ebgp
, "fib",
2334 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2335 json_object_int_add(
2336 json_route_ebgp
, "rib",
2337 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2338 json_object_int_add(
2339 json_route_ebgp
, "fibOffLoaded",
2340 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2341 json_object_int_add(
2342 json_route_ebgp
, "fibTrapped",
2343 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2345 json_object_string_add(json_route_ebgp
,
2347 json_object_array_add(json_route_routes
,
2350 json_object
*json_route_ibgp
=
2351 json_object_new_object();
2353 json_object_int_add(
2354 json_route_ibgp
, "fib",
2355 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2356 json_object_int_add(
2357 json_route_ibgp
, "rib",
2358 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2359 json_object_int_add(
2360 json_route_ibgp
, "fibOffLoaded",
2361 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2362 json_object_int_add(
2363 json_route_ibgp
, "fibTrapped",
2364 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2365 json_object_string_add(json_route_ibgp
,
2367 json_object_array_add(json_route_routes
,
2370 vty_out(vty
, "%-20s %-20d %-20d \n",
2372 rib_cnt
[ZEBRA_ROUTE_BGP
],
2373 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2374 vty_out(vty
, "%-20s %-20d %-20d \n",
2376 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2377 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2381 json_object
*json_route_type
=
2382 json_object_new_object();
2384 json_object_int_add(json_route_type
,
2386 json_object_int_add(json_route_type
,
2389 json_object_int_add(json_route_type
,
2392 json_object_int_add(json_route_type
,
2395 json_object_string_add(
2396 json_route_type
, "type",
2397 zebra_route_string(i
));
2398 json_object_array_add(json_route_routes
,
2401 vty_out(vty
, "%-20s %-20d %-20d \n",
2402 zebra_route_string(i
),
2403 rib_cnt
[i
], fib_cnt
[i
]);
2409 json_object_int_add(json_route_summary
, "routesTotal",
2410 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2411 json_object_int_add(json_route_summary
, "routesTotalFib",
2412 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2414 vty_json(vty
, json_route_summary
);
2416 vty_out(vty
, "------\n");
2417 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2418 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2424 * Implementation of the ip route summary prefix command.
2426 * This command prints the primary prefixes that have been installed by various
2427 * protocols on the box.
2430 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2431 struct route_table
*table
,
2434 struct route_node
*rn
;
2435 struct route_entry
*re
;
2436 struct nexthop
*nexthop
;
2437 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2438 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2439 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2440 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2443 json_object
*json_route_summary
= NULL
;
2444 json_object
*json_route_routes
= NULL
;
2446 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2447 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2450 json_route_summary
= json_object_new_object();
2451 json_route_routes
= json_object_new_array();
2452 json_object_object_add(json_route_summary
, "prefixRoutes",
2456 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2457 RNODE_FOREACH_RE (rn
, re
) {
2460 * In case of ECMP, count only once.
2463 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2464 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2465 fib_cnt
[re
->type
]++;
2467 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2468 nexthop
= nexthop
->next
) {
2470 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2471 rib_cnt
[re
->type
]++;
2472 if (re
->type
== ZEBRA_ROUTE_BGP
2473 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2474 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2475 if (CHECK_FLAG(re
->status
,
2476 ROUTE_ENTRY_INSTALLED
))
2477 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2483 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2484 "Prefix Routes", "FIB",
2485 zvrf_name(((struct rib_table_info
*)
2486 route_table_get_info(table
))
2489 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2490 if (rib_cnt
[i
] > 0) {
2491 if (i
== ZEBRA_ROUTE_BGP
) {
2493 json_object
*json_route_ebgp
=
2494 json_object_new_object();
2496 json_object_int_add(
2497 json_route_ebgp
, "fib",
2498 fib_cnt
[ZEBRA_ROUTE_BGP
]
2499 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2500 json_object_int_add(
2501 json_route_ebgp
, "rib",
2502 rib_cnt
[ZEBRA_ROUTE_BGP
]
2503 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2504 json_object_string_add(json_route_ebgp
,
2506 json_object_array_add(json_route_routes
,
2509 json_object
*json_route_ibgp
=
2510 json_object_new_object();
2512 json_object_int_add(
2513 json_route_ibgp
, "fib",
2514 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2515 json_object_int_add(
2516 json_route_ibgp
, "rib",
2517 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2518 json_object_string_add(json_route_ibgp
,
2520 json_object_array_add(json_route_routes
,
2523 vty_out(vty
, "%-20s %-20d %-20d \n",
2525 rib_cnt
[ZEBRA_ROUTE_BGP
]
2526 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2527 fib_cnt
[ZEBRA_ROUTE_BGP
]
2528 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2529 vty_out(vty
, "%-20s %-20d %-20d \n",
2531 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2532 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2536 json_object
*json_route_type
=
2537 json_object_new_object();
2539 json_object_int_add(json_route_type
,
2541 json_object_int_add(json_route_type
,
2543 json_object_string_add(
2544 json_route_type
, "type",
2545 zebra_route_string(i
));
2546 json_object_array_add(json_route_routes
,
2549 vty_out(vty
, "%-20s %-20d %-20d \n",
2550 zebra_route_string(i
),
2551 rib_cnt
[i
], fib_cnt
[i
]);
2557 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2558 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2559 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2560 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2562 vty_json(vty
, json_route_summary
);
2564 vty_out(vty
, "------\n");
2565 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2566 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2571 DEFUN (allow_external_route_update
,
2572 allow_external_route_update_cmd
,
2573 "allow-external-route-update",
2574 "Allow FRR routes to be overwritten by external processes\n")
2576 zrouter
.allow_delete
= true;
2581 DEFUN (no_allow_external_route_update
,
2582 no_allow_external_route_update_cmd
,
2583 "no allow-external-route-update",
2585 "Allow FRR routes to be overwritten by external processes\n")
2587 zrouter
.allow_delete
= false;
2600 struct zebra_vrf
*zvrf
;
2602 if (vrf_is_backend_netns())
2603 vty_out(vty
, "netns-based vrfs\n");
2605 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2606 if (!(zvrf
= vrf
->info
))
2608 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2611 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2612 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2613 vty_out(vty
, "inactive");
2614 else if (zvrf_ns_name(zvrf
))
2615 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2616 zvrf_ns_name(zvrf
));
2618 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2620 if (vrf_is_user_cfged(vrf
))
2621 vty_out(vty
, " (configured)");
2628 DEFPY (evpn_mh_mac_holdtime
,
2629 evpn_mh_mac_holdtime_cmd
,
2630 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2635 "Duration in seconds\n")
2637 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2641 DEFPY (evpn_mh_neigh_holdtime
,
2642 evpn_mh_neigh_holdtime_cmd
,
2643 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2647 "Neighbor entry hold time\n"
2648 "Duration in seconds\n")
2651 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2655 DEFPY (evpn_mh_startup_delay
,
2656 evpn_mh_startup_delay_cmd
,
2657 "[no] evpn mh startup-delay(0-3600)$duration",
2662 "duration in seconds\n")
2665 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2669 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2670 "[no$no] evpn mh redirect-off",
2674 "ES bond redirect for fast-failover off\n")
2678 redirect_off
= no
? false : true;
2680 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2683 DEFUN (default_vrf_vni_mapping
,
2684 default_vrf_vni_mapping_cmd
,
2685 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2686 "VNI corresponding to the DEFAULT VRF\n"
2688 "Prefix routes only \n")
2690 char xpath
[XPATH_MAXLEN
];
2691 struct zebra_vrf
*zvrf
= NULL
;
2694 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2701 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2703 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2705 snprintf(xpath
, sizeof(xpath
),
2706 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2708 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2711 snprintf(xpath
, sizeof(xpath
),
2712 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2714 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2717 return nb_cli_apply_changes(vty
, NULL
);
2720 DEFUN (no_default_vrf_vni_mapping
,
2721 no_default_vrf_vni_mapping_cmd
,
2722 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2724 "VNI corresponding to DEFAULT VRF\n"
2726 "Prefix routes only \n")
2728 char xpath
[XPATH_MAXLEN
];
2730 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2731 struct zebra_vrf
*zvrf
= NULL
;
2733 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2740 if (zvrf
->l3vni
!= vni
) {
2741 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2746 snprintf(xpath
, sizeof(xpath
),
2747 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2749 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2752 snprintf(xpath
, sizeof(xpath
),
2753 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2755 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2758 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2760 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2762 return nb_cli_apply_changes(vty
, NULL
);
2765 DEFUN (vrf_vni_mapping
,
2766 vrf_vni_mapping_cmd
,
2767 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2768 "VNI corresponding to tenant VRF\n"
2770 "prefix-routes-only\n")
2774 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2782 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2783 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2787 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2788 NB_OP_MODIFY
, "true");
2790 return nb_cli_apply_changes(vty
, NULL
);
2793 DEFUN (no_vrf_vni_mapping
,
2794 no_vrf_vni_mapping_cmd
,
2795 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2797 "VNI corresponding to tenant VRF\n"
2799 "prefix-routes-only\n")
2803 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2804 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2812 if (zvrf
->l3vni
!= vni
) {
2813 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2818 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2822 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2823 NB_OP_DESTROY
, "true");
2825 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2827 return nb_cli_apply_changes(vty
, NULL
);
2831 DEFPY (show_vrf_vni
,
2833 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2835 VRF_FULL_CMD_HELP_STR
2840 struct zebra_vrf
*zvrf
;
2841 json_object
*json
= NULL
;
2842 json_object
*json_vrfs
= NULL
;
2843 bool uj
= use_json(argc
, argv
);
2844 bool use_vrf
= false;
2847 json
= json_object_new_object();
2849 /* show vrf vni used to display across all vrfs
2850 * This is enhanced to support only for specific
2853 if (vrf_all
|| !vrf_name
) {
2854 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2865 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2866 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2869 json_vrfs
= json_object_new_array();
2872 vty_json(vty
, json
);
2874 vty_out(vty
, "%% VRF does not exist\n");
2881 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2886 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2888 } else if (vrf_name
) {
2889 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2892 vty_json(vty
, json
);
2895 "%% VRF '%s' specified does not exist\n",
2902 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2903 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2906 json_vrfs
= json_object_new_array();
2908 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2912 json_object_object_add(json
, "vrfs", json_vrfs
);
2913 vty_json(vty
, json
);
2919 DEFUN (show_evpn_global
,
2920 show_evpn_global_cmd
,
2926 bool uj
= use_json(argc
, argv
);
2928 zebra_vxlan_print_evpn(vty
, uj
);
2932 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2933 SHOW_STR IP_STR
"neighbors\n")
2936 zebra_neigh_show(vty
);
2941 DEFPY(show_evpn_l2_nh
,
2942 show_evpn_l2_nh_cmd
,
2943 "show evpn l2-nh [json$json]",
2951 zebra_evpn_l2_nh_show(vty
, uj
);
2958 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2961 "Ethernet Segment\n"
2963 "Detailed information\n"
2970 if (!str_to_esi(esi_str
, &esi
)) {
2971 vty_out(vty
, "%% Malformed ESI\n");
2974 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2977 zebra_evpn_es_show_detail(vty
, uj
);
2979 zebra_evpn_es_show(vty
, uj
);
2985 DEFPY(show_evpn_es_evi
,
2986 show_evpn_es_evi_cmd
,
2987 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
2990 "Ethernet Segment per EVI\n"
2991 "VxLAN Network Identifier\n"
2993 "Detailed information\n"
3000 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3002 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3007 DEFPY(show_evpn_access_vlan
, show_evpn_access_vlan_cmd
,
3008 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3014 "Detailed information\n" JSON_STR
)
3018 if (if_name
&& vid
) {
3021 struct interface
*ifp
;
3023 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3025 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
3027 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
,
3035 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
3040 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3042 zebra_evpn_acc_vl_show(vty
, uj
);
3048 DEFUN (show_evpn_vni
,
3050 "show evpn vni [json]",
3053 "VxLAN Network Identifier\n"
3056 struct zebra_vrf
*zvrf
;
3057 bool uj
= use_json(argc
, argv
);
3059 zvrf
= zebra_vrf_get_evpn();
3060 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3064 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3065 "show evpn vni detail [json]",
3068 "VxLAN Network Identifier\n"
3069 "Detailed Information On Each VNI\n"
3072 struct zebra_vrf
*zvrf
;
3073 bool uj
= use_json(argc
, argv
);
3075 zvrf
= zebra_vrf_get_evpn();
3076 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3080 DEFUN (show_evpn_vni_vni
,
3081 show_evpn_vni_vni_cmd
,
3082 "show evpn vni " CMD_VNI_RANGE
"[json]",
3085 "VxLAN Network Identifier\n"
3089 struct zebra_vrf
*zvrf
;
3091 bool uj
= use_json(argc
, argv
);
3093 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3094 zvrf
= zebra_vrf_get_evpn();
3095 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3099 DEFUN (show_evpn_rmac_vni_mac
,
3100 show_evpn_rmac_vni_mac_cmd
,
3101 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3108 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3113 bool uj
= use_json(argc
, argv
);
3115 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3116 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3117 vty_out(vty
, "%% Malformed MAC address\n");
3120 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3124 DEFUN (show_evpn_rmac_vni
,
3125 show_evpn_rmac_vni_cmd
,
3126 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3135 bool uj
= use_json(argc
, argv
);
3137 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3138 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3143 DEFUN (show_evpn_rmac_vni_all
,
3144 show_evpn_rmac_vni_all_cmd
,
3145 "show evpn rmac vni all [json]",
3153 bool uj
= use_json(argc
, argv
);
3155 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3160 DEFUN (show_evpn_nh_vni_ip
,
3161 show_evpn_nh_vni_ip_cmd
,
3162 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3169 "Host address (ipv4 or ipv6)\n"
3174 bool uj
= use_json(argc
, argv
);
3176 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3177 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3179 vty_out(vty
, "%% Malformed Neighbor address\n");
3182 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3187 DEFUN_HIDDEN (show_evpn_nh_svd_ip
,
3188 show_evpn_nh_svd_ip_cmd
,
3189 "show evpn next-hops svd ip WORD [json]",
3193 "Single Vxlan Device\n"
3195 "Host address (ipv4 or ipv6)\n"
3199 bool uj
= use_json(argc
, argv
);
3201 if (str2ipaddr(argv
[5]->arg
, &ip
) != 0) {
3203 vty_out(vty
, "%% Malformed Neighbor address\n");
3206 zebra_vxlan_print_specific_nh_l3vni(vty
, 0, &ip
, uj
);
3211 DEFUN (show_evpn_nh_vni
,
3212 show_evpn_nh_vni_cmd
,
3213 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3222 bool uj
= use_json(argc
, argv
);
3224 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3225 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3230 DEFUN_HIDDEN (show_evpn_nh_svd
,
3231 show_evpn_nh_svd_cmd
,
3232 "show evpn next-hops svd [json]",
3236 "Single Vxlan Device\n"
3239 bool uj
= use_json(argc
, argv
);
3241 zebra_vxlan_print_nh_svd(vty
, uj
);
3246 DEFUN (show_evpn_nh_vni_all
,
3247 show_evpn_nh_vni_all_cmd
,
3248 "show evpn next-hops vni all [json]",
3256 bool uj
= use_json(argc
, argv
);
3258 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3263 DEFUN (show_evpn_mac_vni
,
3264 show_evpn_mac_vni_cmd
,
3265 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3269 "VxLAN Network Identifier\n"
3273 struct zebra_vrf
*zvrf
;
3275 bool uj
= use_json(argc
, argv
);
3277 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3278 zvrf
= zebra_vrf_get_evpn();
3279 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3283 DEFPY (show_evpn_mac_vni_detail
,
3284 show_evpn_mac_vni_detail_cmd
,
3285 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3289 "VXLAN Network Identifier\n"
3291 "Detailed Information On Each VNI MAC\n"
3294 struct zebra_vrf
*zvrf
;
3295 bool uj
= use_json(argc
, argv
);
3297 zvrf
= zebra_vrf_get_evpn();
3298 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3302 DEFUN (show_evpn_mac_vni_all
,
3303 show_evpn_mac_vni_all_cmd
,
3304 "show evpn mac vni all [json]",
3308 "VxLAN Network Identifier\n"
3312 struct zebra_vrf
*zvrf
;
3313 bool uj
= use_json(argc
, argv
);
3315 zvrf
= zebra_vrf_get_evpn();
3316 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3320 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3321 "show evpn mac vni all detail [json]",
3325 "VxLAN Network Identifier\n"
3327 "Detailed Information On Each VNI MAC\n"
3330 struct zebra_vrf
*zvrf
;
3331 bool uj
= use_json(argc
, argv
);
3333 zvrf
= zebra_vrf_get_evpn();
3334 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3338 DEFUN (show_evpn_mac_vni_all_vtep
,
3339 show_evpn_mac_vni_all_vtep_cmd
,
3340 "show evpn mac vni all vtep A.B.C.D [json]",
3344 "VxLAN Network Identifier\n"
3347 "Remote VTEP IP address\n"
3350 struct zebra_vrf
*zvrf
;
3351 struct in_addr vtep_ip
;
3352 bool uj
= use_json(argc
, argv
);
3354 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3356 vty_out(vty
, "%% Malformed VTEP IP address\n");
3359 zvrf
= zebra_vrf_get_evpn();
3360 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3366 DEFUN (show_evpn_mac_vni_mac
,
3367 show_evpn_mac_vni_mac_cmd
,
3368 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3372 "VxLAN Network Identifier\n"
3375 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3379 struct zebra_vrf
*zvrf
;
3382 bool uj
= use_json(argc
, argv
);
3384 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3385 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3386 vty_out(vty
, "%% Malformed MAC address\n");
3389 zvrf
= zebra_vrf_get_evpn();
3390 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3394 DEFUN (show_evpn_mac_vni_vtep
,
3395 show_evpn_mac_vni_vtep_cmd
,
3396 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3400 "VxLAN Network Identifier\n"
3403 "Remote VTEP IP address\n"
3406 struct zebra_vrf
*zvrf
;
3408 struct in_addr vtep_ip
;
3409 bool uj
= use_json(argc
, argv
);
3411 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3412 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3414 vty_out(vty
, "%% Malformed VTEP IP address\n");
3418 zvrf
= zebra_vrf_get_evpn();
3419 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3423 DEFPY (show_evpn_mac_vni_all_dad
,
3424 show_evpn_mac_vni_all_dad_cmd
,
3425 "show evpn mac vni all duplicate [json]",
3429 "VxLAN Network Identifier\n"
3431 "Duplicate address list\n"
3434 struct zebra_vrf
*zvrf
;
3435 bool uj
= use_json(argc
, argv
);
3437 zvrf
= zebra_vrf_get_evpn();
3438 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3443 DEFPY (show_evpn_mac_vni_dad
,
3444 show_evpn_mac_vni_dad_cmd
,
3445 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3449 "VxLAN Network Identifier\n"
3451 "Duplicate address list\n"
3454 struct zebra_vrf
*zvrf
;
3455 bool uj
= use_json(argc
, argv
);
3457 zvrf
= zebra_vrf_get_evpn();
3459 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3464 DEFPY (show_evpn_neigh_vni_dad
,
3465 show_evpn_neigh_vni_dad_cmd
,
3466 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3469 "ARP and ND cache\n"
3470 "VxLAN Network Identifier\n"
3472 "Duplicate address list\n"
3475 struct zebra_vrf
*zvrf
;
3476 bool uj
= use_json(argc
, argv
);
3478 zvrf
= zebra_vrf_get_evpn();
3479 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3483 DEFPY (show_evpn_neigh_vni_all_dad
,
3484 show_evpn_neigh_vni_all_dad_cmd
,
3485 "show evpn arp-cache vni all duplicate [json]",
3488 "ARP and ND cache\n"
3489 "VxLAN Network Identifier\n"
3491 "Duplicate address list\n"
3494 struct zebra_vrf
*zvrf
;
3495 bool uj
= use_json(argc
, argv
);
3497 zvrf
= zebra_vrf_get_evpn();
3498 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3503 DEFUN (show_evpn_neigh_vni
,
3504 show_evpn_neigh_vni_cmd
,
3505 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3508 "ARP and ND cache\n"
3509 "VxLAN Network Identifier\n"
3513 struct zebra_vrf
*zvrf
;
3515 bool uj
= use_json(argc
, argv
);
3517 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3518 zvrf
= zebra_vrf_get_evpn();
3519 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3523 DEFUN (show_evpn_neigh_vni_all
,
3524 show_evpn_neigh_vni_all_cmd
,
3525 "show evpn arp-cache vni all [json]",
3528 "ARP and ND cache\n"
3529 "VxLAN Network Identifier\n"
3533 struct zebra_vrf
*zvrf
;
3534 bool uj
= use_json(argc
, argv
);
3536 zvrf
= zebra_vrf_get_evpn();
3537 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3541 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3542 "show evpn arp-cache vni all detail [json]",
3545 "ARP and ND cache\n"
3546 "VxLAN Network Identifier\n"
3548 "Neighbor details for all vnis in detail\n" JSON_STR
)
3550 struct zebra_vrf
*zvrf
;
3551 bool uj
= use_json(argc
, argv
);
3553 zvrf
= zebra_vrf_get_evpn();
3554 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3558 DEFUN (show_evpn_neigh_vni_neigh
,
3559 show_evpn_neigh_vni_neigh_cmd
,
3560 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3563 "ARP and ND cache\n"
3564 "VxLAN Network Identifier\n"
3567 "Neighbor address (IPv4 or IPv6 address)\n"
3570 struct zebra_vrf
*zvrf
;
3573 bool uj
= use_json(argc
, argv
);
3575 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3576 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3578 vty_out(vty
, "%% Malformed Neighbor address\n");
3581 zvrf
= zebra_vrf_get_evpn();
3582 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3586 DEFUN (show_evpn_neigh_vni_vtep
,
3587 show_evpn_neigh_vni_vtep_cmd
,
3588 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3591 "ARP and ND cache\n"
3592 "VxLAN Network Identifier\n"
3595 "Remote VTEP IP address\n"
3598 struct zebra_vrf
*zvrf
;
3600 struct in_addr vtep_ip
;
3601 bool uj
= use_json(argc
, argv
);
3603 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3604 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3606 vty_out(vty
, "%% Malformed VTEP IP address\n");
3610 zvrf
= zebra_vrf_get_evpn();
3611 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3615 /* policy routing contexts */
3616 DEFUN (show_pbr_ipset
,
3618 "show pbr ipset [WORD]",
3620 "Policy-Based Routing\n"
3621 "IPset Context information\n"
3622 "IPset Name information\n")
3626 found
= argv_find(argv
, argc
, "WORD", &idx
);
3628 zebra_pbr_show_ipset_list(vty
, NULL
);
3630 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3634 /* policy routing contexts */
3635 DEFUN (show_pbr_iptable
,
3636 show_pbr_iptable_cmd
,
3637 "show pbr iptable [WORD]",
3639 "Policy-Based Routing\n"
3640 "IPtable Context information\n"
3641 "IPtable Name information\n")
3646 found
= argv_find(argv
, argc
, "WORD", &idx
);
3648 zebra_pbr_show_iptable(vty
, NULL
);
3650 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3654 /* policy routing contexts */
3655 DEFPY (show_pbr_rule
,
3659 "Policy-Based Routing\n"
3662 zebra_pbr_show_rule(vty
);
3666 DEFPY (pbr_nexthop_resolve
,
3667 pbr_nexthop_resolve_cmd
,
3668 "[no$no] pbr nexthop-resolve",
3670 "Policy Based Routing\n"
3671 "Resolve nexthop for dataplane programming\n")
3673 zebra_pbr_expand_action_update(!no
);
3677 DEFPY (clear_evpn_dup_addr
,
3678 clear_evpn_dup_addr_cmd
,
3679 "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>]>",
3682 "Duplicate address \n"
3683 "VxLAN Network Identifier\n"
3687 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3692 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3693 int ret
= CMD_SUCCESS
;
3695 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3696 *yang_dup_mac
= NULL
;
3701 yang_dup
= yang_data_new(
3702 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3705 yang_dup
= yang_data_new_uint32(
3706 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3708 if (!is_zero_mac(&mac
->eth_addr
)) {
3709 yang_dup_mac
= yang_data_new_mac(
3710 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3713 listnode_add(input
, yang_dup_mac
);
3715 if (sockunion_family(ip
) == AF_INET
) {
3716 host_ip
.ipa_type
= IPADDR_V4
;
3717 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3719 host_ip
.ipa_type
= IPADDR_V6
;
3720 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3721 sizeof(struct in6_addr
));
3724 yang_dup_ip
= yang_data_new_ip(
3725 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3729 listnode_add(input
, yang_dup_ip
);
3734 listnode_add(input
, yang_dup
);
3735 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3739 list_delete(&input
);
3744 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3745 evpn_accept_bgp_seq_cmd
,
3746 "evpn accept-bgp-seq",
3748 "Accept all sequence numbers from BGP\n")
3750 zebra_vxlan_set_accept_bgp_seq(true);
3754 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3755 no_evpn_accept_bgp_seq_cmd
,
3756 "no evpn accept-bgp-seq",
3759 "Accept all sequence numbers from BGP\n")
3761 zebra_vxlan_set_accept_bgp_seq(false);
3765 /* Static ip route configuration write function. */
3766 static int zebra_ip_config(struct vty
*vty
)
3770 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3775 DEFUN (ip_zebra_import_table_distance
,
3776 ip_zebra_import_table_distance_cmd
,
3777 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3779 "import routes from non-main kernel table\n"
3780 "kernel routing table id\n"
3781 "Distance for imported routes\n"
3782 "Default distance value\n"
3783 "route-map for filtering\n"
3786 uint32_t table_id
= 0;
3788 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3789 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3791 strmatch(argv
[argc
- 2]->text
, "route-map")
3792 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3796 if (argc
== 7 || (argc
== 5 && !rmap
))
3797 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3799 if (!is_zebra_valid_kernel_table(table_id
)) {
3801 "Invalid routing table ID, %d. Must be in range 1-252\n",
3804 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3808 if (is_zebra_main_routing_table(table_id
)) {
3810 "Invalid routing table ID, %d. Must be non-default table\n",
3813 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3817 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3820 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3825 DEFUN_HIDDEN (zebra_packet_process
,
3826 zebra_packet_process_cmd
,
3827 "zebra zapi-packets (1-10000)",
3830 "Number of packets to process before relinquishing thread\n")
3832 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3834 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3835 memory_order_relaxed
);
3840 DEFUN_HIDDEN (no_zebra_packet_process
,
3841 no_zebra_packet_process_cmd
,
3842 "no zebra zapi-packets [(1-10000)]",
3846 "Number of packets to process before relinquishing thread\n")
3848 atomic_store_explicit(&zrouter
.packets_to_process
,
3849 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3850 memory_order_relaxed
);
3855 DEFUN_HIDDEN (zebra_workqueue_timer
,
3856 zebra_workqueue_timer_cmd
,
3857 "zebra work-queue (0-10000)",
3860 "Time in milliseconds\n")
3862 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3863 zrouter
.ribq
->spec
.hold
= timer
;
3868 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3869 no_zebra_workqueue_timer_cmd
,
3870 "no zebra work-queue [(0-10000)]",
3874 "Time in milliseconds\n")
3876 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3881 DEFUN (no_ip_zebra_import_table
,
3882 no_ip_zebra_import_table_cmd
,
3883 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3886 "import routes from non-main kernel table\n"
3887 "kernel routing table id\n"
3888 "Distance for imported routes\n"
3889 "Default distance value\n"
3890 "route-map for filtering\n"
3893 uint32_t table_id
= 0;
3894 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3896 if (!is_zebra_valid_kernel_table(table_id
)) {
3898 "Invalid routing table ID. Must be in range 1-252\n");
3902 if (is_zebra_main_routing_table(table_id
)) {
3904 "Invalid routing table ID, %d. Must be non-default table\n",
3909 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3912 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3915 DEFPY (zebra_nexthop_group_keep
,
3916 zebra_nexthop_group_keep_cmd
,
3917 "[no] zebra nexthop-group keep (1-3600)",
3921 "How long to keep\n"
3922 "Time in seconds from 1-3600\n")
3925 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3927 zrouter
.nhg_keep
= keep
;
3932 static int config_write_protocol(struct vty
*vty
)
3934 if (zrouter
.allow_delete
)
3935 vty_out(vty
, "allow-external-route-update\n");
3937 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3938 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3940 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3941 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3943 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3944 vty_out(vty
, "zebra zapi-packets %u\n",
3945 zrouter
.packets_to_process
);
3947 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3949 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3950 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3951 ipv4_multicast_mode
== MCAST_URIB_ONLY
3953 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3955 : ipv4_multicast_mode
3956 == MCAST_MIX_MRIB_FIRST
3958 : ipv4_multicast_mode
3959 == MCAST_MIX_DISTANCE
3963 /* Include dataplane info */
3964 dplane_config_write_helper(vty
);
3966 zebra_evpn_mh_config_write(vty
);
3968 zebra_pbr_config_write(vty
);
3970 if (!zebra_vxlan_get_accept_bgp_seq())
3971 vty_out(vty
, "no evpn accept-bgp-seq\n");
3973 /* Include nexthop-group config */
3974 if (!zebra_nhg_kernel_nexthops_enabled())
3975 vty_out(vty
, "no zebra nexthop kernel enable\n");
3977 if (zebra_nhg_proto_nexthops_only())
3978 vty_out(vty
, "zebra nexthop proto only\n");
3980 if (!zebra_nhg_recursive_use_backups())
3981 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3983 if (rnh_get_hide_backups())
3984 vty_out(vty
, "ip nht hide-backup-events\n");
3987 /* Include netlink info */
3988 netlink_config_write_helper(vty
);
3989 #endif /* HAVE_NETLINK */
4001 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4004 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4005 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4006 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4007 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4008 ttable_add_row(table
, "v6 Forwarding|%s",
4009 ipforward_ipv6() ? "On" : "Off");
4010 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4011 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4012 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4016 if (!vrf_is_backend_netns())
4017 ttable_add_row(table
, "VRF|l3mdev Available");
4019 ttable_add_row(table
, "VRF|Namespaces");
4021 ttable_add_row(table
, "VRF|Not Available");
4024 ttable_add_row(table
, "ASIC offload|%s",
4025 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4028 * Do not display this unless someone is actually using it
4030 * Why this distinction? I think this is effectively dead code
4031 * and should not be exposed. Maybe someone proves me wrong.
4033 if (zrouter
.asic_notification_nexthop_control
)
4034 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4036 ttable_add_row(table
, "RA|%s",
4037 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4038 ttable_add_row(table
, "RFC 5549|%s",
4039 rtadv_get_interfaces_configured_from_bgp()
4041 : "BGP is not using");
4043 ttable_add_row(table
, "Kernel NHG|%s",
4044 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4046 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4047 zrouter
.allow_delete
? "Yes" : "No");
4048 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4049 zrouter
.all_linkdownv4
? "On" : "Off");
4050 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4051 zrouter
.default_linkdownv4
? "On" : "Off");
4052 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4053 zrouter
.all_linkdownv6
? "On" : "Off");
4054 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4055 zrouter
.default_linkdownv6
? "On" : "Off");
4057 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4058 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4059 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4060 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4061 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4062 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4063 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4064 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4066 out
= ttable_dump(table
, "\n");
4067 vty_out(vty
, "%s\n", out
);
4068 XFREE(MTYPE_TMP
, out
);
4072 " Route Route Neighbor LSP LSP\n");
4074 "VRF Installs Removals Updates Installs Removals\n");
4076 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4077 struct zebra_vrf
*zvrf
= vrf
->info
;
4079 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4080 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4081 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4082 zvrf
->lsp_removals
);
4088 DEFUN (ip_forwarding
,
4092 "Turn on IP forwarding\n")
4098 ret
= ipforward_on();
4101 vty_out(vty
, "Can't turn on IP forwarding\n");
4102 return CMD_WARNING_CONFIG_FAILED
;
4108 DEFUN (no_ip_forwarding
,
4109 no_ip_forwarding_cmd
,
4113 "Turn off IP forwarding\n")
4119 ret
= ipforward_off();
4122 vty_out(vty
, "Can't turn off IP forwarding\n");
4123 return CMD_WARNING_CONFIG_FAILED
;
4129 /* Only display ip forwarding is enabled or not. */
4130 DEFUN (show_ip_forwarding
,
4131 show_ip_forwarding_cmd
,
4132 "show ip forwarding",
4135 "IP forwarding status\n")
4142 vty_out(vty
, "IP forwarding is off\n");
4144 vty_out(vty
, "IP forwarding is on\n");
4148 /* Only display ipv6 forwarding is enabled or not. */
4149 DEFUN (show_ipv6_forwarding
,
4150 show_ipv6_forwarding_cmd
,
4151 "show ipv6 forwarding",
4153 "IPv6 information\n"
4154 "Forwarding status\n")
4158 ret
= ipforward_ipv6();
4162 vty_out(vty
, "ipv6 forwarding is unknown\n");
4165 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4168 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4171 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4177 DEFUN (ipv6_forwarding
,
4178 ipv6_forwarding_cmd
,
4181 "Turn on IPv6 forwarding\n")
4185 ret
= ipforward_ipv6();
4187 ret
= ipforward_ipv6_on();
4190 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4191 return CMD_WARNING_CONFIG_FAILED
;
4197 DEFUN (no_ipv6_forwarding
,
4198 no_ipv6_forwarding_cmd
,
4199 "no ipv6 forwarding",
4202 "Turn off IPv6 forwarding\n")
4206 ret
= ipforward_ipv6();
4208 ret
= ipforward_ipv6_off();
4211 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4212 return CMD_WARNING_CONFIG_FAILED
;
4218 /* Display dataplane info */
4219 DEFUN (show_dataplane
,
4221 "show zebra dplane [detailed]",
4224 "Zebra dataplane information\n"
4225 "Detailed output\n")
4228 bool detailed
= false;
4230 if (argv_find(argv
, argc
, "detailed", &idx
))
4233 return dplane_show_helper(vty
, detailed
);
4236 /* Display dataplane providers info */
4237 DEFUN (show_dataplane_providers
,
4238 show_dataplane_providers_cmd
,
4239 "show zebra dplane providers [detailed]",
4242 "Zebra dataplane information\n"
4243 "Zebra dataplane provider information\n"
4244 "Detailed output\n")
4247 bool detailed
= false;
4249 if (argv_find(argv
, argc
, "detailed", &idx
))
4252 return dplane_show_provs_helper(vty
, detailed
);
4255 /* Configure dataplane incoming queue limit */
4256 DEFUN (zebra_dplane_queue_limit
,
4257 zebra_dplane_queue_limit_cmd
,
4258 "zebra dplane limit (0-10000)",
4261 "Limit incoming queued updates\n"
4262 "Number of queued updates\n")
4266 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4268 dplane_set_in_queue_limit(limit
, true);
4273 /* Reset dataplane queue limit to default value */
4274 DEFUN (no_zebra_dplane_queue_limit
,
4275 no_zebra_dplane_queue_limit_cmd
,
4276 "no zebra dplane limit [(0-10000)]",
4280 "Limit incoming queued updates\n"
4281 "Number of queued updates\n")
4283 dplane_set_in_queue_limit(0, false);
4288 DEFUN (zebra_show_routing_tables_summary
,
4289 zebra_show_routing_tables_summary_cmd
,
4290 "show zebra router table summary",
4293 "The Zebra Router Information\n"
4294 "Table Information about this Zebra Router\n"
4295 "Summary Information\n")
4297 zebra_router_show_table_summary(vty
);
4302 /* Table configuration write function. */
4303 static int config_write_table(struct vty
*vty
)
4308 /* IPForwarding configuration write function. */
4309 static int config_write_forwarding(struct vty
*vty
)
4312 vty_out(vty
, "no ip forwarding\n");
4313 if (!ipforward_ipv6())
4314 vty_out(vty
, "no ipv6 forwarding\n");
4315 vty_out(vty
, "!\n");
4319 DEFUN_HIDDEN (show_frr
,
4325 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4326 vty_out(vty
, ".............................7777:..............................................\n");
4327 vty_out(vty
, ".............................777777,............................................\n");
4328 vty_out(vty
, "... .........................77777777,..........................................\n");
4329 vty_out(vty
, "............................=7777777777:........................................\n");
4330 vty_out(vty
, "........................:7777777777777777,......................................\n");
4331 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4332 vty_out(vty
, "...................I7777777777+.................................................\n");
4333 vty_out(vty
, "................,777777777?............ .......................................\n");
4334 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4335 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4336 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4337 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4338 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4339 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4340 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4341 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4342 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4343 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4344 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4345 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4346 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4347 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4348 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4349 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4350 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4351 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4352 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4353 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4354 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4355 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4356 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4357 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4358 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4359 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4360 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4361 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4362 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4363 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4364 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4365 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4366 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4367 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4368 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4369 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4370 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4371 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4372 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4373 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4374 vty_out(vty
, "................................~77777777...............=777777.................\n");
4375 vty_out(vty
, ".....................................:=?I................~777777................\n");
4376 vty_out(vty
, "..........................................................:777777,..............\n");
4377 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4383 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4384 zebra_kernel_netlink_batch_tx_buf_cmd
,
4385 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4387 "Zebra kernel interface\n"
4388 "Set Netlink parameters\n"
4389 "Set batch buffer size and send threshold\n"
4390 "Size of the buffer\n"
4393 uint32_t bufsize
= 0, threshold
= 0;
4395 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4396 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4398 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4403 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4404 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4405 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4407 "Zebra kernel interface\n"
4408 "Set Netlink parameters\n"
4409 "Set batch buffer size and send threshold\n"
4410 "Size of the buffer\n"
4413 netlink_set_batch_buffer_size(0, 0, false);
4418 DEFPY (zebra_protodown_bit
,
4419 zebra_protodown_bit_cmd
,
4420 "zebra protodown reason-bit (0-31)$bit",
4422 "Protodown Configuration\n"
4423 "Reason Bit used in the kernel for application\n"
4424 "Reason Bit range\n")
4426 if_netlink_set_frr_protodown_r_bit(bit
);
4430 DEFPY (no_zebra_protodown_bit
,
4431 no_zebra_protodown_bit_cmd
,
4432 "no zebra protodown reason-bit [(0-31)$bit]",
4435 "Protodown Configuration\n"
4436 "Reason Bit used in the kernel for setting protodown\n"
4437 "Reason Bit Range\n")
4439 if_netlink_unset_frr_protodown_r_bit();
4443 #endif /* HAVE_NETLINK */
4445 DEFUN(ip_table_range
, ip_table_range_cmd
,
4446 "[no] ip table range (1-4294967295) (1-4294967295)",
4448 "table configuration\n"
4449 "Configure table range\n"
4450 "Start Routing Table\n"
4451 "End Routing Table\n")
4453 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4458 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4460 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4464 if (strmatch(argv
[0]->text
, "no"))
4465 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4467 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4470 #ifdef HAVE_SCRIPTING
4472 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4473 "zebra on-rib-process script SCRIPT",
4475 "on_rib_process_dplane_results hook call\n"
4477 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4480 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4483 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4484 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4486 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4487 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4492 #endif /* HAVE_SCRIPTING */
4494 /* IP node for static routes. */
4495 static int zebra_ip_config(struct vty
*vty
);
4496 static struct cmd_node ip_node
= {
4497 .name
= "static ip",
4500 .config_write
= zebra_ip_config
,
4502 static int config_write_protocol(struct vty
*vty
);
4503 static struct cmd_node protocol_node
= {
4505 .node
= PROTOCOL_NODE
,
4507 .config_write
= config_write_protocol
,
4509 /* table node for routing tables. */
4510 static int config_write_table(struct vty
*vty
);
4511 static struct cmd_node table_node
= {
4515 .config_write
= config_write_table
,
4517 static int config_write_forwarding(struct vty
*vty
);
4518 static struct cmd_node forwarding_node
= {
4519 .name
= "forwarding",
4520 .node
= FORWARDING_NODE
,
4522 .config_write
= config_write_forwarding
,
4526 void zebra_vty_init(void)
4528 /* Install configuration write function. */
4529 install_node(&table_node
);
4530 install_node(&forwarding_node
);
4532 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4533 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4534 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4535 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4537 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4538 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4539 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4542 zebra_route_map_init();
4544 zebra_affinity_map_init();
4546 install_node(&ip_node
);
4547 install_node(&protocol_node
);
4549 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4550 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4552 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4553 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4555 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4556 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4557 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4558 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4559 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4560 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4561 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4562 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4563 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4564 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4566 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4567 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4569 install_element(VIEW_NODE
, &show_vrf_cmd
);
4570 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4571 install_element(VIEW_NODE
, &show_route_cmd
);
4572 install_element(VIEW_NODE
, &show_ro_cmd
);
4573 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4574 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4575 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4577 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4578 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4580 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4581 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4582 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4583 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4584 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4585 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4586 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4587 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4588 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4590 install_element(VIEW_NODE
, &show_frr_cmd
);
4591 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4592 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4593 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4594 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4595 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4596 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4597 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4598 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4599 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4600 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4601 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4602 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4603 install_element(VIEW_NODE
, &show_evpn_nh_svd_ip_cmd
);
4604 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4605 install_element(VIEW_NODE
, &show_evpn_nh_svd_cmd
);
4606 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4607 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4608 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4609 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4610 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4611 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4612 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4613 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4614 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4615 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4616 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4617 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4618 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4619 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4620 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4621 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4622 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4623 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4624 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4625 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4627 install_element(VIEW_NODE
, &show_neigh_cmd
);
4629 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4630 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4631 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4632 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4633 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4635 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4636 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4637 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4638 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4639 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4640 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4641 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4642 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4644 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4645 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4646 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4647 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4649 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4650 install_element(VRF_NODE
, &ip_table_range_cmd
);
4653 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4654 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4655 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4656 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4657 #endif /* HAVE_NETLINK */
4659 #ifdef HAVE_SCRIPTING
4660 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4661 #endif /* HAVE_SCRIPTING */
4663 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);