2 * Copyright (C) 2002 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "srcdest_table.h"
37 #include "zebra/zebra_router.h"
38 #include "zebra/zserv.h"
39 #include "zebra/zebra_vrf.h"
40 #include "zebra/zebra_mpls.h"
41 #include "zebra/zebra_rnh.h"
42 #include "zebra/redistribute.h"
43 #include "zebra/zebra_routemap.h"
45 #include "lib/route_opaque.h"
46 #include "zebra/zebra_vxlan.h"
47 #include "zebra/zebra_evpn_mh.h"
48 #ifndef VTYSH_EXTRACT_PL
49 #include "zebra/zebra_vty_clippy.c"
51 #include "zebra/zserv.h"
52 #include "zebra/router-id.h"
53 #include "zebra/ipforward.h"
54 #include "zebra/zebra_vxlan_private.h"
55 #include "zebra/zebra_pbr.h"
56 #include "zebra/zebra_nhg.h"
57 #include "zebra/zebra_evpn_mh.h"
58 #include "zebra/interface.h"
59 #include "northbound_cli.h"
60 #include "zebra/zebra_nb.h"
61 #include "zebra/kernel_netlink.h"
62 #include "zebra/table_manager.h"
64 extern int allow_delete
;
66 /* context to manage dumps in multiple tables or vrfs */
67 struct route_show_ctx
{
68 bool multi
; /* dump multiple tables or vrf */
69 bool header_done
; /* common header already displayed */
72 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
73 safi_t safi
, bool use_fib
, bool use_json
,
75 const struct prefix
*longer_prefix_p
,
76 bool supernets_only
, int type
,
77 unsigned short ospf_instance_id
, uint32_t tableid
,
78 struct route_show_ctx
*ctx
);
79 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
80 int mcast
, bool use_fib
, bool show_ng
);
81 static void vty_show_ip_route_summary(struct vty
*vty
,
82 struct route_table
*table
, bool use_json
);
83 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
84 struct route_table
*table
,
86 /* Helper api to format a nexthop in the 'detailed' output path. */
87 static void show_nexthop_detail_helper(struct vty
*vty
,
88 const struct route_entry
*re
,
89 const struct nexthop
*nexthop
,
92 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
93 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
94 struct route_entry
*re
, unsigned int num
);
96 DEFUN (ip_multicast_mode
,
97 ip_multicast_mode_cmd
,
98 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
100 "Multicast options\n"
101 "RPF lookup behavior\n"
102 "Lookup in unicast RIB only\n"
103 "Lookup in multicast RIB only\n"
104 "Try multicast RIB first, fall back to unicast RIB\n"
105 "Lookup both, use entry with lower distance\n"
106 "Lookup both, use entry with longer prefix\n")
108 char *mode
= argv
[3]->text
;
110 if (strmatch(mode
, "urib-only"))
111 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
112 else if (strmatch(mode
, "mrib-only"))
113 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
114 else if (strmatch(mode
, "mrib-then-urib"))
115 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
116 else if (strmatch(mode
, "lower-distance"))
117 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
118 else if (strmatch(mode
, "longer-prefix"))
119 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
121 vty_out(vty
, "Invalid mode specified\n");
122 return CMD_WARNING_CONFIG_FAILED
;
128 DEFUN (no_ip_multicast_mode
,
129 no_ip_multicast_mode_cmd
,
130 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
133 "Multicast options\n"
134 "RPF lookup behavior\n"
135 "Lookup in unicast RIB only\n"
136 "Lookup in multicast RIB only\n"
137 "Try multicast RIB first, fall back to unicast RIB\n"
138 "Lookup both, use entry with lower distance\n"
139 "Lookup both, use entry with longer prefix\n")
141 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
148 "show ip rpf [json]",
151 "Display RPF information for multicast source\n"
154 bool uj
= use_json(argc
, argv
);
155 struct route_show_ctx ctx
= {
159 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
160 false, uj
, 0, NULL
, false, 0, 0, 0, &ctx
);
163 DEFUN (show_ip_rpf_addr
,
164 show_ip_rpf_addr_cmd
,
165 "show ip rpf A.B.C.D",
168 "Display RPF information for multicast source\n"
169 "IP multicast source address (e.g. 10.0.0.0)\n")
173 struct route_node
*rn
;
174 struct route_entry
*re
;
177 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
179 vty_out(vty
, "%% Malformed address\n");
183 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
186 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
188 vty_out(vty
, "%% No match for RPF lookup\n");
193 static char re_status_output_char(const struct route_entry
*re
,
194 const struct nexthop
*nhop
,
197 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
201 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
202 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
203 /* More-specific test for 'fib' output */
205 star_p
= !!CHECK_FLAG(nhop
->flags
,
211 if (zrouter
.asic_offloaded
&&
212 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
215 if (zrouter
.asic_offloaded
216 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
219 if (zrouter
.asic_offloaded
220 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
229 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
230 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
236 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
243 * Show backup nexthop info, in the 'detailed' output path
245 static void show_nh_backup_helper(struct vty
*vty
,
246 const struct route_entry
*re
,
247 const struct nexthop
*nexthop
)
249 const struct nexthop
*start
, *backup
, *temp
;
252 /* Double-check that there _is_ a backup */
253 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
254 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
255 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
258 /* Locate the backup nexthop(s) */
259 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
260 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
261 /* Format the backup(s) (indented) */
263 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
264 backup
= backup
->next
;
269 /* It's possible for backups to be recursive too,
270 * so walk the recursive resolution list if present.
275 show_nexthop_detail_helper(vty
, re
, backup
,
279 if (backup
->resolved
&& temp
== backup
)
280 backup
= backup
->resolved
;
282 backup
= nexthop_next(backup
);
284 if (backup
== temp
->next
)
292 * Helper api to format output for a nexthop, used in the 'detailed'
295 static void show_nexthop_detail_helper(struct vty
*vty
,
296 const struct route_entry
*re
,
297 const struct nexthop
*nexthop
,
301 char buf
[MPLS_LABEL_STRLEN
];
306 nexthop
->rparent
? " " : "");
308 vty_out(vty
, " %c%s",
309 re_status_output_char(re
, nexthop
, false),
310 nexthop
->rparent
? " " : "");
312 switch (nexthop
->type
) {
313 case NEXTHOP_TYPE_IPV4
:
314 case NEXTHOP_TYPE_IPV4_IFINDEX
:
315 vty_out(vty
, " %pI4",
316 &nexthop
->gate
.ipv4
);
317 if (nexthop
->ifindex
)
318 vty_out(vty
, ", via %s",
323 case NEXTHOP_TYPE_IPV6
:
324 case NEXTHOP_TYPE_IPV6_IFINDEX
:
326 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
328 if (nexthop
->ifindex
)
329 vty_out(vty
, ", via %s",
335 case NEXTHOP_TYPE_IFINDEX
:
336 vty_out(vty
, " directly connected, %s",
337 ifindex2ifname(nexthop
->ifindex
,
340 case NEXTHOP_TYPE_BLACKHOLE
:
341 vty_out(vty
, " unreachable");
342 switch (nexthop
->bh_type
) {
343 case BLACKHOLE_REJECT
:
344 vty_out(vty
, " (ICMP unreachable)");
346 case BLACKHOLE_ADMINPROHIB
:
348 " (ICMP admin-prohibited)");
351 vty_out(vty
, " (blackhole)");
353 case BLACKHOLE_UNSPEC
:
359 if (re
->vrf_id
!= nexthop
->vrf_id
) {
360 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
362 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
365 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
366 vty_out(vty
, " (duplicate nexthop removed)");
368 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
369 vty_out(vty
, " inactive");
371 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
372 vty_out(vty
, " onlink");
374 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
375 vty_out(vty
, " (recursive)");
377 /* Source specified? */
378 switch (nexthop
->type
) {
379 case NEXTHOP_TYPE_IPV4
:
380 case NEXTHOP_TYPE_IPV4_IFINDEX
:
381 if (nexthop
->src
.ipv4
.s_addr
) {
382 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
383 addrstr
, sizeof(addrstr
)))
384 vty_out(vty
, ", src %s",
389 case NEXTHOP_TYPE_IPV6
:
390 case NEXTHOP_TYPE_IPV6_IFINDEX
:
391 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
393 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
394 addrstr
, sizeof(addrstr
)))
395 vty_out(vty
, ", src %s",
405 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
407 /* Label information */
408 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
409 vty_out(vty
, ", label %s",
410 mpls_label2str(nexthop
->nh_label
->num_labels
,
411 nexthop
->nh_label
->label
, buf
,
412 sizeof(buf
), 1 /*pretty*/));
416 vty_out(vty
, ", weight %u", nexthop
->weight
);
418 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
419 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
421 for (i
= 1; i
< nexthop
->backup_num
; i
++)
422 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
426 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
427 struct json_object
*json
)
429 struct bgp_zebra_opaque bzo
= {};
435 case ZEBRA_ROUTE_SHARP
:
437 json_object_string_add(json
, "opaque",
438 (char *)re
->opaque
->data
);
440 vty_out(vty
, " Opaque Data: %s",
441 (char *)re
->opaque
->data
);
443 case ZEBRA_ROUTE_BGP
: {
444 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
447 json_object_string_add(json
, "asPath", bzo
.aspath
);
448 json_object_string_add(json
, "communities",
450 json_object_string_add(json
, "largeCommunities",
453 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
455 if (bzo
.community
[0] != '\0')
456 vty_out(vty
, " Communities : %s\n",
459 if (bzo
.lcommunity
[0] != '\0')
460 vty_out(vty
, " Large-Communities: %s\n",
469 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
473 cur
= monotime(NULL
);
476 frrtime_to_interval(cur
, buf
, bufsize
);
479 /* New RIB. Detailed information for IPv4 route. */
480 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
481 int mcast
, bool use_fib
, bool show_ng
)
483 struct route_entry
*re
;
484 struct nexthop
*nexthop
;
485 char buf
[SRCDEST2STR_BUFFER
];
486 struct zebra_vrf
*zvrf
;
489 dest
= rib_dest_from_rnode(rn
);
491 RNODE_FOREACH_RE (rn
, re
) {
493 * If re not selected for forwarding, skip re
494 * for "show ip/ipv6 fib <prefix>"
496 if (use_fib
&& re
!= dest
->selected_fib
)
499 const char *mcast_info
= "";
501 struct rib_table_info
*info
=
502 srcdest_rnode_table_info(rn
);
503 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
504 ? " using Multicast RIB"
505 : " using Unicast RIB";
508 vty_out(vty
, "Routing entry for %s%s\n",
509 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
510 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
512 vty_out(vty
, "[%d]", re
->instance
);
514 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
517 vty_out(vty
, ", tag %u", re
->tag
);
518 #if defined(SUPPORT_REALMS)
519 if (re
->tag
> 0 && re
->tag
<= 255)
520 vty_out(vty
, "(realm)");
524 vty_out(vty
, ", mtu %u", re
->mtu
);
525 if (re
->vrf_id
!= VRF_DEFAULT
) {
526 zvrf
= vrf_info_lookup(re
->vrf_id
);
527 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
529 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
530 vty_out(vty
, ", best");
533 uptime2str(re
->uptime
, buf
, sizeof(buf
));
535 vty_out(vty
, " Last update %s ago\n", buf
);
538 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
540 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
541 /* Use helper to format each nexthop */
542 show_nexthop_detail_helper(vty
, re
, nexthop
,
543 false /*not backup*/);
546 /* Include backup(s), if present */
547 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
548 show_nh_backup_helper(vty
, re
, nexthop
);
550 zebra_show_ip_route_opaque(vty
, re
, NULL
);
557 * Helper for nexthop output, used in the 'show ip route' path
559 static void show_route_nexthop_helper(struct vty
*vty
,
560 const struct route_entry
*re
,
561 const struct nexthop
*nexthop
)
563 char buf
[MPLS_LABEL_STRLEN
];
566 switch (nexthop
->type
) {
567 case NEXTHOP_TYPE_IPV4
:
568 case NEXTHOP_TYPE_IPV4_IFINDEX
:
569 vty_out(vty
, " via %pI4", &nexthop
->gate
.ipv4
);
570 if (nexthop
->ifindex
)
572 ifindex2ifname(nexthop
->ifindex
,
575 case NEXTHOP_TYPE_IPV6
:
576 case NEXTHOP_TYPE_IPV6_IFINDEX
:
577 vty_out(vty
, " via %s",
578 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
580 if (nexthop
->ifindex
)
582 ifindex2ifname(nexthop
->ifindex
,
586 case NEXTHOP_TYPE_IFINDEX
:
587 vty_out(vty
, " is directly connected, %s",
588 ifindex2ifname(nexthop
->ifindex
,
591 case NEXTHOP_TYPE_BLACKHOLE
:
592 vty_out(vty
, " unreachable");
593 switch (nexthop
->bh_type
) {
594 case BLACKHOLE_REJECT
:
595 vty_out(vty
, " (ICMP unreachable)");
597 case BLACKHOLE_ADMINPROHIB
:
598 vty_out(vty
, " (ICMP admin-prohibited)");
601 vty_out(vty
, " (blackhole)");
603 case BLACKHOLE_UNSPEC
:
609 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
610 vty_out(vty
, " (vrf %s)", vrf_id_to_name(nexthop
->vrf_id
));
612 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
613 vty_out(vty
, " inactive");
615 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
616 vty_out(vty
, " onlink");
618 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
619 vty_out(vty
, " (recursive)");
621 switch (nexthop
->type
) {
622 case NEXTHOP_TYPE_IPV4
:
623 case NEXTHOP_TYPE_IPV4_IFINDEX
:
624 if (nexthop
->src
.ipv4
.s_addr
) {
625 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
627 vty_out(vty
, ", src %s", buf
);
628 /* SR-TE information */
629 if (nexthop
->srte_color
)
630 vty_out(vty
, ", SR-TE color %u",
631 nexthop
->srte_color
);
634 case NEXTHOP_TYPE_IPV6
:
635 case NEXTHOP_TYPE_IPV6_IFINDEX
:
636 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
637 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
639 vty_out(vty
, ", src %s", buf
);
646 /* Label information */
647 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
648 vty_out(vty
, ", label %s",
649 mpls_label2str(nexthop
->nh_label
->num_labels
,
650 nexthop
->nh_label
->label
, buf
,
654 if (nexthop
->nh_srv6
) {
655 seg6local_context2str(buf
, sizeof(buf
),
656 &nexthop
->nh_srv6
->seg6local_ctx
,
657 nexthop
->nh_srv6
->seg6local_action
);
658 vty_out(vty
, ", seg6local %s %s", seg6local_action2str(
659 nexthop
->nh_srv6
->seg6local_action
), buf
);
661 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
663 vty_out(vty
, ", seg6 %s", buf
);
667 vty_out(vty
, ", weight %u", nexthop
->weight
);
669 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
670 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
672 for (i
= 1; i
< nexthop
->backup_num
; i
++)
673 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
678 * Render a nexthop into a json object; the caller allocates and owns
679 * the json object memory.
681 static void show_nexthop_json_helper(json_object
*json_nexthop
,
682 const struct nexthop
*nexthop
,
683 const struct route_entry
*re
)
685 char buf
[SRCDEST2STR_BUFFER
];
686 json_object
*json_labels
= NULL
;
687 json_object
*json_backups
= NULL
;
688 json_object
*json_seg6local
= NULL
;
689 json_object
*json_seg6
= NULL
;
692 json_object_int_add(json_nexthop
, "flags",
695 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
696 json_object_boolean_true_add(json_nexthop
,
699 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
700 json_object_boolean_true_add(json_nexthop
,
703 switch (nexthop
->type
) {
704 case NEXTHOP_TYPE_IPV4
:
705 case NEXTHOP_TYPE_IPV4_IFINDEX
:
706 json_object_string_add(
708 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
,
710 json_object_string_add(json_nexthop
, "afi",
713 if (nexthop
->ifindex
) {
714 json_object_int_add(json_nexthop
,
717 json_object_string_add(
718 json_nexthop
, "interfaceName",
724 case NEXTHOP_TYPE_IPV6
:
725 case NEXTHOP_TYPE_IPV6_IFINDEX
:
726 json_object_string_add(
728 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
730 json_object_string_add(json_nexthop
, "afi",
733 if (nexthop
->ifindex
) {
734 json_object_int_add(json_nexthop
,
737 json_object_string_add(
738 json_nexthop
, "interfaceName",
745 case NEXTHOP_TYPE_IFINDEX
:
746 json_object_boolean_true_add(
747 json_nexthop
, "directlyConnected");
748 json_object_int_add(json_nexthop
,
751 json_object_string_add(
752 json_nexthop
, "interfaceName",
753 ifindex2ifname(nexthop
->ifindex
,
756 case NEXTHOP_TYPE_BLACKHOLE
:
757 json_object_boolean_true_add(json_nexthop
,
759 switch (nexthop
->bh_type
) {
760 case BLACKHOLE_REJECT
:
761 json_object_boolean_true_add(
762 json_nexthop
, "reject");
764 case BLACKHOLE_ADMINPROHIB
:
765 json_object_boolean_true_add(
770 json_object_boolean_true_add(
771 json_nexthop
, "blackhole");
773 case BLACKHOLE_UNSPEC
:
779 if (nexthop
->vrf_id
!= re
->vrf_id
)
780 json_object_string_add(json_nexthop
, "vrf",
781 vrf_id_to_name(nexthop
->vrf_id
));
783 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
784 json_object_boolean_true_add(json_nexthop
,
787 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
788 json_object_boolean_true_add(json_nexthop
,
791 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
792 json_object_boolean_true_add(json_nexthop
,
795 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
796 json_object_boolean_true_add(json_nexthop
,
799 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
800 json_backups
= json_object_new_array();
801 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
802 json_object_array_add(
804 json_object_new_int(nexthop
->backup_idx
[i
]));
807 json_object_object_add(json_nexthop
, "backupIndex",
811 switch (nexthop
->type
) {
812 case NEXTHOP_TYPE_IPV4
:
813 case NEXTHOP_TYPE_IPV4_IFINDEX
:
814 if (nexthop
->src
.ipv4
.s_addr
) {
815 if (inet_ntop(AF_INET
,
816 &nexthop
->src
.ipv4
, buf
,
818 json_object_string_add(
819 json_nexthop
, "source",
823 case NEXTHOP_TYPE_IPV6
:
824 case NEXTHOP_TYPE_IPV6_IFINDEX
:
825 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
827 if (inet_ntop(AF_INET6
,
828 &nexthop
->src
.ipv6
, buf
,
830 json_object_string_add(
831 json_nexthop
, "source",
839 if (nexthop
->nh_label
840 && nexthop
->nh_label
->num_labels
) {
841 json_labels
= json_object_new_array();
843 for (int label_index
= 0;
845 < nexthop
->nh_label
->num_labels
;
847 json_object_array_add(
850 nexthop
->nh_label
->label
853 json_object_object_add(json_nexthop
, "labels",
858 json_object_int_add(json_nexthop
, "weight",
861 if (nexthop
->srte_color
)
862 json_object_int_add(json_nexthop
, "srteColor",
863 nexthop
->srte_color
);
865 if (nexthop
->nh_srv6
) {
866 json_seg6local
= json_object_new_object();
867 json_object_string_add(
868 json_seg6local
, "action", seg6local_action2str(
869 nexthop
->nh_srv6
->seg6local_action
));
870 json_object_object_add(json_nexthop
, "seg6local",
873 json_seg6
= json_object_new_object();
874 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
876 json_object_string_add(json_seg6
, "segs", buf
);
877 json_object_object_add(json_nexthop
, "seg6", json_seg6
);
881 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
882 struct route_entry
*re
, json_object
*json
,
885 const struct nexthop
*nexthop
;
887 char buf
[SRCDEST2STR_BUFFER
];
888 json_object
*json_nexthops
= NULL
;
889 json_object
*json_nexthop
= NULL
;
890 json_object
*json_route
= NULL
;
891 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
892 const struct nexthop_group
*nhg
;
893 char up_str
[MONOTIME_STRLEN
];
895 bool nhg_from_backup
= false;
897 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
899 /* If showing fib information, use the fib view of the
903 nhg
= rib_get_fib_nhg(re
);
905 nhg
= &(re
->nhe
->nhg
);
908 json_route
= json_object_new_object();
909 json_nexthops
= json_object_new_array();
911 json_object_string_add(json_route
, "prefix",
912 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
913 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
914 json_object_string_add(json_route
, "protocol",
915 zebra_route_string(re
->type
));
918 json_object_int_add(json_route
, "instance",
921 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
922 json_object_string_add(json_route
, "vrfName",
923 vrf_id_to_name(re
->vrf_id
));
925 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
926 json_object_boolean_true_add(json_route
, "selected");
928 if (dest
->selected_fib
== re
)
929 json_object_boolean_true_add(json_route
,
932 json_object_int_add(json_route
, "distance",
934 json_object_int_add(json_route
, "metric", re
->metric
);
936 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
937 json_object_boolean_true_add(json_route
, "installed");
939 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
940 json_object_boolean_true_add(json_route
, "failed");
942 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
943 json_object_boolean_true_add(json_route
, "queued");
945 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
946 json_object_boolean_true_add(json_route
, "trapped");
948 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
949 json_object_boolean_true_add(json_route
, "offloaded");
951 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
952 json_object_boolean_false_add(json_route
, "offloaded");
955 json_object_int_add(json_route
, "tag", re
->tag
);
958 json_object_int_add(json_route
, "table", re
->table
);
960 json_object_int_add(json_route
, "internalStatus",
962 json_object_int_add(json_route
, "internalFlags",
964 json_object_int_add(json_route
, "internalNextHopNum",
965 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
966 json_object_int_add(json_route
, "internalNextHopActiveNum",
967 nexthop_group_active_nexthop_num(
969 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
971 json_object_string_add(json_route
, "uptime", up_str
);
973 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
974 json_nexthop
= json_object_new_object();
975 show_nexthop_json_helper(json_nexthop
,
978 json_object_array_add(json_nexthops
,
982 json_object_object_add(json_route
, "nexthops", json_nexthops
);
984 /* If there are backup nexthops, include them */
986 nhg
= rib_get_fib_backup_nhg(re
);
988 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
990 if (nhg
&& nhg
->nexthop
) {
991 json_nexthops
= json_object_new_array();
993 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
994 json_nexthop
= json_object_new_object();
996 show_nexthop_json_helper(json_nexthop
,
998 json_object_array_add(json_nexthops
,
1002 json_object_object_add(json_route
, "backupNexthops",
1005 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
1007 json_object_array_add(json
, json_route
);
1011 /* Prefix information, and first nexthop. If we're showing 'fib',
1012 * and there are no installed primary nexthops, see if there are any
1013 * backup nexthops and start with those.
1015 if (is_fib
&& nhg
->nexthop
== NULL
) {
1016 nhg
= rib_get_fib_backup_nhg(re
);
1017 nhg_from_backup
= true;
1020 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1022 len
+= vty_out(vty
, "[%d]", re
->instance
);
1023 if (nhg_from_backup
&& nhg
->nexthop
) {
1026 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1027 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1028 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1032 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1033 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1034 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1037 /* Distance and metric display. */
1038 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
1039 (re
->distance
|| re
->metric
)) ||
1040 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
1041 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1044 /* Nexthop information. */
1045 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1048 } else if (nhg_from_backup
) {
1049 vty_out(vty
, " b%c%*c",
1050 re_status_output_char(re
, nexthop
, is_fib
),
1051 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1053 vty_out(vty
, " %c%*c",
1054 re_status_output_char(re
, nexthop
, is_fib
),
1055 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1058 show_route_nexthop_helper(vty
, re
, nexthop
);
1059 vty_out(vty
, ", %s\n", up_str
);
1062 /* If we only had backup nexthops, we're done */
1063 if (nhg_from_backup
)
1066 /* Check for backup nexthop info if present */
1068 nhg
= rib_get_fib_backup_nhg(re
);
1070 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1075 /* Print backup info */
1076 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1077 bool star_p
= false;
1080 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1082 /* TODO -- it'd be nice to be able to include
1083 * the entire list of backups, *and* include the
1084 * real installation state.
1086 vty_out(vty
, " b%c %*c",
1087 (star_p
? '*' : ' '),
1088 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1089 show_route_nexthop_helper(vty
, re
, nexthop
);
1095 static void vty_show_ip_route_detail_json(struct vty
*vty
,
1096 struct route_node
*rn
, bool use_fib
)
1098 json_object
*json
= NULL
;
1099 json_object
*json_prefix
= NULL
;
1100 struct route_entry
*re
;
1104 dest
= rib_dest_from_rnode(rn
);
1106 json
= json_object_new_object();
1107 json_prefix
= json_object_new_array();
1109 RNODE_FOREACH_RE (rn
, re
) {
1111 * If re not selected for forwarding, skip re
1112 * for "show ip/ipv6 fib <prefix> json"
1114 if (use_fib
&& re
!= dest
->selected_fib
)
1116 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
);
1119 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1120 json_object_object_add(json
, buf
, json_prefix
);
1121 vty_out(vty
, "%s\n",
1122 json_object_to_json_string_ext(
1123 json
, JSON_C_TO_STRING_PRETTY
1124 | JSON_C_TO_STRING_NOSLASHESCAPE
));
1125 json_object_free(json
);
1128 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1129 struct route_table
*table
, afi_t afi
,
1130 bool use_fib
, route_tag_t tag
,
1131 const struct prefix
*longer_prefix_p
,
1132 bool supernets_only
, int type
,
1133 unsigned short ospf_instance_id
, bool use_json
,
1134 uint32_t tableid
, struct route_show_ctx
*ctx
)
1136 struct route_node
*rn
;
1137 struct route_entry
*re
;
1140 json_object
*json
= NULL
;
1141 json_object
*json_prefix
= NULL
;
1146 * ctx->multi indicates if we are dumping multiple tables or vrfs.
1148 * => display the common header at most once
1149 * => add newline at each call except first
1150 * => always display the VRF and table
1152 * => display the common header if at least one entry is found
1153 * => display the VRF and table if specific
1157 json
= json_object_new_object();
1159 /* Show all routes. */
1160 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
1161 dest
= rib_dest_from_rnode(rn
);
1163 RNODE_FOREACH_RE (rn
, re
) {
1164 if (use_fib
&& re
!= dest
->selected_fib
)
1167 if (tag
&& re
->tag
!= tag
)
1171 && !prefix_match(longer_prefix_p
, &rn
->p
))
1174 /* This can only be true when the afi is IPv4 */
1175 if (supernets_only
) {
1176 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1178 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1181 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1184 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1188 if (type
&& re
->type
!= type
)
1191 if (ospf_instance_id
1192 && (re
->type
!= ZEBRA_ROUTE_OSPF
1193 || re
->instance
!= ospf_instance_id
))
1198 json_prefix
= json_object_new_array();
1200 if (!ctx
->header_done
) {
1203 SHOW_ROUTE_V4_HEADER
);
1206 SHOW_ROUTE_V6_HEADER
);
1208 if (ctx
->multi
&& ctx
->header_done
)
1210 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
1213 vty_out(vty
, "VRF %s:\n",
1217 "VRF %s table %u:\n",
1221 ctx
->header_done
= true;
1225 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
);
1229 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1230 json_object_object_add(json
, buf
, json_prefix
);
1236 vty_out(vty
, "%s\n",
1237 json_object_to_json_string_ext(
1239 JSON_C_TO_STRING_PRETTY
1240 | JSON_C_TO_STRING_NOSLASHESCAPE
));
1241 json_object_free(json
);
1245 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1246 afi_t afi
, bool use_fib
, bool use_json
,
1248 const struct prefix
*longer_prefix_p
,
1249 bool supernets_only
, int type
,
1250 unsigned short ospf_instance_id
,
1251 struct route_show_ctx
*ctx
)
1253 struct zebra_router_table
*zrt
;
1254 struct rib_table_info
*info
;
1256 RB_FOREACH (zrt
, zebra_router_table_head
,
1258 info
= route_table_get_info(zrt
->table
);
1260 if (zvrf
!= info
->zvrf
)
1262 if (zrt
->afi
!= afi
||
1263 zrt
->safi
!= SAFI_UNICAST
)
1266 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1267 use_fib
, use_json
, tag
, longer_prefix_p
,
1268 supernets_only
, type
, ospf_instance_id
,
1273 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1274 safi_t safi
, bool use_fib
, bool use_json
,
1276 const struct prefix
*longer_prefix_p
,
1277 bool supernets_only
, int type
,
1278 unsigned short ospf_instance_id
, uint32_t tableid
,
1279 struct route_show_ctx
*ctx
)
1281 struct route_table
*table
;
1282 struct zebra_vrf
*zvrf
= NULL
;
1284 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1286 vty_out(vty
, "{}\n");
1288 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1292 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1294 vty_out(vty
, "{}\n");
1296 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1301 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1303 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1306 vty_out(vty
, "{}\n");
1310 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1311 longer_prefix_p
, supernets_only
, type
,
1312 ospf_instance_id
, use_json
, tableid
, ctx
);
1319 "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]",
1323 "IP nexthop tracking table\n"
1324 "IP import check tracking table\n"
1330 VRF_ALL_CMD_HELP_STR
)
1332 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1333 vrf_id_t vrf_id
= VRF_DEFAULT
;
1334 struct prefix prefix
, *p
= NULL
;
1335 enum rnh_type rtype
;
1337 if (strcmp(type
, "nht") == 0)
1338 rtype
= RNH_NEXTHOP_TYPE
;
1340 rtype
= RNH_IMPORT_CHECK_TYPE
;
1344 struct zebra_vrf
*zvrf
;
1346 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1347 if ((zvrf
= vrf
->info
) != NULL
) {
1348 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1349 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, vty
,
1355 VRF_GET_ID(vrf_id
, vrf_name
, false);
1357 memset(&prefix
, 0, sizeof(prefix
));
1359 p
= sockunion2hostprefix(addr
, &prefix
);
1364 zebra_print_rnh_table(vrf_id
, afi
, vty
, rtype
, p
);
1368 DEFUN (ip_nht_default_route
,
1369 ip_nht_default_route_cmd
,
1370 "ip nht resolve-via-default",
1372 "Filter Next Hop tracking route resolution\n"
1373 "Resolve via default route\n")
1375 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
1380 if (zvrf
->zebra_rnh_ip_default_route
)
1383 zvrf
->zebra_rnh_ip_default_route
= 1;
1385 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, RNH_NEXTHOP_TYPE
, NULL
);
1389 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
)
1391 struct nexthop
*nexthop
= NULL
;
1392 struct nhg_connected
*rb_node_dep
= NULL
;
1393 struct nexthop_group
*backup_nhg
;
1394 char up_str
[MONOTIME_STRLEN
];
1396 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1398 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
, zebra_route_string(nhe
->type
));
1399 vty_out(vty
, " RefCnt: %u\n", nhe
->refcnt
);
1400 vty_out(vty
, " Uptime: %s\n", up_str
);
1401 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1403 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1404 vty_out(vty
, " Valid");
1405 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
))
1406 vty_out(vty
, ", Installed");
1410 vty_out(vty
, " Interface Index: %d\n", nhe
->ifp
->ifindex
);
1412 if (!zebra_nhg_depends_is_empty(nhe
)) {
1413 vty_out(vty
, " Depends:");
1414 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1415 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1420 /* Output nexthops */
1421 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1422 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1425 /* Make recursive nexthops a bit more clear */
1428 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1430 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1431 if (CHECK_FLAG(nexthop
->flags
,
1432 NEXTHOP_FLAG_HAS_BACKUP
))
1433 vty_out(vty
, " [backup %d]",
1434 nexthop
->backup_idx
[0]);
1440 /* TODO -- print more useful backup info */
1441 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
1444 vty_out(vty
, "[backup");
1445 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1446 vty_out(vty
, " %d", nexthop
->backup_idx
[i
]);
1454 /* Output backup nexthops (if any) */
1455 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1457 vty_out(vty
, " Backups:\n");
1459 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1460 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1463 /* Make recursive nexthops a bit more clear */
1466 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1471 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1472 vty_out(vty
, " Dependents:");
1473 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1475 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1482 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
)
1484 struct nhg_hash_entry
*nhe
= NULL
;
1486 nhe
= zebra_nhg_lookup_id(id
);
1489 show_nexthop_group_out(vty
, nhe
);
1491 vty_out(vty
, "Nexthop Group ID: %u does not exist\n", id
);
1497 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1499 struct nhe_show_context
{
1506 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1508 struct nhe_show_context
*ctx
= arg
;
1509 struct nhg_hash_entry
*nhe
;
1511 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1513 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1516 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1519 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1522 show_nexthop_group_out(ctx
->vty
, nhe
);
1525 return HASHWALK_CONTINUE
;
1528 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1529 struct zebra_vrf
*zvrf
, afi_t afi
,
1532 struct nhe_show_context ctx
;
1536 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1539 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1542 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1544 struct zebra_if
*zebra_if
= NULL
;
1545 struct nhg_connected
*rb_node_dep
= NULL
;
1547 zebra_if
= ifp
->info
;
1549 if (!if_nhg_dependents_is_empty(ifp
)) {
1550 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1552 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1555 show_nexthop_group_out(vty
, rb_node_dep
->nhe
);
1560 DEFPY (show_interface_nexthop_group
,
1561 show_interface_nexthop_group_cmd
,
1562 "show interface [IFNAME$if_name] nexthop-group",
1564 "Interface status and configuration\n"
1566 "Show Nexthop Groups\n")
1568 struct vrf
*vrf
= NULL
;
1569 struct interface
*ifp
= NULL
;
1572 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1574 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1576 if_nexthop_group_dump_vty(vty
, ifp
);
1580 FOR_ALL_INTERFACES (vrf
, ifp
)
1581 if_nexthop_group_dump_vty(vty
, ifp
);
1587 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1594 DEFPY (show_nexthop_group
,
1595 show_nexthop_group_cmd
,
1596 "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>]>",
1598 "Show Nexthop Groups\n"
1600 "Nexthop Group ID\n"
1601 "Show Singleton Nexthop-Groups\n"
1604 "Kernel (not installed via the zebra RIB)\n"
1605 "Zebra (implicitly created by zebra)\n"
1606 "Border Gateway Protocol (BGP)\n"
1607 "Super Happy Advanced Routing Protocol (SHARP)\n"
1608 VRF_FULL_CMD_HELP_STR
)
1611 struct zebra_vrf
*zvrf
= NULL
;
1612 afi_t afi
= AFI_UNSPEC
;
1616 return show_nexthop_group_id_cmd_helper(vty
, id
);
1624 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1627 type
= ZEBRA_ROUTE_NHG
;
1631 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1633 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1640 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1641 struct zebra_vrf
*zvrf
;
1647 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1648 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1655 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1657 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1660 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1665 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1670 DEFPY_HIDDEN(nexthop_group_use_enable
,
1671 nexthop_group_use_enable_cmd
,
1672 "[no] zebra nexthop kernel enable",
1675 "Nexthop configuration \n"
1676 "Configure use of kernel nexthops\n"
1677 "Enable kernel nexthops\n")
1679 zebra_nhg_enable_kernel_nexthops(!no
);
1683 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1684 "[no] zebra nexthop proto only",
1686 "Nexthop configuration\n"
1687 "Configure exclusive use of proto nexthops\n"
1688 "Only use proto nexthops\n")
1690 zebra_nhg_set_proto_nexthops_only(!no
);
1694 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1695 backup_nexthop_recursive_use_enable_cmd
,
1696 "[no] zebra nexthop resolve-via-backup",
1699 "Nexthop configuration \n"
1700 "Configure use of backup nexthops in recursive resolution\n")
1702 zebra_nhg_set_recursive_use_backups(!no
);
1706 DEFUN (no_ip_nht_default_route
,
1707 no_ip_nht_default_route_cmd
,
1708 "no ip nht resolve-via-default",
1711 "Filter Next Hop tracking route resolution\n"
1712 "Resolve via default route\n")
1714 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
1719 if (!zvrf
->zebra_rnh_ip_default_route
)
1722 zvrf
->zebra_rnh_ip_default_route
= 0;
1723 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, RNH_NEXTHOP_TYPE
, NULL
);
1727 DEFUN (ipv6_nht_default_route
,
1728 ipv6_nht_default_route_cmd
,
1729 "ipv6 nht resolve-via-default",
1731 "Filter Next Hop tracking route resolution\n"
1732 "Resolve via default route\n")
1734 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
1739 if (zvrf
->zebra_rnh_ipv6_default_route
)
1742 zvrf
->zebra_rnh_ipv6_default_route
= 1;
1743 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, RNH_NEXTHOP_TYPE
, NULL
);
1747 DEFUN (no_ipv6_nht_default_route
,
1748 no_ipv6_nht_default_route_cmd
,
1749 "no ipv6 nht resolve-via-default",
1752 "Filter Next Hop tracking route resolution\n"
1753 "Resolve via default route\n")
1755 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
1760 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1763 zvrf
->zebra_rnh_ipv6_default_route
= 0;
1764 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, RNH_NEXTHOP_TYPE
, NULL
);
1768 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1769 "[no] ip nht hide-backup-events",
1772 "Nexthop-tracking configuration\n"
1773 "Hide notification about backup nexthops\n")
1775 rnh_set_hide_backups(!no
);
1783 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1784 [vrf <NAME$vrf_name|all$vrf_all>]\
1787 |A.B.C.D/M$prefix longer-prefixes\
1788 |supernets-only$supernets_only\
1791 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1792 |ospf$type_str (1-65535)$ospf_instance_id\
1794 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1795 [vrf <NAME$vrf_name|all$vrf_all>]\
1798 |X:X::X:X/M$prefix longer-prefixes\
1800 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1805 "IP forwarding table\n"
1806 "IP routing table\n"
1807 "Table to display\n"
1808 "The table number to display\n"
1810 VRF_FULL_CMD_HELP_STR
1811 "Show only routes with tag\n"
1813 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1814 "Show route matching the specified Network/Mask pair only\n"
1815 "Show supernet entries only\n"
1816 FRR_IP_REDIST_HELP_STR_ZEBRA
1817 "Open Shortest Path First (OSPFv2)\n"
1820 "IP forwarding table\n"
1821 "IP routing table\n"
1822 "Table to display\n"
1823 "The table number to display\n"
1825 VRF_FULL_CMD_HELP_STR
1826 "Show only routes with tag\n"
1829 "Show route matching the specified Network/Mask pair only\n"
1830 FRR_IP6_REDIST_HELP_STR_ZEBRA
1833 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1836 struct zebra_vrf
*zvrf
;
1837 struct route_show_ctx ctx
= {
1838 .multi
= vrf_all
|| table_all
,
1841 if (!vrf_is_backend_netns()) {
1842 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1844 vty_out(vty
, "{}\n");
1846 vty_out(vty
, "Linux vrf backend already points to table id\n");
1847 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1853 type
= proto_redistnum(afi
, type_str
);
1855 vty_out(vty
, "Unknown route type\n");
1861 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1862 if ((zvrf
= vrf
->info
) == NULL
1863 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1867 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
,
1869 prefix_str
? prefix
: NULL
,
1870 !!supernets_only
, type
,
1871 ospf_instance_id
, &ctx
);
1873 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
,
1874 SAFI_UNICAST
, !!fib
, !!json
,
1876 prefix_str
? prefix
: NULL
,
1877 !!supernets_only
, type
,
1878 ospf_instance_id
, table
, &ctx
);
1881 vrf_id_t vrf_id
= VRF_DEFAULT
;
1884 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1885 vrf
= vrf_lookup_by_id(vrf_id
);
1894 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1895 prefix_str
? prefix
: NULL
,
1896 !!supernets_only
, type
,
1897 ospf_instance_id
, &ctx
);
1899 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1901 prefix_str
? prefix
: NULL
,
1902 !!supernets_only
, type
,
1903 ospf_instance_id
, table
, &ctx
);
1909 ALIAS_HIDDEN (show_route
,
1911 "show <ip$ipv4|ipv6$ipv6> ro",
1915 "IP routing table\n");
1918 DEFPY (show_route_detail
,
1919 show_route_detail_cmd
,
1922 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1927 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1933 [json$json] [nexthop-group$ng]",
1936 "IPv6 forwarding table\n"
1937 "IP routing table\n"
1938 VRF_FULL_CMD_HELP_STR
1939 "Network in the IP routing table to display\n"
1940 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1942 "IPv6 forwarding table\n"
1943 "IPv6 routing table\n"
1944 VRF_FULL_CMD_HELP_STR
1948 "Nexthop Group Information\n")
1950 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1951 struct route_table
*table
;
1953 struct route_node
*rn
;
1954 bool use_fib
= !!fib
;
1956 bool network_found
= false;
1957 bool show_ng
= !!ng
;
1960 prefix_str
= address_str
;
1961 if (str2prefix(prefix_str
, &p
) < 0) {
1962 vty_out(vty
, "%% Malformed address\n");
1968 struct zebra_vrf
*zvrf
;
1970 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1971 if ((zvrf
= vrf
->info
) == NULL
1972 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1975 rn
= route_node_match(table
, &p
);
1978 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1979 route_unlock_node(rn
);
1983 dest
= rib_dest_from_rnode(rn
);
1984 if (use_fib
&& !dest
->selected_fib
) {
1985 route_unlock_node(rn
);
1989 network_found
= true;
1991 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1993 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1996 route_unlock_node(rn
);
1999 if (!network_found
) {
2001 vty_out(vty
, "{}\n");
2005 "%% Network not in FIB\n");
2008 "%% Network not in RIB\n");
2013 vrf_id_t vrf_id
= VRF_DEFAULT
;
2016 VRF_GET_ID(vrf_id
, vrf_name
, false);
2018 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2022 rn
= route_node_match(table
, &p
);
2024 dest
= rib_dest_from_rnode(rn
);
2026 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
2027 (use_fib
&& dest
&& !dest
->selected_fib
)) {
2029 vty_out(vty
, "{}\n");
2033 "%% Network not in FIB\n");
2036 "%% Network not in table\n");
2039 route_unlock_node(rn
);
2044 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2046 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2048 route_unlock_node(rn
);
2054 DEFPY (show_route_summary
,
2055 show_route_summary_cmd
,
2056 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2057 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2061 "IP routing table\n"
2062 VRF_FULL_CMD_HELP_STR
2063 "Summary of all routes\n"
2064 "Table to display summary for\n"
2065 "The table number\n"
2069 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2070 struct route_table
*table
;
2071 bool uj
= use_json(argc
, argv
);
2075 struct zebra_vrf
*zvrf
;
2077 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2078 if ((zvrf
= vrf
->info
) == NULL
)
2082 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2085 table
= zebra_vrf_lookup_table_with_table_id(
2086 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2093 vty_show_ip_route_summary_prefix(vty
, table
,
2096 vty_show_ip_route_summary(vty
, table
, uj
);
2099 vrf_id_t vrf_id
= VRF_DEFAULT
;
2102 VRF_GET_ID(vrf_id
, vrf_name
, false);
2105 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2107 table
= zebra_vrf_lookup_table_with_table_id(
2108 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2113 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2115 vty_show_ip_route_summary(vty
, table
, uj
);
2121 DEFUN_HIDDEN (show_route_zebra_dump
,
2122 show_route_zebra_dump_cmd
,
2123 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2133 struct route_table
*table
;
2134 const char *vrf_name
= NULL
;
2137 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2139 if (argv_find(argv
, argc
, "vrf", &idx
))
2140 vrf_name
= argv
[++idx
]->arg
;
2144 struct zebra_vrf
*zvrf
;
2146 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2149 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2152 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2153 show_ip_route_dump_vty(vty
, table
);
2156 vrf_id_t vrf_id
= VRF_DEFAULT
;
2158 VRF_GET_ID(vrf_id
, vrf_name
, true);
2160 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2164 show_ip_route_dump_vty(vty
, table
);
2170 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2171 struct route_entry
*re
, unsigned int num
)
2174 char buf
[SRCDEST2STR_BUFFER
];
2176 vty_out(vty
, " Nexthop %u:\n", num
);
2177 vty_out(vty
, " type: %u\n", nexthop
->type
);
2178 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2179 switch (nexthop
->type
) {
2180 case NEXTHOP_TYPE_IPV4
:
2181 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2182 vty_out(vty
, " ip address: %s\n",
2183 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2185 vty_out(vty
, " afi: ipv4\n");
2187 if (nexthop
->ifindex
) {
2188 vty_out(vty
, " interface index: %d\n",
2190 vty_out(vty
, " interface name: %s\n",
2191 ifindex2ifname(nexthop
->ifindex
,
2195 if (nexthop
->src
.ipv4
.s_addr
2196 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2198 vty_out(vty
, " source: %s\n", buf
);
2200 case NEXTHOP_TYPE_IPV6
:
2201 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2202 vty_out(vty
, " ip: %s\n",
2203 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2205 vty_out(vty
, " afi: ipv6\n");
2207 if (nexthop
->ifindex
) {
2208 vty_out(vty
, " interface index: %d\n",
2210 vty_out(vty
, " interface name: %s\n",
2211 ifindex2ifname(nexthop
->ifindex
,
2215 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2216 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2218 vty_out(vty
, " source: %s\n", buf
);
2221 case NEXTHOP_TYPE_IFINDEX
:
2223 " Nexthop is an interface (directly connected).\n");
2224 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2225 vty_out(vty
, " interface name: %s\n",
2226 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2228 case NEXTHOP_TYPE_BLACKHOLE
:
2229 vty_out(vty
, " Nexthop type is blackhole.\n");
2231 switch (nexthop
->bh_type
) {
2232 case BLACKHOLE_REJECT
:
2233 vty_out(vty
, " Blackhole type: reject\n");
2235 case BLACKHOLE_ADMINPROHIB
:
2237 " Blackhole type: admin-prohibited\n");
2239 case BLACKHOLE_NULL
:
2240 vty_out(vty
, " Blackhole type: NULL0\n");
2242 case BLACKHOLE_UNSPEC
:
2249 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2251 struct route_node
*rn
;
2252 struct route_entry
*re
;
2253 char buf
[SRCDEST2STR_BUFFER
];
2258 struct nexthop
*nexthop
= NULL
;
2259 int nexthop_num
= 0;
2261 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2262 vty_out(vty
, "----------------------------\n");
2264 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2265 RNODE_FOREACH_RE (rn
, re
) {
2266 vty_out(vty
, "Route: %s\n",
2267 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2268 vty_out(vty
, " protocol: %s\n",
2269 zebra_route_string(re
->type
));
2270 vty_out(vty
, " instance: %u\n", re
->instance
);
2271 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2272 vty_out(vty
, " VRF name: %s\n",
2273 vrf_id_to_name(re
->vrf_id
));
2274 vty_out(vty
, " flags: %u\n", re
->flags
);
2276 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2277 vty_out(vty
, " distance: %u\n", re
->distance
);
2278 vty_out(vty
, " metric: %u\n", re
->metric
);
2281 vty_out(vty
, " tag: %u\n", re
->tag
);
2283 uptime
= monotime(&tv
);
2284 uptime
-= re
->uptime
;
2285 gmtime_r(&uptime
, &tm
);
2287 if (uptime
< ONE_DAY_SECOND
)
2288 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2289 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2290 else if (uptime
< ONE_WEEK_SECOND
)
2291 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2292 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2294 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2296 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2299 vty_out(vty
, " status: %u\n", re
->status
);
2300 vty_out(vty
, " nexthop_num: %u\n",
2301 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2302 vty_out(vty
, " nexthop_active_num: %u\n",
2303 nexthop_group_active_nexthop_num(
2305 vty_out(vty
, " table: %u\n", re
->table
);
2306 vty_out(vty
, " uptime: %s\n", time
);
2308 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2310 show_ip_route_nht_dump(vty
, nexthop
, re
,
2320 static void vty_show_ip_route_summary(struct vty
*vty
,
2321 struct route_table
*table
, bool use_json
)
2323 struct route_node
*rn
;
2324 struct route_entry
*re
;
2325 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2326 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2327 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2328 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2329 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2330 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2333 json_object
*json_route_summary
= NULL
;
2334 json_object
*json_route_routes
= NULL
;
2336 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2337 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2338 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2339 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2342 json_route_summary
= json_object_new_object();
2343 json_route_routes
= json_object_new_array();
2344 json_object_object_add(json_route_summary
, "routes",
2348 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2349 RNODE_FOREACH_RE (rn
, re
) {
2350 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2351 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2353 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2355 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2357 rib_cnt
[re
->type
]++;
2359 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2360 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2363 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2365 fib_cnt
[re
->type
]++;
2368 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2370 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2372 trap_cnt
[re
->type
]++;
2375 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2377 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2379 offload_cnt
[re
->type
]++;
2384 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2386 zvrf_name(((struct rib_table_info
*)
2387 route_table_get_info(table
))
2390 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2391 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2392 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2393 if (i
== ZEBRA_ROUTE_BGP
) {
2395 json_object
*json_route_ebgp
=
2396 json_object_new_object();
2398 json_object_int_add(
2399 json_route_ebgp
, "fib",
2400 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2401 json_object_int_add(
2402 json_route_ebgp
, "rib",
2403 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2404 json_object_int_add(
2405 json_route_ebgp
, "fibOffLoaded",
2406 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2407 json_object_int_add(
2408 json_route_ebgp
, "fibTrapped",
2409 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2411 json_object_string_add(json_route_ebgp
,
2413 json_object_array_add(json_route_routes
,
2416 json_object
*json_route_ibgp
=
2417 json_object_new_object();
2419 json_object_int_add(
2420 json_route_ibgp
, "fib",
2421 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2422 json_object_int_add(
2423 json_route_ibgp
, "rib",
2424 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2425 json_object_int_add(
2426 json_route_ibgp
, "fibOffLoaded",
2427 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2428 json_object_int_add(
2429 json_route_ibgp
, "fibTrapped",
2430 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2431 json_object_string_add(json_route_ibgp
,
2433 json_object_array_add(json_route_routes
,
2436 vty_out(vty
, "%-20s %-20d %-20d \n",
2438 rib_cnt
[ZEBRA_ROUTE_BGP
],
2439 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2440 vty_out(vty
, "%-20s %-20d %-20d \n",
2442 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2443 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2447 json_object
*json_route_type
=
2448 json_object_new_object();
2450 json_object_int_add(json_route_type
,
2452 json_object_int_add(json_route_type
,
2455 json_object_int_add(json_route_type
,
2458 json_object_int_add(json_route_type
,
2461 json_object_string_add(
2462 json_route_type
, "type",
2463 zebra_route_string(i
));
2464 json_object_array_add(json_route_routes
,
2467 vty_out(vty
, "%-20s %-20d %-20d \n",
2468 zebra_route_string(i
),
2469 rib_cnt
[i
], fib_cnt
[i
]);
2475 json_object_int_add(json_route_summary
, "routesTotal",
2476 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2477 json_object_int_add(json_route_summary
, "routesTotalFib",
2478 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2480 vty_out(vty
, "%s\n",
2481 json_object_to_json_string_ext(
2482 json_route_summary
, JSON_C_TO_STRING_PRETTY
));
2483 json_object_free(json_route_summary
);
2485 vty_out(vty
, "------\n");
2486 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2487 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2493 * Implementation of the ip route summary prefix command.
2495 * This command prints the primary prefixes that have been installed by various
2496 * protocols on the box.
2499 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2500 struct route_table
*table
,
2503 struct route_node
*rn
;
2504 struct route_entry
*re
;
2505 struct nexthop
*nexthop
;
2506 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2507 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2508 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2509 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2512 json_object
*json_route_summary
= NULL
;
2513 json_object
*json_route_routes
= NULL
;
2515 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2516 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2519 json_route_summary
= json_object_new_object();
2520 json_route_routes
= json_object_new_array();
2521 json_object_object_add(json_route_summary
, "prefixRoutes",
2525 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2526 RNODE_FOREACH_RE (rn
, re
) {
2529 * In case of ECMP, count only once.
2532 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2533 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2534 fib_cnt
[re
->type
]++;
2536 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2537 nexthop
= nexthop
->next
) {
2539 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2540 rib_cnt
[re
->type
]++;
2541 if (re
->type
== ZEBRA_ROUTE_BGP
2542 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2543 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2544 if (CHECK_FLAG(re
->status
,
2545 ROUTE_ENTRY_INSTALLED
))
2546 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2552 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2553 "Prefix Routes", "FIB",
2554 zvrf_name(((struct rib_table_info
*)
2555 route_table_get_info(table
))
2558 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2559 if (rib_cnt
[i
] > 0) {
2560 if (i
== ZEBRA_ROUTE_BGP
) {
2562 json_object
*json_route_ebgp
=
2563 json_object_new_object();
2565 json_object_int_add(
2566 json_route_ebgp
, "fib",
2567 fib_cnt
[ZEBRA_ROUTE_BGP
]
2568 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2569 json_object_int_add(
2570 json_route_ebgp
, "rib",
2571 rib_cnt
[ZEBRA_ROUTE_BGP
]
2572 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2573 json_object_string_add(json_route_ebgp
,
2575 json_object_array_add(json_route_routes
,
2578 json_object
*json_route_ibgp
=
2579 json_object_new_object();
2581 json_object_int_add(
2582 json_route_ibgp
, "fib",
2583 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2584 json_object_int_add(
2585 json_route_ibgp
, "rib",
2586 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2587 json_object_string_add(json_route_ibgp
,
2589 json_object_array_add(json_route_routes
,
2592 vty_out(vty
, "%-20s %-20d %-20d \n",
2594 rib_cnt
[ZEBRA_ROUTE_BGP
]
2595 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2596 fib_cnt
[ZEBRA_ROUTE_BGP
]
2597 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2598 vty_out(vty
, "%-20s %-20d %-20d \n",
2600 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2601 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2605 json_object
*json_route_type
=
2606 json_object_new_object();
2608 json_object_int_add(json_route_type
,
2610 json_object_int_add(json_route_type
,
2612 json_object_string_add(
2613 json_route_type
, "type",
2614 zebra_route_string(i
));
2615 json_object_array_add(json_route_routes
,
2618 vty_out(vty
, "%-20s %-20d %-20d \n",
2619 zebra_route_string(i
),
2620 rib_cnt
[i
], fib_cnt
[i
]);
2626 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2627 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2628 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2629 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2631 vty_out(vty
, "%s\n",
2632 json_object_to_json_string_ext(
2633 json_route_summary
, JSON_C_TO_STRING_PRETTY
));
2634 json_object_free(json_route_summary
);
2636 vty_out(vty
, "------\n");
2637 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2638 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2644 * Show IPv6 mroute command.Used to dump
2645 * the Multicast routing table.
2647 DEFUN (show_ipv6_mroute
,
2648 show_ipv6_mroute_cmd
,
2649 "show ipv6 mroute [vrf NAME]",
2652 "IPv6 Multicast routing table\n"
2655 struct route_table
*table
;
2656 struct route_node
*rn
;
2657 struct route_entry
*re
;
2659 vrf_id_t vrf_id
= VRF_DEFAULT
;
2662 VRF_GET_ID(vrf_id
, argv
[4]->arg
, false);
2664 table
= zebra_vrf_table(AFI_IP6
, SAFI_MULTICAST
, vrf_id
);
2668 /* Show all IPv6 route. */
2669 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2670 RNODE_FOREACH_RE (rn
, re
) {
2672 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2675 vty_show_ip_route(vty
, rn
, re
, NULL
, false);
2680 DEFUN (show_ipv6_mroute_vrf_all
,
2681 show_ipv6_mroute_vrf_all_cmd
,
2682 "show ipv6 mroute vrf all",
2685 "IPv6 Multicast routing table\n"
2686 VRF_ALL_CMD_HELP_STR
)
2688 struct route_table
*table
;
2689 struct route_node
*rn
;
2690 struct route_entry
*re
;
2692 struct zebra_vrf
*zvrf
;
2695 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2696 if ((zvrf
= vrf
->info
) == NULL
2697 || (table
= zvrf
->table
[AFI_IP6
][SAFI_MULTICAST
]) == NULL
)
2700 /* Show all IPv6 route. */
2701 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2702 RNODE_FOREACH_RE (rn
, re
) {
2704 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2707 vty_show_ip_route(vty
, rn
, re
, NULL
, false);
2713 DEFUN (allow_external_route_update
,
2714 allow_external_route_update_cmd
,
2715 "allow-external-route-update",
2716 "Allow FRR routes to be overwritten by external processes\n")
2723 DEFUN (no_allow_external_route_update
,
2724 no_allow_external_route_update_cmd
,
2725 "no allow-external-route-update",
2727 "Allow FRR routes to be overwritten by external processes\n")
2742 struct zebra_vrf
*zvrf
;
2744 if (vrf_is_backend_netns())
2745 vty_out(vty
, "netns-based vrfs\n");
2747 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2748 if (!(zvrf
= vrf
->info
))
2750 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2753 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2754 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2755 vty_out(vty
, "inactive");
2756 else if (zvrf_ns_name(zvrf
))
2757 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2758 zvrf_ns_name(zvrf
));
2760 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2762 if (vrf_is_user_cfged(vrf
))
2763 vty_out(vty
, " (configured)");
2770 DEFPY (evpn_mh_mac_holdtime
,
2771 evpn_mh_mac_holdtime_cmd
,
2772 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2777 "Duration in seconds\n")
2779 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2783 DEFPY (evpn_mh_neigh_holdtime
,
2784 evpn_mh_neigh_holdtime_cmd
,
2785 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2789 "Neighbor entry hold time\n"
2790 "Duration in seconds\n")
2793 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2797 DEFPY (evpn_mh_startup_delay
,
2798 evpn_mh_startup_delay_cmd
,
2799 "[no] evpn mh startup-delay(0-3600)$duration",
2804 "duration in seconds\n")
2807 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2811 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2812 "[no$no] evpn mh redirect-off",
2816 "ES bond redirect for fast-failover off\n")
2820 redirect_off
= no
? false : true;
2822 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2825 DEFUN (default_vrf_vni_mapping
,
2826 default_vrf_vni_mapping_cmd
,
2827 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2828 "VNI corresponding to the DEFAULT VRF\n"
2830 "Prefix routes only \n")
2832 char xpath
[XPATH_MAXLEN
];
2833 struct zebra_vrf
*zvrf
= NULL
;
2836 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2843 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2845 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2847 snprintf(xpath
, sizeof(xpath
),
2848 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2850 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2853 snprintf(xpath
, sizeof(xpath
),
2854 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2856 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2859 return nb_cli_apply_changes(vty
, NULL
);
2862 DEFUN (no_default_vrf_vni_mapping
,
2863 no_default_vrf_vni_mapping_cmd
,
2864 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2866 "VNI corresponding to DEFAULT VRF\n"
2868 "Prefix routes only \n")
2870 char xpath
[XPATH_MAXLEN
];
2872 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2873 struct zebra_vrf
*zvrf
= NULL
;
2875 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2882 if (zvrf
->l3vni
!= vni
) {
2883 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2888 snprintf(xpath
, sizeof(xpath
),
2889 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2891 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2894 snprintf(xpath
, sizeof(xpath
),
2895 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2897 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2900 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2902 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2904 return nb_cli_apply_changes(vty
, NULL
);
2907 DEFUN (vrf_vni_mapping
,
2908 vrf_vni_mapping_cmd
,
2909 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2910 "VNI corresponding to tenant VRF\n"
2912 "prefix-routes-only\n")
2916 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2924 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2925 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2929 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2930 NB_OP_MODIFY
, "true");
2932 return nb_cli_apply_changes(vty
, NULL
);
2935 DEFUN (no_vrf_vni_mapping
,
2936 no_vrf_vni_mapping_cmd
,
2937 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2939 "VNI corresponding to tenant VRF\n"
2941 "prefix-routes-only\n")
2945 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2946 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2954 if (zvrf
->l3vni
!= vni
) {
2955 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2960 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2964 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2965 NB_OP_DESTROY
, "true");
2967 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2969 return nb_cli_apply_changes(vty
, NULL
);
2973 DEFUN (show_vrf_vni
,
2975 "show vrf vni [json]",
2982 struct zebra_vrf
*zvrf
;
2983 json_object
*json
= NULL
;
2984 json_object
*json_vrfs
= NULL
;
2985 bool uj
= use_json(argc
, argv
);
2988 json
= json_object_new_object();
2989 json_vrfs
= json_object_new_array();
2993 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2994 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2996 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3001 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3005 json_object_object_add(json
, "vrfs", json_vrfs
);
3006 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3007 json
, JSON_C_TO_STRING_PRETTY
));
3008 json_object_free(json
);
3014 DEFUN (show_evpn_global
,
3015 show_evpn_global_cmd
,
3021 bool uj
= use_json(argc
, argv
);
3023 zebra_vxlan_print_evpn(vty
, uj
);
3027 DEFPY(show_evpn_l2_nh
,
3028 show_evpn_l2_nh_cmd
,
3029 "show evpn l2-nh [json$json]",
3037 zebra_evpn_l2_nh_show(vty
, uj
);
3044 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3047 "Ethernet Segment\n"
3049 "Detailed information\n"
3056 if (!str_to_esi(esi_str
, &esi
)) {
3057 vty_out(vty
, "%% Malformed ESI\n");
3060 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3063 zebra_evpn_es_show_detail(vty
, uj
);
3065 zebra_evpn_es_show(vty
, uj
);
3071 DEFPY(show_evpn_es_evi
,
3072 show_evpn_es_evi_cmd
,
3073 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3076 "Ethernet Segment per EVI\n"
3077 "VxLAN Network Identifier\n"
3079 "Detailed information\n"
3086 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3088 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3093 DEFPY(show_evpn_access_vlan
,
3094 show_evpn_access_vlan_cmd
,
3095 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3100 "Detailed information\n"
3106 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3109 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3111 zebra_evpn_acc_vl_show(vty
, uj
);
3117 DEFUN (show_evpn_vni
,
3119 "show evpn vni [json]",
3122 "VxLAN Network Identifier\n"
3125 struct zebra_vrf
*zvrf
;
3126 bool uj
= use_json(argc
, argv
);
3128 zvrf
= zebra_vrf_get_evpn();
3129 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3133 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3134 "show evpn vni detail [json]",
3137 "VxLAN Network Identifier\n"
3138 "Detailed Information On Each VNI\n"
3141 struct zebra_vrf
*zvrf
;
3142 bool uj
= use_json(argc
, argv
);
3144 zvrf
= zebra_vrf_get_evpn();
3145 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3149 DEFUN (show_evpn_vni_vni
,
3150 show_evpn_vni_vni_cmd
,
3151 "show evpn vni " CMD_VNI_RANGE
"[json]",
3154 "VxLAN Network Identifier\n"
3158 struct zebra_vrf
*zvrf
;
3160 bool uj
= use_json(argc
, argv
);
3162 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3163 zvrf
= zebra_vrf_get_evpn();
3164 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3168 DEFUN (show_evpn_rmac_vni_mac
,
3169 show_evpn_rmac_vni_mac_cmd
,
3170 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3177 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3182 bool uj
= use_json(argc
, argv
);
3184 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3185 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3186 vty_out(vty
, "%% Malformed MAC address\n");
3189 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3193 DEFUN (show_evpn_rmac_vni
,
3194 show_evpn_rmac_vni_cmd
,
3195 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3204 bool uj
= use_json(argc
, argv
);
3206 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3207 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3212 DEFUN (show_evpn_rmac_vni_all
,
3213 show_evpn_rmac_vni_all_cmd
,
3214 "show evpn rmac vni all [json]",
3222 bool uj
= use_json(argc
, argv
);
3224 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3229 DEFUN (show_evpn_nh_vni_ip
,
3230 show_evpn_nh_vni_ip_cmd
,
3231 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3238 "Host address (ipv4 or ipv6)\n"
3243 bool uj
= use_json(argc
, argv
);
3245 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3246 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3248 vty_out(vty
, "%% Malformed Neighbor address\n");
3251 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3256 DEFUN (show_evpn_nh_vni
,
3257 show_evpn_nh_vni_cmd
,
3258 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3267 bool uj
= use_json(argc
, argv
);
3269 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3270 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3275 DEFUN (show_evpn_nh_vni_all
,
3276 show_evpn_nh_vni_all_cmd
,
3277 "show evpn next-hops vni all [json]",
3285 bool uj
= use_json(argc
, argv
);
3287 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3292 DEFUN (show_evpn_mac_vni
,
3293 show_evpn_mac_vni_cmd
,
3294 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3298 "VxLAN Network Identifier\n"
3302 struct zebra_vrf
*zvrf
;
3304 bool uj
= use_json(argc
, argv
);
3306 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3307 zvrf
= zebra_vrf_get_evpn();
3308 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3312 DEFUN (show_evpn_mac_vni_all
,
3313 show_evpn_mac_vni_all_cmd
,
3314 "show evpn mac vni all [json]",
3318 "VxLAN Network Identifier\n"
3322 struct zebra_vrf
*zvrf
;
3323 bool uj
= use_json(argc
, argv
);
3325 zvrf
= zebra_vrf_get_evpn();
3326 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3330 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3331 "show evpn mac vni all detail [json]",
3335 "VxLAN Network Identifier\n"
3337 "Detailed Information On Each VNI MAC\n"
3340 struct zebra_vrf
*zvrf
;
3341 bool uj
= use_json(argc
, argv
);
3343 zvrf
= zebra_vrf_get_evpn();
3344 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3348 DEFUN (show_evpn_mac_vni_all_vtep
,
3349 show_evpn_mac_vni_all_vtep_cmd
,
3350 "show evpn mac vni all vtep A.B.C.D [json]",
3354 "VxLAN Network Identifier\n"
3357 "Remote VTEP IP address\n"
3360 struct zebra_vrf
*zvrf
;
3361 struct in_addr vtep_ip
;
3362 bool uj
= use_json(argc
, argv
);
3364 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3366 vty_out(vty
, "%% Malformed VTEP IP address\n");
3369 zvrf
= zebra_vrf_get_evpn();
3370 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3376 DEFUN (show_evpn_mac_vni_mac
,
3377 show_evpn_mac_vni_mac_cmd
,
3378 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3382 "VxLAN Network Identifier\n"
3385 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3389 struct zebra_vrf
*zvrf
;
3392 bool uj
= use_json(argc
, argv
);
3394 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3395 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3396 vty_out(vty
, "%% Malformed MAC address");
3399 zvrf
= zebra_vrf_get_evpn();
3400 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3404 DEFUN (show_evpn_mac_vni_vtep
,
3405 show_evpn_mac_vni_vtep_cmd
,
3406 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3410 "VxLAN Network Identifier\n"
3413 "Remote VTEP IP address\n"
3416 struct zebra_vrf
*zvrf
;
3418 struct in_addr vtep_ip
;
3419 bool uj
= use_json(argc
, argv
);
3421 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3422 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3424 vty_out(vty
, "%% Malformed VTEP IP address\n");
3428 zvrf
= zebra_vrf_get_evpn();
3429 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3433 DEFPY (show_evpn_mac_vni_all_dad
,
3434 show_evpn_mac_vni_all_dad_cmd
,
3435 "show evpn mac vni all duplicate [json]",
3439 "VxLAN Network Identifier\n"
3441 "Duplicate address list\n"
3444 struct zebra_vrf
*zvrf
;
3445 bool uj
= use_json(argc
, argv
);
3447 zvrf
= zebra_vrf_get_evpn();
3448 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3453 DEFPY (show_evpn_mac_vni_dad
,
3454 show_evpn_mac_vni_dad_cmd
,
3455 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3459 "VxLAN Network Identifier\n"
3461 "Duplicate address list\n"
3464 struct zebra_vrf
*zvrf
;
3465 bool uj
= use_json(argc
, argv
);
3467 zvrf
= zebra_vrf_get_evpn();
3469 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3474 DEFPY (show_evpn_neigh_vni_dad
,
3475 show_evpn_neigh_vni_dad_cmd
,
3476 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3479 "ARP and ND cache\n"
3480 "VxLAN Network Identifier\n"
3482 "Duplicate address list\n"
3485 struct zebra_vrf
*zvrf
;
3486 bool uj
= use_json(argc
, argv
);
3488 zvrf
= zebra_vrf_get_evpn();
3489 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3493 DEFPY (show_evpn_neigh_vni_all_dad
,
3494 show_evpn_neigh_vni_all_dad_cmd
,
3495 "show evpn arp-cache vni all duplicate [json]",
3498 "ARP and ND cache\n"
3499 "VxLAN Network Identifier\n"
3501 "Duplicate address list\n"
3504 struct zebra_vrf
*zvrf
;
3505 bool uj
= use_json(argc
, argv
);
3507 zvrf
= zebra_vrf_get_evpn();
3508 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3513 DEFUN (show_evpn_neigh_vni
,
3514 show_evpn_neigh_vni_cmd
,
3515 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3523 struct zebra_vrf
*zvrf
;
3525 bool uj
= use_json(argc
, argv
);
3527 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3528 zvrf
= zebra_vrf_get_evpn();
3529 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3533 DEFUN (show_evpn_neigh_vni_all
,
3534 show_evpn_neigh_vni_all_cmd
,
3535 "show evpn arp-cache vni all [json]",
3538 "ARP and ND cache\n"
3539 "VxLAN Network Identifier\n"
3543 struct zebra_vrf
*zvrf
;
3544 bool uj
= use_json(argc
, argv
);
3546 zvrf
= zebra_vrf_get_evpn();
3547 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3551 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3552 "show evpn arp-cache vni all detail [json]",
3555 "ARP and ND cache\n"
3556 "VxLAN Network Identifier\n"
3558 "Neighbor details for all vnis in detail\n" JSON_STR
)
3560 struct zebra_vrf
*zvrf
;
3561 bool uj
= use_json(argc
, argv
);
3563 zvrf
= zebra_vrf_get_evpn();
3564 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3568 DEFUN (show_evpn_neigh_vni_neigh
,
3569 show_evpn_neigh_vni_neigh_cmd
,
3570 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3573 "ARP and ND cache\n"
3574 "VxLAN Network Identifier\n"
3577 "Neighbor address (IPv4 or IPv6 address)\n"
3580 struct zebra_vrf
*zvrf
;
3583 bool uj
= use_json(argc
, argv
);
3585 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3586 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3588 vty_out(vty
, "%% Malformed Neighbor address\n");
3591 zvrf
= zebra_vrf_get_evpn();
3592 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3596 DEFUN (show_evpn_neigh_vni_vtep
,
3597 show_evpn_neigh_vni_vtep_cmd
,
3598 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3601 "ARP and ND cache\n"
3602 "VxLAN Network Identifier\n"
3605 "Remote VTEP IP address\n"
3608 struct zebra_vrf
*zvrf
;
3610 struct in_addr vtep_ip
;
3611 bool uj
= use_json(argc
, argv
);
3613 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3614 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3616 vty_out(vty
, "%% Malformed VTEP IP address\n");
3620 zvrf
= zebra_vrf_get_evpn();
3621 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3625 /* policy routing contexts */
3626 DEFUN (show_pbr_ipset
,
3628 "show pbr ipset [WORD]",
3630 "Policy-Based Routing\n"
3631 "IPset Context information\n"
3632 "IPset Name information\n")
3636 found
= argv_find(argv
, argc
, "WORD", &idx
);
3638 zebra_pbr_show_ipset_list(vty
, NULL
);
3640 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3644 /* policy routing contexts */
3645 DEFUN (show_pbr_iptable
,
3646 show_pbr_iptable_cmd
,
3647 "show pbr iptable [WORD]",
3649 "Policy-Based Routing\n"
3650 "IPtable Context information\n"
3651 "IPtable Name information\n")
3656 found
= argv_find(argv
, argc
, "WORD", &idx
);
3658 zebra_pbr_show_iptable(vty
, NULL
);
3660 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3664 DEFPY (clear_evpn_dup_addr
,
3665 clear_evpn_dup_addr_cmd
,
3666 "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>]>",
3669 "Duplicate address \n"
3670 "VxLAN Network Identifier\n"
3674 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3679 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3680 int ret
= CMD_SUCCESS
;
3682 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3683 *yang_dup_mac
= NULL
;
3688 yang_dup
= yang_data_new(
3689 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3692 yang_dup
= yang_data_new_uint32(
3693 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3695 if (!is_zero_mac(&mac
->eth_addr
)) {
3696 yang_dup_mac
= yang_data_new_mac(
3697 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3700 listnode_add(input
, yang_dup_mac
);
3702 if (sockunion_family(ip
) == AF_INET
) {
3703 host_ip
.ipa_type
= IPADDR_V4
;
3704 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3706 host_ip
.ipa_type
= IPADDR_V6
;
3707 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3708 sizeof(struct in6_addr
));
3711 yang_dup_ip
= yang_data_new_ip(
3712 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3716 listnode_add(input
, yang_dup_ip
);
3721 listnode_add(input
, yang_dup
);
3722 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3726 list_delete(&input
);
3731 /* Static ip route configuration write function. */
3732 static int zebra_ip_config(struct vty
*vty
)
3736 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3741 DEFUN (ip_zebra_import_table_distance
,
3742 ip_zebra_import_table_distance_cmd
,
3743 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3745 "import routes from non-main kernel table\n"
3746 "kernel routing table id\n"
3747 "Distance for imported routes\n"
3748 "Default distance value\n"
3749 "route-map for filtering\n"
3752 uint32_t table_id
= 0;
3754 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3755 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3757 strmatch(argv
[argc
- 2]->text
, "route-map")
3758 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3762 if (argc
== 7 || (argc
== 5 && !rmap
))
3763 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3765 if (!is_zebra_valid_kernel_table(table_id
)) {
3767 "Invalid routing table ID, %d. Must be in range 1-252\n",
3770 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3774 if (is_zebra_main_routing_table(table_id
)) {
3776 "Invalid routing table ID, %d. Must be non-default table\n",
3779 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3783 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3786 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3791 DEFUN_HIDDEN (zebra_packet_process
,
3792 zebra_packet_process_cmd
,
3793 "zebra zapi-packets (1-10000)",
3796 "Number of packets to process before relinquishing thread\n")
3798 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3800 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3801 memory_order_relaxed
);
3806 DEFUN_HIDDEN (no_zebra_packet_process
,
3807 no_zebra_packet_process_cmd
,
3808 "no zebra zapi-packets [(1-10000)]",
3812 "Number of packets to process before relinquishing thread\n")
3814 atomic_store_explicit(&zrouter
.packets_to_process
,
3815 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3816 memory_order_relaxed
);
3821 DEFUN_HIDDEN (zebra_workqueue_timer
,
3822 zebra_workqueue_timer_cmd
,
3823 "zebra work-queue (0-10000)",
3826 "Time in milliseconds\n")
3828 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3829 zrouter
.ribq
->spec
.hold
= timer
;
3834 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3835 no_zebra_workqueue_timer_cmd
,
3836 "no zebra work-queue [(0-10000)]",
3840 "Time in milliseconds\n")
3842 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3847 DEFUN (no_ip_zebra_import_table
,
3848 no_ip_zebra_import_table_cmd
,
3849 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3852 "import routes from non-main kernel table\n"
3853 "kernel routing table id\n"
3854 "Distance for imported routes\n"
3855 "Default distance value\n"
3856 "route-map for filtering\n"
3859 uint32_t table_id
= 0;
3860 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3862 if (!is_zebra_valid_kernel_table(table_id
)) {
3864 "Invalid routing table ID. Must be in range 1-252\n");
3868 if (is_zebra_main_routing_table(table_id
)) {
3870 "Invalid routing table ID, %d. Must be non-default table\n",
3875 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3878 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3881 static int config_write_protocol(struct vty
*vty
)
3884 vty_out(vty
, "allow-external-route-update\n");
3886 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3887 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3889 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3890 vty_out(vty
, "zebra zapi-packets %u\n",
3891 zrouter
.packets_to_process
);
3893 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3895 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3896 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3897 ipv4_multicast_mode
== MCAST_URIB_ONLY
3899 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3901 : ipv4_multicast_mode
3902 == MCAST_MIX_MRIB_FIRST
3904 : ipv4_multicast_mode
3905 == MCAST_MIX_DISTANCE
3909 /* Include dataplane info */
3910 dplane_config_write_helper(vty
);
3912 zebra_evpn_mh_config_write(vty
);
3914 /* Include nexthop-group config */
3915 if (!zebra_nhg_kernel_nexthops_enabled())
3916 vty_out(vty
, "no zebra nexthop kernel enable\n");
3918 if (zebra_nhg_proto_nexthops_only())
3919 vty_out(vty
, "zebra nexthop proto only\n");
3921 if (!zebra_nhg_recursive_use_backups())
3922 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3924 if (rnh_get_hide_backups())
3925 vty_out(vty
, "ip nht hide-backup-events\n");
3928 /* Include netlink info */
3929 netlink_config_write_helper(vty
);
3930 #endif /* HAVE_NETLINK */
3943 if (zrouter
.asic_offloaded
)
3944 vty_out(vty
, "Asic Offload is being used\n");
3947 " Route Route Neighbor LSP LSP\n");
3949 "VRF Installs Removals Updates Installs Removals\n");
3951 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3952 struct zebra_vrf
*zvrf
= vrf
->info
;
3954 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
3955 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
3956 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
3957 zvrf
->lsp_removals
);
3963 DEFUN (ip_forwarding
,
3967 "Turn on IP forwarding\n")
3973 ret
= ipforward_on();
3976 vty_out(vty
, "Can't turn on IP forwarding\n");
3977 return CMD_WARNING_CONFIG_FAILED
;
3983 DEFUN (no_ip_forwarding
,
3984 no_ip_forwarding_cmd
,
3988 "Turn off IP forwarding\n")
3994 ret
= ipforward_off();
3997 vty_out(vty
, "Can't turn off IP forwarding\n");
3998 return CMD_WARNING_CONFIG_FAILED
;
4004 /* Only display ip forwarding is enabled or not. */
4005 DEFUN (show_ip_forwarding
,
4006 show_ip_forwarding_cmd
,
4007 "show ip forwarding",
4010 "IP forwarding status\n")
4017 vty_out(vty
, "IP forwarding is off\n");
4019 vty_out(vty
, "IP forwarding is on\n");
4023 /* Only display ipv6 forwarding is enabled or not. */
4024 DEFUN (show_ipv6_forwarding
,
4025 show_ipv6_forwarding_cmd
,
4026 "show ipv6 forwarding",
4028 "IPv6 information\n"
4029 "Forwarding status\n")
4033 ret
= ipforward_ipv6();
4037 vty_out(vty
, "ipv6 forwarding is unknown\n");
4040 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4043 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4046 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4052 DEFUN (ipv6_forwarding
,
4053 ipv6_forwarding_cmd
,
4056 "Turn on IPv6 forwarding\n")
4060 ret
= ipforward_ipv6();
4062 ret
= ipforward_ipv6_on();
4065 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4066 return CMD_WARNING_CONFIG_FAILED
;
4072 DEFUN (no_ipv6_forwarding
,
4073 no_ipv6_forwarding_cmd
,
4074 "no ipv6 forwarding",
4077 "Turn off IPv6 forwarding\n")
4081 ret
= ipforward_ipv6();
4083 ret
= ipforward_ipv6_off();
4086 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4087 return CMD_WARNING_CONFIG_FAILED
;
4093 /* Display dataplane info */
4094 DEFUN (show_dataplane
,
4096 "show zebra dplane [detailed]",
4099 "Zebra dataplane information\n"
4100 "Detailed output\n")
4103 bool detailed
= false;
4105 if (argv_find(argv
, argc
, "detailed", &idx
))
4108 return dplane_show_helper(vty
, detailed
);
4111 /* Display dataplane providers info */
4112 DEFUN (show_dataplane_providers
,
4113 show_dataplane_providers_cmd
,
4114 "show zebra dplane providers [detailed]",
4117 "Zebra dataplane information\n"
4118 "Zebra dataplane provider information\n"
4119 "Detailed output\n")
4122 bool detailed
= false;
4124 if (argv_find(argv
, argc
, "detailed", &idx
))
4127 return dplane_show_provs_helper(vty
, detailed
);
4130 /* Configure dataplane incoming queue limit */
4131 DEFUN (zebra_dplane_queue_limit
,
4132 zebra_dplane_queue_limit_cmd
,
4133 "zebra dplane limit (0-10000)",
4136 "Limit incoming queued updates\n"
4137 "Number of queued updates\n")
4141 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4143 dplane_set_in_queue_limit(limit
, true);
4148 /* Reset dataplane queue limit to default value */
4149 DEFUN (no_zebra_dplane_queue_limit
,
4150 no_zebra_dplane_queue_limit_cmd
,
4151 "no zebra dplane limit [(0-10000)]",
4155 "Limit incoming queued updates\n"
4156 "Number of queued updates\n")
4158 dplane_set_in_queue_limit(0, false);
4163 DEFUN (zebra_show_routing_tables_summary
,
4164 zebra_show_routing_tables_summary_cmd
,
4165 "show zebra router table summary",
4168 "The Zebra Router Information\n"
4169 "Table Information about this Zebra Router\n"
4170 "Summary Information\n")
4172 zebra_router_show_table_summary(vty
);
4177 /* Table configuration write function. */
4178 static int config_write_table(struct vty
*vty
)
4183 /* IPForwarding configuration write function. */
4184 static int config_write_forwarding(struct vty
*vty
)
4187 vty_out(vty
, "no ip forwarding\n");
4188 if (!ipforward_ipv6())
4189 vty_out(vty
, "no ipv6 forwarding\n");
4190 vty_out(vty
, "!\n");
4194 DEFUN_HIDDEN (show_frr
,
4200 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4201 vty_out(vty
, ".............................7777:..............................................\n");
4202 vty_out(vty
, ".............................777777,............................................\n");
4203 vty_out(vty
, "... .........................77777777,..........................................\n");
4204 vty_out(vty
, "............................=7777777777:........................................\n");
4205 vty_out(vty
, "........................:7777777777777777,......................................\n");
4206 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4207 vty_out(vty
, "...................I7777777777+.................................................\n");
4208 vty_out(vty
, "................,777777777?............ .......................................\n");
4209 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4210 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4211 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4212 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4213 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4214 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4215 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4216 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4217 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4218 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4219 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4220 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4221 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4222 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4223 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4224 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4225 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4226 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4227 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4228 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4229 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4230 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4231 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4232 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4233 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4234 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4235 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4236 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4237 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4238 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4239 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4240 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4241 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4242 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4243 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4244 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4245 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4246 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4247 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4248 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4249 vty_out(vty
, "................................~77777777...............=777777.................\n");
4250 vty_out(vty
, ".....................................:=?I................~777777................\n");
4251 vty_out(vty
, "..........................................................:777777,..............\n");
4252 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4258 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4259 zebra_kernel_netlink_batch_tx_buf_cmd
,
4260 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4262 "Zebra kernel interface\n"
4263 "Set Netlink parameters\n"
4264 "Set batch buffer size and send threshold\n"
4265 "Size of the buffer\n"
4268 uint32_t bufsize
= 0, threshold
= 0;
4270 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4271 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4273 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4278 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4279 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4280 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4282 "Zebra kernel interface\n"
4283 "Set Netlink parameters\n"
4284 "Set batch buffer size and send threshold\n"
4285 "Size of the buffer\n"
4288 netlink_set_batch_buffer_size(0, 0, false);
4293 #endif /* HAVE_NETLINK */
4295 DEFUN(ip_table_range
, ip_table_range_cmd
,
4296 "[no] ip table range (1-4294967295) (1-4294967295)",
4298 "table configuration\n"
4299 "Configure table range\n"
4300 "Start Routing Table\n"
4301 "End Routing Table\n")
4303 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
4308 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4310 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4314 if (strmatch(argv
[0]->text
, "no"))
4315 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4317 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4320 /* IP node for static routes. */
4321 static int zebra_ip_config(struct vty
*vty
);
4322 static struct cmd_node ip_node
= {
4323 .name
= "static ip",
4326 .config_write
= zebra_ip_config
,
4328 static int config_write_protocol(struct vty
*vty
);
4329 static struct cmd_node protocol_node
= {
4331 .node
= PROTOCOL_NODE
,
4333 .config_write
= config_write_protocol
,
4335 /* table node for routing tables. */
4336 static int config_write_table(struct vty
*vty
);
4337 static struct cmd_node table_node
= {
4341 .config_write
= config_write_table
,
4343 static int config_write_forwarding(struct vty
*vty
);
4344 static struct cmd_node forwarding_node
= {
4345 .name
= "forwarding",
4346 .node
= FORWARDING_NODE
,
4348 .config_write
= config_write_forwarding
,
4352 void zebra_vty_init(void)
4354 /* Install configuration write function. */
4355 install_node(&table_node
);
4356 install_node(&forwarding_node
);
4358 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4359 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4360 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4361 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4363 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4364 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4365 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4368 zebra_route_map_init();
4370 install_node(&ip_node
);
4371 install_node(&protocol_node
);
4373 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4374 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4376 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4377 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4379 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4380 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4381 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4382 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4383 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4384 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4385 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4386 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4387 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4389 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4390 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4392 install_element(VIEW_NODE
, &show_vrf_cmd
);
4393 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4394 install_element(VIEW_NODE
, &show_route_cmd
);
4395 install_element(VIEW_NODE
, &show_ro_cmd
);
4396 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4397 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4398 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4400 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4401 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4403 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4404 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4405 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4406 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4407 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4408 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4409 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4410 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4411 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4413 install_element(VIEW_NODE
, &show_ipv6_mroute_cmd
);
4415 /* Commands for VRF */
4416 install_element(VIEW_NODE
, &show_ipv6_mroute_vrf_all_cmd
);
4418 install_element(VIEW_NODE
, &show_frr_cmd
);
4419 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4420 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4421 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4422 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4423 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4424 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4425 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4426 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4427 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4428 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4429 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4430 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4431 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4432 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4433 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4434 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4435 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4436 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4437 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4438 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4439 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4440 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4441 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4442 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4443 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4444 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4445 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4446 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4447 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4448 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4450 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4451 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4452 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4454 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4455 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4456 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4457 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4458 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4459 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4460 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4461 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4463 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4464 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4465 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4466 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4468 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4469 install_element(VRF_NODE
, &ip_table_range_cmd
);
4472 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4473 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4474 #endif /* HAVE_NETLINK */
4476 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);