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
24 #include "zebra_memory.h"
35 #include "srcdest_table.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"
44 #include "zebra/zebra_static.h"
46 #include "zebra/zebra_vxlan.h"
47 #ifndef VTYSH_EXTRACT_PL
48 #include "zebra/zebra_vty_clippy.c"
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
55 extern int allow_delete
;
57 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
58 safi_t safi
, bool use_fib
, u_char use_json
,
60 const struct prefix
*longer_prefix_p
,
61 bool supernets_only
, int type
,
62 u_short ospf_instance_id
);
63 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
65 static void vty_show_ip_route_summary(struct vty
*vty
,
66 struct route_table
*table
);
67 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
68 struct route_table
*table
);
71 * special macro to allow us to get the correct zebra_vrf
73 #define ZEBRA_DECLVAR_CONTEXT(A, B) \
74 struct vrf *A = VTY_GET_CONTEXT(vrf); \
75 struct zebra_vrf *B = (vrf) ? vrf->info : NULL;
77 /* VNI range as per RFC 7432 */
78 #define CMD_VNI_RANGE "(1-16777215)"
80 struct static_hold_route
{
96 static struct list
*static_list
;
98 static int static_list_compare_helper(const char *s1
, const char *s2
)
110 return strcmp(s1
, s2
);
113 static void static_list_delete(struct static_hold_route
*shr
)
116 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
118 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
120 XFREE(MTYPE_STATIC_ROUTE
, shr
->dest_str
);
122 XFREE(MTYPE_STATIC_ROUTE
, shr
->mask_str
);
124 XFREE(MTYPE_STATIC_ROUTE
, shr
->src_str
);
126 XFREE(MTYPE_STATIC_ROUTE
, shr
->gate_str
);
128 XFREE(MTYPE_STATIC_ROUTE
, shr
->ifname
);
130 XFREE(MTYPE_STATIC_ROUTE
, shr
->flag_str
);
132 XFREE(MTYPE_STATIC_ROUTE
, shr
->tag_str
);
133 if (shr
->distance_str
)
134 XFREE(MTYPE_STATIC_ROUTE
, shr
->distance_str
);
136 XFREE(MTYPE_STATIC_ROUTE
, shr
->label_str
);
138 XFREE(MTYPE_STATIC_ROUTE
, shr
);
141 static int static_list_compare(void *arg1
, void *arg2
)
143 struct static_hold_route
*shr1
= arg1
;
144 struct static_hold_route
*shr2
= arg2
;
147 ret
= strcmp(shr1
->vrf_name
, shr2
->vrf_name
);
151 ret
= strcmp(shr2
->nhvrf_name
, shr2
->nhvrf_name
);
155 ret
= shr1
->afi
- shr2
->afi
;
159 ret
= shr1
->safi
- shr2
->afi
;
163 ret
= static_list_compare_helper(shr1
->dest_str
, shr2
->dest_str
);
167 ret
= static_list_compare_helper(shr1
->mask_str
, shr2
->mask_str
);
171 ret
= static_list_compare_helper(shr1
->src_str
, shr2
->src_str
);
175 ret
= static_list_compare_helper(shr1
->gate_str
, shr2
->gate_str
);
179 ret
= static_list_compare_helper(shr1
->ifname
, shr2
->ifname
);
183 ret
= static_list_compare_helper(shr1
->flag_str
, shr2
->flag_str
);
187 ret
= static_list_compare_helper(shr1
->tag_str
, shr2
->tag_str
);
191 ret
= static_list_compare_helper(shr1
->distance_str
,
196 return static_list_compare_helper(shr1
->label_str
, shr2
->label_str
);
200 /* General function for static route. */
201 static int zebra_static_route_holdem(struct zebra_vrf
*zvrf
,
202 struct zebra_vrf
*nh_zvrf
,
203 afi_t afi
, safi_t safi
,
204 const char *negate
, const char *dest_str
,
205 const char *mask_str
, const char *src_str
,
206 const char *gate_str
, const char *ifname
,
207 const char *flag_str
, const char *tag_str
,
208 const char *distance_str
,
209 const char *label_str
)
211 struct static_hold_route
*shr
, *lookup
;
212 struct listnode
*node
;
214 shr
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(*shr
));
215 shr
->vrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, zvrf
->vrf
->name
);
216 shr
->nhvrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, nh_zvrf
->vrf
->name
);
220 shr
->dest_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, dest_str
);
222 shr
->mask_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, mask_str
);
224 shr
->src_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, src_str
);
226 shr
->gate_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, gate_str
);
228 shr
->ifname
= XSTRDUP(MTYPE_STATIC_ROUTE
, ifname
);
230 shr
->flag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, flag_str
);
232 shr
->tag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, tag_str
);
234 shr
->distance_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, distance_str
);
236 shr
->label_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, label_str
);
238 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, lookup
)) {
239 if (static_list_compare(shr
, lookup
) == 0)
245 listnode_delete(static_list
, lookup
);
246 static_list_delete(shr
);
247 static_list_delete(lookup
);
253 * If a person enters the same line again
254 * we need to silently accept it
259 listnode_add_sort(static_list
, shr
);
264 static int zebra_static_route_leak(
265 struct vty
*vty
, struct zebra_vrf
*zvrf
, struct zebra_vrf
*nh_zvrf
,
266 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
267 const char *mask_str
, const char *src_str
, const char *gate_str
,
268 const char *ifname
, const char *flag_str
, const char *tag_str
,
269 const char *distance_str
, const char *label_str
)
273 struct prefix p
, src
;
274 struct prefix_ipv6
*src_p
= NULL
;
276 union g_addr
*gatep
= NULL
;
278 enum static_blackhole_type bh_type
= 0;
281 struct static_nh_label snh_label
;
283 ret
= str2prefix(dest_str
, &p
);
286 vty_out(vty
, "%% Malformed address\n");
288 zlog_warn("%s: Malformed address: %s",
289 __PRETTY_FUNCTION__
, dest_str
);
290 return CMD_WARNING_CONFIG_FAILED
;
293 if (zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
294 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
295 vrf_set_user_cfged(zvrf
->vrf
);
296 return zebra_static_route_holdem(
297 zvrf
, nh_zvrf
, afi
, safi
, negate
, dest_str
, mask_str
,
298 src_str
, gate_str
, ifname
, flag_str
, tag_str
,
299 distance_str
, label_str
);
303 /* Cisco like mask notation. */
305 ret
= inet_aton(mask_str
, &mask
);
308 vty_out(vty
, "%% Malformed address\n");
310 zlog_warn("%s: Malformed address: %s",
313 return CMD_WARNING_CONFIG_FAILED
;
315 p
.prefixlen
= ip_masklen(mask
);
319 /* srcdest routing */
321 ret
= str2prefix(src_str
, &src
);
322 if (ret
<= 0 || src
.family
!= AF_INET6
) {
325 "%% Malformed source address\n");
328 "%s: Malformed Source address: %s",
329 __PRETTY_FUNCTION__
, src_str
);
330 return CMD_WARNING_CONFIG_FAILED
;
332 src_p
= (struct prefix_ipv6
*)&src
;
339 /* Apply mask for given prefix. */
342 /* Administrative distance. */
344 distance
= atoi(distance_str
);
346 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
350 tag
= strtoul(tag_str
, NULL
, 10);
353 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
358 "%% MPLS not turned on in kernel, ignoring command\n");
361 "%s: MPLS not turned on in kernel ignoring static route to %s",
362 __PRETTY_FUNCTION__
, dest_str
);
363 return CMD_WARNING_CONFIG_FAILED
;
365 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
371 vty_out(vty
, "%% Malformed label(s)\n");
374 "%s: Malformed labels specified for route %s",
375 __PRETTY_FUNCTION__
, dest_str
);
380 "%% Cannot use reserved label(s) (%d-%d)\n",
381 MPLS_LABEL_RESERVED_MIN
,
382 MPLS_LABEL_RESERVED_MAX
);
385 "%s: Cannot use reserved labels (%d-%d) for %s",
387 MPLS_LABEL_RESERVED_MIN
,
388 MPLS_LABEL_RESERVED_MAX
,
394 "%% Too many labels. Enter %d or fewer\n",
398 "%s: Too many labels, Enter %d or fewer for %s",
400 MPLS_MAX_LABELS
, dest_str
);
403 return CMD_WARNING_CONFIG_FAILED
;
407 /* Null0 static route. */
408 if (ifname
!= NULL
) {
409 if (strncasecmp(ifname
, "Null0", strlen(ifname
)) == 0
410 || strncasecmp(ifname
, "reject", strlen(ifname
)) == 0
411 || strncasecmp(ifname
, "blackhole", strlen(ifname
)) == 0) {
414 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
417 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
418 __PRETTY_FUNCTION__
, dest_str
);
419 return CMD_WARNING_CONFIG_FAILED
;
425 switch (flag_str
[0]) {
427 bh_type
= STATIC_BLACKHOLE_REJECT
;
430 bh_type
= STATIC_BLACKHOLE_DROP
;
433 bh_type
= STATIC_BLACKHOLE_NULL
;
437 vty_out(vty
, "%% Malformed flag %s \n",
440 zlog_warn("%s: Malformed flag %s for %s",
441 __PRETTY_FUNCTION__
, flag_str
,
443 return CMD_WARNING_CONFIG_FAILED
;
448 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
451 "%% Malformed nexthop address %s\n",
455 "%s: Malformed nexthop address %s for %s",
456 __PRETTY_FUNCTION__
, gate_str
,
458 return CMD_WARNING_CONFIG_FAILED
;
463 if (gate_str
== NULL
&& ifname
== NULL
)
464 type
= STATIC_BLACKHOLE
;
465 else if (gate_str
&& ifname
) {
467 type
= STATIC_IPV4_GATEWAY_IFNAME
;
469 type
= STATIC_IPV6_GATEWAY_IFNAME
;
471 type
= STATIC_IFNAME
;
474 type
= STATIC_IPV4_GATEWAY
;
476 type
= STATIC_IPV6_GATEWAY
;
480 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
481 bh_type
, tag
, distance
, zvrf
, nh_zvrf
,
483 /* Mark as having FRR configuration */
484 vrf_set_user_cfged(zvrf
->vrf
);
486 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
487 tag
, distance
, zvrf
, &snh_label
);
488 /* If no other FRR config for this VRF, mark accordingly. */
489 if (!zebra_vrf_has_config(zvrf
))
490 vrf_reset_user_cfged(zvrf
->vrf
);
496 static struct zebra_vrf
*zebra_vty_get_unknown_vrf(struct vty
*vty
,
497 const char *vrf_name
)
499 struct zebra_vrf
*zvrf
;
502 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
507 vrf
= vrf_get(VRF_UNKNOWN
, vrf_name
);
509 vty_out(vty
, "%% Could not create vrf %s\n", vrf_name
);
514 vty_out(vty
, "%% Could not create vrf-info %s\n",
518 /* Mark as having FRR configuration */
519 vrf_set_user_cfged(vrf
);
524 static int zebra_static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
525 const char *negate
, const char *dest_str
,
526 const char *mask_str
, const char *src_str
,
527 const char *gate_str
, const char *ifname
,
528 const char *flag_str
, const char *tag_str
,
529 const char *distance_str
, const char *vrf_name
,
530 const char *label_str
)
532 struct zebra_vrf
*zvrf
;
535 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
537 /* When trying to delete, the VRF must exist. */
538 if (negate
&& !zvrf
) {
539 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
540 return CMD_WARNING_CONFIG_FAILED
;
543 /* When trying to create, create the VRF if it doesn't exist.
544 * Note: The VRF isn't active until we hear about it from the kernel.
547 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf_name
);
549 return CMD_WARNING_CONFIG_FAILED
;
551 return zebra_static_route_leak(
552 vty
, zvrf
, zvrf
, afi
, safi
, negate
, dest_str
, mask_str
, src_str
,
553 gate_str
, ifname
, flag_str
, tag_str
, distance_str
, label_str
);
556 void static_config_install_delayed_routes(struct zebra_vrf
*zvrf
)
558 struct listnode
*node
, *nnode
;
559 struct static_hold_route
*shr
;
560 struct zebra_vrf
*ozvrf
, *nh_zvrf
;
563 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
564 ozvrf
= zebra_vrf_lookup_by_name(shr
->vrf_name
);
565 nh_zvrf
= zebra_vrf_lookup_by_name(shr
->nhvrf_name
);
567 if (ozvrf
!= zvrf
&& nh_zvrf
!= zvrf
)
570 if (ozvrf
->vrf
->vrf_id
== VRF_UNKNOWN
571 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
574 installed
= zebra_static_route_leak(
575 NULL
, ozvrf
, nh_zvrf
, shr
->afi
, shr
->safi
, NULL
,
576 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
577 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
578 shr
->distance_str
, shr
->label_str
);
580 if (installed
!= CMD_SUCCESS
)
582 "%s: Attempt to install %s as a route and it was rejected",
583 __PRETTY_FUNCTION__
, shr
->dest_str
);
584 listnode_delete(static_list
, shr
);
585 static_list_delete(shr
);
588 /* Static unicast routes for multicast RPF lookup. */
589 DEFPY (ip_mroute_dist
,
591 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
594 "Configure static unicast route into MRIB for multicast RPF lookup\n"
595 "IP destination prefix (e.g. 10.0.0.0/8)\n"
597 "Nexthop interface name\n"
600 return zebra_static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
601 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
602 distance_str
, NULL
, NULL
);
605 DEFUN (ip_multicast_mode
,
606 ip_multicast_mode_cmd
,
607 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
609 "Multicast options\n"
610 "RPF lookup behavior\n"
611 "Lookup in unicast RIB only\n"
612 "Lookup in multicast RIB only\n"
613 "Try multicast RIB first, fall back to unicast RIB\n"
614 "Lookup both, use entry with lower distance\n"
615 "Lookup both, use entry with longer prefix\n")
617 char *mode
= argv
[3]->text
;
619 if (strmatch(mode
, "urib-only"))
620 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
621 else if (strmatch(mode
, "mrib-only"))
622 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
623 else if (strmatch(mode
, "mrib-then-urib"))
624 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
625 else if (strmatch(mode
, "lower-distance"))
626 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
627 else if (strmatch(mode
, "longer-prefix"))
628 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
630 vty_out(vty
, "Invalid mode specified\n");
631 return CMD_WARNING_CONFIG_FAILED
;
637 DEFUN (no_ip_multicast_mode
,
638 no_ip_multicast_mode_cmd
,
639 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
642 "Multicast options\n"
643 "RPF lookup behavior\n"
644 "Lookup in unicast RIB only\n"
645 "Lookup in multicast RIB only\n"
646 "Try multicast RIB first, fall back to unicast RIB\n"
647 "Lookup both, use entry with lower distance\n"
648 "Lookup both, use entry with longer prefix\n")
650 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
657 "show ip rpf [json]",
660 "Display RPF information for multicast source\n"
663 int uj
= use_json(argc
, argv
);
664 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
665 false, uj
, 0, NULL
, false, 0, 0);
668 DEFUN (show_ip_rpf_addr
,
669 show_ip_rpf_addr_cmd
,
670 "show ip rpf A.B.C.D",
673 "Display RPF information for multicast source\n"
674 "IP multicast source address (e.g. 10.0.0.0)\n")
678 struct route_node
*rn
;
679 struct route_entry
*re
;
682 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
684 vty_out(vty
, "%% Malformed address\n");
688 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
691 vty_show_ip_route_detail(vty
, rn
, 1);
693 vty_out(vty
, "%% No match for RPF lookup\n");
698 /* Static route configuration. */
699 DEFPY(ip_route_blackhole
,
700 ip_route_blackhole_cmd
,
702 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
703 <reject|blackhole>$flag \
711 "Establish static routes\n"
712 "IP destination prefix (e.g. 10.0.0.0/8)\n"
713 "IP destination prefix\n"
714 "IP destination prefix mask\n"
715 "Emit an ICMP unreachable when matched\n"
716 "Silently discard pkts when matched\n"
717 "Set tag for this route\n"
719 "Distance value for this route\n"
723 return zebra_static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
724 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
725 distance_str
, vrf
, label
);
728 DEFPY(ip_route_blackhole_vrf
,
729 ip_route_blackhole_vrf_cmd
,
731 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
732 <reject|blackhole>$flag \
739 "Establish static routes\n"
740 "IP destination prefix (e.g. 10.0.0.0/8)\n"
741 "IP destination prefix\n"
742 "IP destination prefix mask\n"
743 "Emit an ICMP unreachable when matched\n"
744 "Silently discard pkts when matched\n"
745 "Set tag for this route\n"
747 "Distance value for this route\n"
750 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
751 struct zebra_vrf
*zvrf
= vrf
->info
;
754 * Coverity is complaining that prefix could
755 * be dereferenced, but we know that prefix will
756 * valid. Add an assert to make it happy
759 return zebra_static_route_leak(vty
, zvrf
, zvrf
, AFI_IP
, SAFI_UNICAST
,
760 no
, prefix
, mask_str
, NULL
, NULL
, NULL
,
761 flag
, tag_str
, distance_str
, label
);
764 DEFPY(ip_route_address_interface
,
765 ip_route_address_interface_cmd
,
767 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
778 "Establish static routes\n"
779 "IP destination prefix (e.g. 10.0.0.0/8)\n"
780 "IP destination prefix\n"
781 "IP destination prefix mask\n"
782 "IP gateway address\n"
783 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
785 "Set tag for this route\n"
787 "Distance value for this route\n"
792 struct zebra_vrf
*zvrf
;
793 struct zebra_vrf
*nh_zvrf
;
795 const char *flag
= NULL
;
796 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
801 zvrf
= zebra_vrf_lookup_by_name(vrf
);
803 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
804 return CMD_WARNING_CONFIG_FAILED
;
808 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
813 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
814 return CMD_WARNING_CONFIG_FAILED
;
817 return zebra_static_route_leak(
818 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
819 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
);
822 DEFPY(ip_route_address_interface_vrf
,
823 ip_route_address_interface_vrf_cmd
,
825 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
835 "Establish static routes\n"
836 "IP destination prefix (e.g. 10.0.0.0/8)\n"
837 "IP destination prefix\n"
838 "IP destination prefix mask\n"
839 "IP gateway address\n"
840 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
842 "Set tag for this route\n"
844 "Distance value for this route\n"
848 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
849 const char *flag
= NULL
;
850 struct zebra_vrf
*zvrf
= vrf
->info
;
851 struct zebra_vrf
*nh_zvrf
;
853 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
859 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
864 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
865 return CMD_WARNING_CONFIG_FAILED
;
868 return zebra_static_route_leak(
869 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
870 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
);
876 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
877 <A.B.C.D$gate|INTERFACE$ifname> \
886 "Establish static routes\n"
887 "IP destination prefix (e.g. 10.0.0.0/8)\n"
888 "IP destination prefix\n"
889 "IP destination prefix mask\n"
890 "IP gateway address\n"
891 "IP gateway interface name\n"
892 "Set tag for this route\n"
894 "Distance value for this route\n"
899 struct zebra_vrf
*zvrf
;
900 struct zebra_vrf
*nh_zvrf
;
901 const char *flag
= NULL
;
903 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
908 zvrf
= zebra_vrf_lookup_by_name(vrf
);
910 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
911 return CMD_WARNING_CONFIG_FAILED
;
915 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
920 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
921 return CMD_WARNING_CONFIG_FAILED
;
925 return zebra_static_route_leak(
926 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
927 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
);
933 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
934 <A.B.C.D$gate|INTERFACE$ifname> \
942 "Establish static routes\n"
943 "IP destination prefix (e.g. 10.0.0.0/8)\n"
944 "IP destination prefix\n"
945 "IP destination prefix mask\n"
946 "IP gateway address\n"
947 "IP gateway interface name\n"
948 "Set tag for this route\n"
950 "Distance value for this route\n"
954 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
955 struct zebra_vrf
*zvrf
= vrf
->info
;
956 struct zebra_vrf
*nh_zvrf
;
958 const char *flag
= NULL
;
959 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
965 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
970 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
971 return CMD_WARNING_CONFIG_FAILED
;
974 return zebra_static_route_leak(
975 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
976 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
);
979 /* New RIB. Detailed information for IPv4 route. */
980 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
983 struct route_entry
*re
;
984 struct nexthop
*nexthop
;
985 char buf
[SRCDEST2STR_BUFFER
];
986 struct zebra_vrf
*zvrf
;
988 RNODE_FOREACH_RE (rn
, re
) {
989 const char *mcast_info
= "";
991 rib_table_info_t
*info
= srcdest_rnode_table_info(rn
);
992 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
993 ? " using Multicast RIB"
994 : " using Unicast RIB";
997 vty_out(vty
, "Routing entry for %s%s\n",
998 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
999 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
1001 vty_out(vty
, "[%d]", re
->instance
);
1003 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
1006 vty_out(vty
, ", tag %u", re
->tag
);
1007 #if defined(SUPPORT_REALMS)
1008 if (re
->tag
> 0 && re
->tag
<= 255)
1009 vty_out(vty
, "(realm)");
1013 vty_out(vty
, ", mtu %u", re
->mtu
);
1014 if (re
->vrf_id
!= VRF_DEFAULT
) {
1015 zvrf
= vrf_info_lookup(re
->vrf_id
);
1016 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
1018 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1019 vty_out(vty
, ", best");
1025 uptime
= time(NULL
);
1026 uptime
-= re
->uptime
;
1027 tm
= gmtime(&uptime
);
1029 vty_out(vty
, " Last update ");
1031 if (uptime
< ONE_DAY_SECOND
)
1032 vty_out(vty
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1034 else if (uptime
< ONE_WEEK_SECOND
)
1035 vty_out(vty
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1038 vty_out(vty
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1039 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1041 vty_out(vty
, " ago\n");
1043 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1046 vty_out(vty
, " %c%s",
1047 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1048 ? CHECK_FLAG(nexthop
->flags
,
1049 NEXTHOP_FLAG_DUPLICATE
)
1053 nexthop
->rparent
? " " : "");
1055 switch (nexthop
->type
) {
1056 case NEXTHOP_TYPE_IPV4
:
1057 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1059 inet_ntoa(nexthop
->gate
.ipv4
));
1060 if (nexthop
->ifindex
)
1061 vty_out(vty
, ", via %s",
1066 case NEXTHOP_TYPE_IPV6
:
1067 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1069 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1071 if (nexthop
->ifindex
)
1072 vty_out(vty
, ", via %s",
1077 case NEXTHOP_TYPE_IFINDEX
:
1078 vty_out(vty
, " directly connected, %s",
1079 ifindex2ifname(nexthop
->ifindex
,
1082 case NEXTHOP_TYPE_BLACKHOLE
:
1083 vty_out(vty
, " unreachable");
1084 switch (nexthop
->bh_type
) {
1085 case BLACKHOLE_REJECT
:
1086 vty_out(vty
, " (ICMP unreachable)");
1088 case BLACKHOLE_ADMINPROHIB
:
1090 " (ICMP admin-prohibited)");
1092 case BLACKHOLE_NULL
:
1093 vty_out(vty
, " (blackhole)");
1095 case BLACKHOLE_UNSPEC
:
1103 if (re
->vrf_id
!= nexthop
->vrf_id
) {
1105 vrf_lookup_by_id(nexthop
->vrf_id
);
1107 vty_out(vty
, "(vrf %s)", vrf
->name
);
1110 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1111 vty_out(vty
, " (duplicate nexthop removed)");
1113 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1114 vty_out(vty
, " inactive");
1116 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1117 vty_out(vty
, " onlink");
1119 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1120 vty_out(vty
, " (recursive)");
1122 switch (nexthop
->type
) {
1123 case NEXTHOP_TYPE_IPV4
:
1124 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1125 if (nexthop
->src
.ipv4
.s_addr
) {
1126 if (inet_ntop(AF_INET
,
1128 addrstr
, sizeof addrstr
))
1129 vty_out(vty
, ", src %s",
1133 case NEXTHOP_TYPE_IPV6
:
1134 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1135 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1137 if (inet_ntop(AF_INET6
,
1139 addrstr
, sizeof addrstr
))
1140 vty_out(vty
, ", src %s",
1148 if (re
->nexthop_mtu
)
1149 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
1151 /* Label information */
1152 if (nexthop
->nh_label
1153 && nexthop
->nh_label
->num_labels
) {
1154 vty_out(vty
, ", label %s",
1156 nexthop
->nh_label
->num_labels
,
1157 nexthop
->nh_label
->label
, buf
,
1167 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
1168 struct route_entry
*re
, json_object
*json
)
1170 struct nexthop
*nexthop
;
1172 char buf
[SRCDEST2STR_BUFFER
];
1173 json_object
*json_nexthops
= NULL
;
1174 json_object
*json_nexthop
= NULL
;
1175 json_object
*json_route
= NULL
;
1176 json_object
*json_labels
= NULL
;
1180 uptime
= time(NULL
);
1181 uptime
-= re
->uptime
;
1182 tm
= gmtime(&uptime
);
1185 json_route
= json_object_new_object();
1186 json_nexthops
= json_object_new_array();
1188 json_object_string_add(json_route
, "prefix",
1189 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1190 json_object_string_add(json_route
, "protocol",
1191 zebra_route_string(re
->type
));
1194 json_object_int_add(json_route
, "instance",
1198 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
1200 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1201 json_object_boolean_true_add(json_route
, "selected");
1203 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
1204 json_object_int_add(json_route
, "distance",
1206 json_object_int_add(json_route
, "metric", re
->metric
);
1209 if (uptime
< ONE_DAY_SECOND
)
1210 sprintf(buf
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1212 else if (uptime
< ONE_WEEK_SECOND
)
1213 sprintf(buf
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1216 sprintf(buf
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1217 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1220 json_object_string_add(json_route
, "uptime", buf
);
1222 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1223 json_nexthop
= json_object_new_object();
1225 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1226 json_object_boolean_true_add(json_nexthop
,
1229 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1230 json_object_boolean_true_add(json_nexthop
,
1233 switch (nexthop
->type
) {
1234 case NEXTHOP_TYPE_IPV4
:
1235 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1236 json_object_string_add(
1238 inet_ntoa(nexthop
->gate
.ipv4
));
1239 json_object_string_add(json_nexthop
, "afi",
1242 if (nexthop
->ifindex
) {
1243 json_object_int_add(json_nexthop
,
1246 json_object_string_add(
1247 json_nexthop
, "interfaceName",
1253 case NEXTHOP_TYPE_IPV6
:
1254 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1255 json_object_string_add(
1257 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1259 json_object_string_add(json_nexthop
, "afi",
1262 if (nexthop
->ifindex
) {
1263 json_object_int_add(json_nexthop
,
1266 json_object_string_add(
1267 json_nexthop
, "interfaceName",
1274 case NEXTHOP_TYPE_IFINDEX
:
1275 json_object_boolean_true_add(
1276 json_nexthop
, "directlyConnected");
1277 json_object_int_add(json_nexthop
,
1280 json_object_string_add(
1281 json_nexthop
, "interfaceName",
1282 ifindex2ifname(nexthop
->ifindex
,
1285 case NEXTHOP_TYPE_BLACKHOLE
:
1286 json_object_boolean_true_add(json_nexthop
,
1288 switch (nexthop
->bh_type
) {
1289 case BLACKHOLE_REJECT
:
1290 json_object_boolean_true_add(
1291 json_nexthop
, "reject");
1293 case BLACKHOLE_ADMINPROHIB
:
1294 json_object_boolean_true_add(
1296 "admin-prohibited");
1298 case BLACKHOLE_NULL
:
1299 json_object_boolean_true_add(
1300 json_nexthop
, "blackhole");
1302 case BLACKHOLE_UNSPEC
:
1310 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1312 vrf_lookup_by_id(nexthop
->vrf_id
);
1314 json_object_string_add(json_nexthop
, "vrf",
1317 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1318 json_object_boolean_true_add(json_nexthop
,
1321 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1322 json_object_boolean_true_add(json_nexthop
,
1325 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1326 json_object_boolean_true_add(json_nexthop
,
1329 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1330 json_object_boolean_true_add(json_nexthop
,
1333 switch (nexthop
->type
) {
1334 case NEXTHOP_TYPE_IPV4
:
1335 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1336 if (nexthop
->src
.ipv4
.s_addr
) {
1337 if (inet_ntop(AF_INET
,
1338 &nexthop
->src
.ipv4
, buf
,
1340 json_object_string_add(
1341 json_nexthop
, "source",
1345 case NEXTHOP_TYPE_IPV6
:
1346 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1347 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1349 if (inet_ntop(AF_INET6
,
1350 &nexthop
->src
.ipv6
, buf
,
1352 json_object_string_add(
1353 json_nexthop
, "source",
1361 if (nexthop
->nh_label
1362 && nexthop
->nh_label
->num_labels
) {
1363 json_labels
= json_object_new_array();
1365 for (int label_index
= 0;
1367 < nexthop
->nh_label
->num_labels
;
1369 json_object_array_add(
1371 json_object_new_int(
1372 nexthop
->nh_label
->label
1375 json_object_object_add(json_nexthop
, "labels",
1379 json_object_array_add(json_nexthops
, json_nexthop
);
1382 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1383 json_object_array_add(json
, json_route
);
1387 /* Nexthop information. */
1388 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1389 if (nexthop
== re
->ng
.nexthop
) {
1390 /* Prefix information. */
1391 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1393 len
+= vty_out(vty
, "[%d]", re
->instance
);
1396 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)
1399 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1402 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1404 /* Distance and metric display. */
1405 if (re
->type
!= ZEBRA_ROUTE_CONNECT
)
1406 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1409 vty_out(vty
, " %c%*c",
1410 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1411 ? CHECK_FLAG(nexthop
->flags
,
1412 NEXTHOP_FLAG_DUPLICATE
)
1416 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1419 switch (nexthop
->type
) {
1420 case NEXTHOP_TYPE_IPV4
:
1421 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1422 vty_out(vty
, " via %s", inet_ntoa(nexthop
->gate
.ipv4
));
1423 if (nexthop
->ifindex
)
1424 vty_out(vty
, ", %s",
1425 ifindex2ifname(nexthop
->ifindex
,
1428 case NEXTHOP_TYPE_IPV6
:
1429 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1430 vty_out(vty
, " via %s",
1431 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
1433 if (nexthop
->ifindex
)
1434 vty_out(vty
, ", %s",
1435 ifindex2ifname(nexthop
->ifindex
,
1439 case NEXTHOP_TYPE_IFINDEX
:
1440 vty_out(vty
, " is directly connected, %s",
1441 ifindex2ifname(nexthop
->ifindex
,
1444 case NEXTHOP_TYPE_BLACKHOLE
:
1445 vty_out(vty
, " unreachable");
1446 switch (nexthop
->bh_type
) {
1447 case BLACKHOLE_REJECT
:
1448 vty_out(vty
, " (ICMP unreachable)");
1450 case BLACKHOLE_ADMINPROHIB
:
1451 vty_out(vty
, " (ICMP admin-prohibited)");
1453 case BLACKHOLE_NULL
:
1454 vty_out(vty
, " (blackhole)");
1456 case BLACKHOLE_UNSPEC
:
1464 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1465 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
1467 vty_out(vty
, "(vrf %s)", vrf
->name
);
1470 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1471 vty_out(vty
, " inactive");
1473 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1474 vty_out(vty
, " onlink");
1476 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1477 vty_out(vty
, " (recursive)");
1479 switch (nexthop
->type
) {
1480 case NEXTHOP_TYPE_IPV4
:
1481 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1482 if (nexthop
->src
.ipv4
.s_addr
) {
1483 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
1485 vty_out(vty
, ", src %s", buf
);
1488 case NEXTHOP_TYPE_IPV6
:
1489 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1490 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
1491 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
1493 vty_out(vty
, ", src %s", buf
);
1500 /* Label information */
1501 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
1502 vty_out(vty
, ", label %s",
1503 mpls_label2str(nexthop
->nh_label
->num_labels
,
1504 nexthop
->nh_label
->label
, buf
,
1508 if (uptime
< ONE_DAY_SECOND
)
1509 vty_out(vty
, ", %02d:%02d:%02d", tm
->tm_hour
,
1510 tm
->tm_min
, tm
->tm_sec
);
1511 else if (uptime
< ONE_WEEK_SECOND
)
1512 vty_out(vty
, ", %dd%02dh%02dm", tm
->tm_yday
,
1513 tm
->tm_hour
, tm
->tm_min
);
1515 vty_out(vty
, ", %02dw%dd%02dh", tm
->tm_yday
/ 7,
1516 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1522 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1523 struct route_table
*table
, afi_t afi
,
1524 bool use_fib
, route_tag_t tag
,
1525 const struct prefix
*longer_prefix_p
,
1526 bool supernets_only
, int type
,
1527 u_short ospf_instance_id
, u_char use_json
)
1529 struct route_node
*rn
;
1530 struct route_entry
*re
;
1533 json_object
*json
= NULL
;
1534 json_object
*json_prefix
= NULL
;
1539 json
= json_object_new_object();
1541 /* Show all routes. */
1542 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
1543 dest
= rib_dest_from_rnode(rn
);
1545 RNODE_FOREACH_RE (rn
, re
) {
1546 if (use_fib
&& re
!= dest
->selected_fib
)
1549 if (tag
&& re
->tag
!= tag
)
1553 && !prefix_match(longer_prefix_p
, &rn
->p
))
1556 /* This can only be true when the afi is IPv4 */
1557 if (supernets_only
) {
1558 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1560 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1563 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1566 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1570 if (type
&& re
->type
!= type
)
1573 if (ospf_instance_id
1574 && (re
->type
!= ZEBRA_ROUTE_OSPF
1575 || re
->instance
!= ospf_instance_id
))
1580 json_prefix
= json_object_new_array();
1585 SHOW_ROUTE_V4_HEADER
);
1588 SHOW_ROUTE_V6_HEADER
);
1590 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1591 vty_out(vty
, "\nVRF %s:\n",
1598 vty_show_ip_route(vty
, rn
, re
, json_prefix
);
1602 prefix2str(&rn
->p
, buf
, sizeof buf
);
1603 json_object_object_add(json
, buf
, json_prefix
);
1609 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1610 json
, JSON_C_TO_STRING_PRETTY
));
1611 json_object_free(json
);
1615 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1616 safi_t safi
, bool use_fib
, u_char use_json
,
1618 const struct prefix
*longer_prefix_p
,
1619 bool supernets_only
, int type
,
1620 u_short ospf_instance_id
)
1622 struct route_table
*table
;
1623 struct zebra_vrf
*zvrf
= NULL
;
1625 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1627 vty_out(vty
, "{}\n");
1629 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1633 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1635 vty_out(vty
, "{}\n");
1637 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1641 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1644 vty_out(vty
, "{}\n");
1648 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1649 longer_prefix_p
, supernets_only
, type
,
1650 ospf_instance_id
, use_json
);
1655 DEFPY (show_route_table
,
1656 show_route_table_cmd
,
1657 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1661 "IP routing table\n"
1662 "Table to display\n"
1663 "The table number to display, if available\n"
1666 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1667 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1668 struct route_table
*t
;
1670 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1672 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1680 "show ip nht [vrf NAME]",
1683 "IP nexthop tracking table\n"
1687 vrf_id_t vrf_id
= VRF_DEFAULT
;
1690 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1692 zebra_print_rnh_table(vrf_id
, AF_INET
, vty
, RNH_NEXTHOP_TYPE
);
1697 DEFUN (show_ip_nht_vrf_all
,
1698 show_ip_nht_vrf_all_cmd
,
1699 "show ip nht vrf all",
1702 "IP nexthop tracking table\n"
1703 VRF_ALL_CMD_HELP_STR
)
1706 struct zebra_vrf
*zvrf
;
1708 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1709 if ((zvrf
= vrf
->info
) != NULL
) {
1710 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1711 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET
, vty
,
1718 DEFUN (show_ipv6_nht
,
1720 "show ipv6 nht [vrf NAME]",
1723 "IPv6 nexthop tracking table\n"
1727 vrf_id_t vrf_id
= VRF_DEFAULT
;
1730 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1732 zebra_print_rnh_table(vrf_id
, AF_INET6
, vty
, RNH_NEXTHOP_TYPE
);
1737 DEFUN (show_ipv6_nht_vrf_all
,
1738 show_ipv6_nht_vrf_all_cmd
,
1739 "show ipv6 nht vrf all",
1742 "IPv6 nexthop tracking table\n"
1743 VRF_ALL_CMD_HELP_STR
)
1746 struct zebra_vrf
*zvrf
;
1748 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1749 if ((zvrf
= vrf
->info
) != NULL
) {
1750 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1751 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET6
, vty
,
1758 DEFUN (ip_nht_default_route
,
1759 ip_nht_default_route_cmd
,
1760 "ip nht resolve-via-default",
1762 "Filter Next Hop tracking route resolution\n"
1763 "Resolve via default route\n")
1765 if (zebra_rnh_ip_default_route
)
1768 zebra_rnh_ip_default_route
= 1;
1769 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1773 DEFUN (no_ip_nht_default_route
,
1774 no_ip_nht_default_route_cmd
,
1775 "no ip nht resolve-via-default",
1778 "Filter Next Hop tracking route resolution\n"
1779 "Resolve via default route\n")
1781 if (!zebra_rnh_ip_default_route
)
1784 zebra_rnh_ip_default_route
= 0;
1785 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1789 DEFUN (ipv6_nht_default_route
,
1790 ipv6_nht_default_route_cmd
,
1791 "ipv6 nht resolve-via-default",
1793 "Filter Next Hop tracking route resolution\n"
1794 "Resolve via default route\n")
1796 if (zebra_rnh_ipv6_default_route
)
1799 zebra_rnh_ipv6_default_route
= 1;
1800 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1804 DEFUN (no_ipv6_nht_default_route
,
1805 no_ipv6_nht_default_route_cmd
,
1806 "no ipv6 nht resolve-via-default",
1809 "Filter Next Hop tracking route resolution\n"
1810 "Resolve via default route\n")
1812 if (!zebra_rnh_ipv6_default_route
)
1815 zebra_rnh_ipv6_default_route
= 0;
1816 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1824 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1827 |A.B.C.D/M$prefix longer-prefixes\
1828 |supernets-only$supernets_only\
1831 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1832 |ospf$type_str (1-65535)$ospf_instance_id\
1834 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1837 |X:X::X:X/M$prefix longer-prefixes\
1839 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1844 "IP forwarding table\n"
1845 "IP routing table\n"
1846 VRF_FULL_CMD_HELP_STR
1847 "Show only routes with tag\n"
1849 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1850 "Show route matching the specified Network/Mask pair only\n"
1851 "Show supernet entries only\n"
1852 FRR_IP_REDIST_HELP_STR_ZEBRA
1853 "Open Shortest Path First (OSPFv2)\n"
1856 "IP forwarding table\n"
1857 "IP routing table\n"
1858 VRF_FULL_CMD_HELP_STR
1859 "Show only routes with tag\n"
1862 "Show route matching the specified Network/Mask pair only\n"
1863 FRR_IP6_REDIST_HELP_STR_ZEBRA
1866 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1871 type
= proto_redistnum(afi
, type_str
);
1873 vty_out(vty
, "Unknown route type\n");
1879 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1880 struct zebra_vrf
*zvrf
;
1881 struct route_table
*table
;
1883 if ((zvrf
= vrf
->info
) == NULL
1884 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1888 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
, !!fib
,
1889 !!json
, tag
, prefix_str
? prefix
: NULL
,
1890 !!supernets_only
, type
, ospf_instance_id
);
1893 vrf_id_t vrf_id
= VRF_DEFAULT
;
1896 VRF_GET_ID(vrf_id
, vrf_name
);
1897 vrf
= vrf_lookup_by_id(vrf_id
);
1898 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
, !!fib
,
1899 !!json
, tag
, prefix_str
? prefix
: NULL
,
1900 !!supernets_only
, type
, ospf_instance_id
);
1906 DEFPY (show_route_detail
,
1907 show_route_detail_cmd
,
1910 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
1915 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
1923 "IP routing table\n"
1924 VRF_FULL_CMD_HELP_STR
1925 "Network in the IP routing table to display\n"
1926 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1928 "IP routing table\n"
1929 VRF_FULL_CMD_HELP_STR
1933 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1934 struct route_table
*table
;
1936 struct route_node
*rn
;
1939 prefix_str
= address_str
;
1940 if (str2prefix(prefix_str
, &p
) < 0) {
1941 vty_out(vty
, "%% Malformed address\n");
1947 struct zebra_vrf
*zvrf
;
1949 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1950 if ((zvrf
= vrf
->info
) == NULL
1951 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1954 rn
= route_node_match(table
, &p
);
1957 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1958 route_unlock_node(rn
);
1962 vty_show_ip_route_detail(vty
, rn
, 0);
1964 route_unlock_node(rn
);
1967 vrf_id_t vrf_id
= VRF_DEFAULT
;
1970 VRF_GET_ID(vrf_id
, vrf_name
);
1972 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1976 rn
= route_node_match(table
, &p
);
1978 vty_out(vty
, "%% Network not in table\n");
1981 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1982 vty_out(vty
, "%% Network not in table\n");
1983 route_unlock_node(rn
);
1987 vty_show_ip_route_detail(vty
, rn
, 0);
1989 route_unlock_node(rn
);
1995 DEFPY (show_route_summary
,
1996 show_route_summary_cmd
,
1999 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2000 summary [prefix$prefix]\
2001 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2002 summary [prefix$prefix]\
2006 "IP routing table\n"
2007 VRF_FULL_CMD_HELP_STR
2008 "Summary of all routes\n"
2011 "IP routing table\n"
2012 VRF_FULL_CMD_HELP_STR
2013 "Summary of all routes\n"
2016 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2017 struct route_table
*table
;
2021 struct zebra_vrf
*zvrf
;
2023 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2024 if ((zvrf
= vrf
->info
) == NULL
2025 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2029 vty_show_ip_route_summary_prefix(vty
, table
);
2031 vty_show_ip_route_summary(vty
, table
);
2034 vrf_id_t vrf_id
= VRF_DEFAULT
;
2037 VRF_GET_ID(vrf_id
, vrf_name
);
2039 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2044 vty_show_ip_route_summary_prefix(vty
, table
);
2046 vty_show_ip_route_summary(vty
, table
);
2052 static void vty_show_ip_route_summary(struct vty
*vty
,
2053 struct route_table
*table
)
2055 struct route_node
*rn
;
2056 struct route_entry
*re
;
2057 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2058 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2059 u_int32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2060 u_int32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2064 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2065 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2066 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2067 RNODE_FOREACH_RE (rn
, re
) {
2068 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2069 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2071 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2073 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2075 rib_cnt
[re
->type
]++;
2077 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)) {
2078 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2081 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2083 fib_cnt
[re
->type
]++;
2087 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2088 "FIB", zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2090 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2091 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2092 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2093 if (i
== ZEBRA_ROUTE_BGP
) {
2094 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2095 rib_cnt
[ZEBRA_ROUTE_BGP
],
2096 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2097 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2098 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2099 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2101 vty_out(vty
, "%-20s %-20d %-20d \n",
2102 zebra_route_string(i
), rib_cnt
[i
],
2107 vty_out(vty
, "------\n");
2108 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2109 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2114 * Implementation of the ip route summary prefix command.
2116 * This command prints the primary prefixes that have been installed by various
2117 * protocols on the box.
2120 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2121 struct route_table
*table
)
2123 struct route_node
*rn
;
2124 struct route_entry
*re
;
2125 struct nexthop
*nexthop
;
2126 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2127 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2128 u_int32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2129 u_int32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2133 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2134 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2135 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2136 RNODE_FOREACH_RE (rn
, re
) {
2139 * In case of ECMP, count only once.
2142 for (nexthop
= re
->ng
.nexthop
; (!cnt
&& nexthop
);
2143 nexthop
= nexthop
->next
) {
2145 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2146 rib_cnt
[re
->type
]++;
2147 if (CHECK_FLAG(nexthop
->flags
,
2148 NEXTHOP_FLAG_FIB
)) {
2149 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2150 fib_cnt
[re
->type
]++;
2152 if (re
->type
== ZEBRA_ROUTE_BGP
2153 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2154 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2155 if (CHECK_FLAG(nexthop
->flags
,
2157 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2162 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2163 "Prefix Routes", "FIB",
2164 zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2166 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2167 if (rib_cnt
[i
] > 0) {
2168 if (i
== ZEBRA_ROUTE_BGP
) {
2169 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2170 rib_cnt
[ZEBRA_ROUTE_BGP
]
2171 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2172 fib_cnt
[ZEBRA_ROUTE_BGP
]
2173 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2174 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2175 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2176 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2178 vty_out(vty
, "%-20s %-20d %-20d \n",
2179 zebra_route_string(i
), rib_cnt
[i
],
2184 vty_out(vty
, "------\n");
2185 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2186 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2190 /* Write static route configuration. */
2191 int static_config(struct vty
*vty
, struct zebra_vrf
*zvrf
, afi_t afi
,
2192 safi_t safi
, const char *cmd
)
2194 struct static_hold_route
*shr
;
2195 struct listnode
*node
;
2197 struct route_node
*rn
;
2198 struct static_route
*si
;
2199 struct route_table
*stable
;
2200 char buf
[SRCDEST2STR_BUFFER
];
2203 if ((stable
= zvrf
->stable
[afi
][safi
]) == NULL
)
2206 sprintf(spacing
, "%s%s", (zvrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
2210 * Static routes for vrfs not fully inited
2212 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
2213 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
2216 if (strcmp(zvrf
->vrf
->name
, shr
->vrf_name
) != 0)
2219 vty_out(vty
, "%s ", spacing
);
2221 vty_out(vty
, "%s ", shr
->dest_str
);
2223 vty_out(vty
, "%s ", shr
->mask_str
);
2225 vty_out(vty
, "from %s ", shr
->src_str
);
2227 vty_out(vty
, "%s ", shr
->gate_str
);
2229 vty_out(vty
, "%s ", shr
->ifname
);
2231 vty_out(vty
, "%s ", shr
->flag_str
);
2233 vty_out(vty
, "tag %s", shr
->tag_str
);
2234 if (shr
->distance_str
)
2235 vty_out(vty
, "%s ", shr
->distance_str
);
2237 vty_out(vty
, "label %s ", shr
->label_str
);
2238 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
2239 vty_out(vty
, "nexthop-vrf %s", shr
->nhvrf_name
);
2243 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
2244 for (si
= rn
->info
; si
; si
= si
->next
) {
2245 vty_out(vty
, "%s %s", spacing
,
2246 srcdest_rnode2str(rn
, buf
, sizeof buf
));
2249 case STATIC_IPV4_GATEWAY
:
2250 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
2252 case STATIC_IPV6_GATEWAY
:
2254 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2258 vty_out(vty
, " %s", si
->ifname
);
2260 case STATIC_BLACKHOLE
:
2261 switch (si
->bh_type
) {
2262 case STATIC_BLACKHOLE_DROP
:
2263 vty_out(vty
, " blackhole");
2265 case STATIC_BLACKHOLE_NULL
:
2266 vty_out(vty
, " Null0");
2268 case STATIC_BLACKHOLE_REJECT
:
2269 vty_out(vty
, " reject");
2273 case STATIC_IPV4_GATEWAY_IFNAME
:
2274 vty_out(vty
, " %s %s",
2275 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
2279 case STATIC_IPV6_GATEWAY_IFNAME
:
2280 vty_out(vty
, " %s %s",
2281 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2288 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
2290 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
2291 vty_out(vty
, " %d", si
->distance
);
2293 if (si
->nh_vrf_id
!= si
->vrf_id
) {
2296 vrf
= vrf_lookup_by_id(si
->nh_vrf_id
);
2297 vty_out(vty
, " nexthop-vrf %s",
2298 (vrf
) ? vrf
->name
: "Unknown");
2301 /* Label information */
2302 if (si
->snh_label
.num_labels
)
2303 vty_out(vty
, " label %s",
2304 mpls_label2str(si
->snh_label
.num_labels
,
2305 si
->snh_label
.label
, buf
,
2315 DEFPY(ipv6_route_blackhole
,
2316 ipv6_route_blackhole_cmd
,
2317 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2318 <Null0|reject|blackhole>$flag \
2320 tag (1-4294967295) \
2327 "Establish static routes\n"
2328 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2329 "IPv6 source-dest route\n"
2330 "IPv6 source prefix\n"
2332 "Emit an ICMP unreachable when matched\n"
2333 "Silently discard pkts when matched\n"
2334 "Set tag for this route\n"
2336 "Distance value for this prefix\n"
2340 return zebra_static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
2341 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
2342 distance_str
, vrf
, label
);
2345 DEFPY(ipv6_route_blackhole_vrf
,
2346 ipv6_route_blackhole_vrf_cmd
,
2347 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2348 <Null0|reject|blackhole>$flag \
2350 tag (1-4294967295) \
2356 "Establish static routes\n"
2357 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2358 "IPv6 source-dest route\n"
2359 "IPv6 source prefix\n"
2361 "Emit an ICMP unreachable when matched\n"
2362 "Silently discard pkts when matched\n"
2363 "Set tag for this route\n"
2365 "Distance value for this prefix\n"
2368 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2369 struct zebra_vrf
*zvrf
= vrf
->info
;
2372 * Coverity is complaining that prefix could
2373 * be dereferenced, but we know that prefix will
2374 * valid. Add an assert to make it happy
2377 return zebra_static_route_leak(
2378 vty
, zvrf
, zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2379 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
);
2382 DEFPY(ipv6_route_address_interface
,
2383 ipv6_route_address_interface_cmd
,
2384 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2388 tag (1-4294967295) \
2396 "Establish static routes\n"
2397 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2398 "IPv6 source-dest route\n"
2399 "IPv6 source prefix\n"
2400 "IPv6 gateway address\n"
2401 "IPv6 gateway interface name\n"
2402 "Set tag for this route\n"
2404 "Distance value for this prefix\n"
2409 struct zebra_vrf
*zvrf
;
2410 struct zebra_vrf
*nh_zvrf
;
2412 zvrf
= zebra_vrf_lookup_by_name(vrf
);
2414 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2415 return CMD_WARNING_CONFIG_FAILED
;
2419 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2424 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2425 return CMD_WARNING_CONFIG_FAILED
;
2428 return zebra_static_route_leak(
2429 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2430 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
);
2433 DEFPY(ipv6_route_address_interface_vrf
,
2434 ipv6_route_address_interface_vrf_cmd
,
2435 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2439 tag (1-4294967295) \
2446 "Establish static routes\n"
2447 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2448 "IPv6 source-dest route\n"
2449 "IPv6 source prefix\n"
2450 "IPv6 gateway address\n"
2451 "IPv6 gateway interface name\n"
2452 "Set tag for this route\n"
2454 "Distance value for this prefix\n"
2458 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2459 struct zebra_vrf
*zvrf
= vrf
->info
;
2460 struct zebra_vrf
*nh_zvrf
;
2463 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2468 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2469 return CMD_WARNING_CONFIG_FAILED
;
2472 return zebra_static_route_leak(
2473 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2474 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
);
2479 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2480 <X:X::X:X$gate|INTERFACE$ifname> \
2482 tag (1-4294967295) \
2490 "Establish static routes\n"
2491 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2492 "IPv6 source-dest route\n"
2493 "IPv6 source prefix\n"
2494 "IPv6 gateway address\n"
2495 "IPv6 gateway interface name\n"
2496 "Set tag for this route\n"
2498 "Distance value for this prefix\n"
2503 struct zebra_vrf
*zvrf
;
2504 struct zebra_vrf
*nh_zvrf
;
2506 zvrf
= zebra_vrf_lookup_by_name(vrf
);
2508 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2509 return CMD_WARNING_CONFIG_FAILED
;
2513 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2518 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2519 return CMD_WARNING_CONFIG_FAILED
;
2522 return zebra_static_route_leak(
2523 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2524 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
);
2527 DEFPY(ipv6_route_vrf
,
2529 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2530 <X:X::X:X$gate|INTERFACE$ifname> \
2532 tag (1-4294967295) \
2539 "Establish static routes\n"
2540 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2541 "IPv6 source-dest route\n"
2542 "IPv6 source prefix\n"
2543 "IPv6 gateway address\n"
2544 "IPv6 gateway interface name\n"
2545 "Set tag for this route\n"
2547 "Distance value for this prefix\n"
2551 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2552 struct zebra_vrf
*zvrf
= vrf
->info
;
2553 struct zebra_vrf
*nh_zvrf
;
2556 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2561 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2562 return CMD_WARNING_CONFIG_FAILED
;
2565 return zebra_static_route_leak(
2566 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2567 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
);
2571 * Show IPv6 mroute command.Used to dump
2572 * the Multicast routing table.
2574 DEFUN (show_ipv6_mroute
,
2575 show_ipv6_mroute_cmd
,
2576 "show ipv6 mroute [vrf NAME]",
2579 "IPv6 Multicast routing table\n"
2582 struct route_table
*table
;
2583 struct route_node
*rn
;
2584 struct route_entry
*re
;
2586 vrf_id_t vrf_id
= VRF_DEFAULT
;
2589 VRF_GET_ID(vrf_id
, argv
[4]->arg
);
2591 table
= zebra_vrf_table(AFI_IP6
, SAFI_MULTICAST
, vrf_id
);
2595 /* Show all IPv6 route. */
2596 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2597 RNODE_FOREACH_RE (rn
, re
) {
2599 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2602 vty_show_ip_route(vty
, rn
, re
, NULL
);
2607 DEFUN (show_ipv6_mroute_vrf_all
,
2608 show_ipv6_mroute_vrf_all_cmd
,
2609 "show ipv6 mroute vrf all",
2612 "IPv6 Multicast routing table\n"
2613 VRF_ALL_CMD_HELP_STR
)
2615 struct route_table
*table
;
2616 struct route_node
*rn
;
2617 struct route_entry
*re
;
2619 struct zebra_vrf
*zvrf
;
2622 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2623 if ((zvrf
= vrf
->info
) == NULL
2624 || (table
= zvrf
->table
[AFI_IP6
][SAFI_MULTICAST
]) == NULL
)
2627 /* Show all IPv6 route. */
2628 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2629 RNODE_FOREACH_RE (rn
, re
) {
2631 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2634 vty_show_ip_route(vty
, rn
, re
, NULL
);
2640 DEFUN (allow_external_route_update
,
2641 allow_external_route_update_cmd
,
2642 "allow-external-route-update",
2643 "Allow FRR routes to be overwritten by external processes\n")
2650 DEFUN (no_allow_external_route_update
,
2651 no_allow_external_route_update_cmd
,
2652 "no allow-external-route-update",
2654 "Allow FRR routes to be overwritten by external processes\n")
2669 struct zebra_vrf
*zvrf
;
2671 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2672 if (!(zvrf
= vrf
->info
))
2674 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2677 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2678 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2679 vty_out(vty
, "inactive");
2680 else if (zvrf_ns_name(zvrf
))
2681 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2682 zvrf_ns_name(zvrf
));
2684 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2686 if (vrf_is_user_cfged(vrf
))
2687 vty_out(vty
, " (configured)");
2694 DEFUN (default_vrf_vni_mapping
,
2695 default_vrf_vni_mapping_cmd
,
2696 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2697 "VNI corresponding to the DEFAULT VRF\n"
2699 "Prefix routes only \n")
2702 char err
[ERR_STR_SZ
];
2703 struct zebra_vrf
*zvrf
= NULL
;
2704 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2707 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2714 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2717 vty_out(vty
, "%s\n", err
);
2724 DEFUN (no_default_vrf_vni_mapping
,
2725 no_default_vrf_vni_mapping_cmd
,
2726 "no vni " CMD_VNI_RANGE
,
2728 "VNI corresponding to DEFAULT VRF\n"
2732 char err
[ERR_STR_SZ
];
2733 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2734 struct zebra_vrf
*zvrf
= NULL
;
2736 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2740 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
, 0, 0);
2742 vty_out(vty
, "%s\n", err
);
2749 DEFUN (vrf_vni_mapping
,
2750 vrf_vni_mapping_cmd
,
2751 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2752 "VNI corresponding to tenant VRF\n"
2754 "prefix-routes-only\n")
2759 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2760 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2761 char err
[ERR_STR_SZ
];
2769 /* Mark as having FRR configuration */
2770 vrf_set_user_cfged(vrf
);
2771 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2774 vty_out(vty
, "%s\n", err
);
2781 DEFUN (no_vrf_vni_mapping
,
2782 no_vrf_vni_mapping_cmd
,
2783 "no vni " CMD_VNI_RANGE
,
2785 "VNI corresponding to tenant VRF\n"
2789 char err
[ERR_STR_SZ
];
2790 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2792 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2797 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
, 0, 0);
2799 vty_out(vty
, "%s\n", err
);
2803 /* If no other FRR config for this VRF, mark accordingly. */
2804 if (!zebra_vrf_has_config(zvrf
))
2805 vrf_reset_user_cfged(vrf
);
2811 DEFUN (show_vrf_vni
,
2813 "show vrf vni [json]",
2820 struct zebra_vrf
*zvrf
;
2821 json_object
*json
= NULL
;
2822 json_object
*json_vrfs
= NULL
;
2823 u_char uj
= use_json(argc
, argv
);
2826 json
= json_object_new_object();
2827 json_vrfs
= json_object_new_array();
2831 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2832 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2834 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2839 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2843 json_object_object_add(json
, "vrfs", json_vrfs
);
2844 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2845 json
, JSON_C_TO_STRING_PRETTY
));
2846 json_object_free(json
);
2852 DEFUN (show_evpn_global
,
2853 show_evpn_global_cmd
,
2859 u_char uj
= use_json(argc
, argv
);
2861 zebra_vxlan_print_evpn(vty
, uj
);
2865 DEFUN (show_evpn_vni
,
2867 "show evpn vni [json]",
2870 "VxLAN information\n"
2873 struct zebra_vrf
*zvrf
;
2874 u_char uj
= use_json(argc
, argv
);
2876 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2877 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
2881 DEFUN (show_evpn_vni_vni
,
2882 show_evpn_vni_vni_cmd
,
2883 "show evpn vni " CMD_VNI_RANGE
"[json]",
2886 "VxLAN Network Identifier\n"
2890 struct zebra_vrf
*zvrf
;
2892 u_char uj
= use_json(argc
, argv
);
2894 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
2895 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2896 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
);
2900 DEFUN (show_evpn_rmac_vni_mac
,
2901 show_evpn_rmac_vni_mac_cmd
,
2902 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
2909 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2914 u_char uj
= use_json(argc
, argv
);
2916 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
2917 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
2918 vty_out(vty
, "%% Malformed MAC address\n");
2921 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
2925 DEFUN (show_evpn_rmac_vni
,
2926 show_evpn_rmac_vni_cmd
,
2927 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
2936 u_char uj
= use_json(argc
, argv
);
2938 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
2939 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
2944 DEFUN (show_evpn_rmac_vni_all
,
2945 show_evpn_rmac_vni_all_cmd
,
2946 "show evpn rmac vni all [json]",
2954 u_char uj
= use_json(argc
, argv
);
2956 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
2961 DEFUN (show_evpn_nh_vni_ip
,
2962 show_evpn_nh_vni_ip_cmd
,
2963 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
2970 "Host address (ipv4 or ipv6)\n"
2975 u_char uj
= use_json(argc
, argv
);
2977 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
2978 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
2980 vty_out(vty
, "%% Malformed Neighbor address\n");
2983 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
2988 DEFUN (show_evpn_nh_vni
,
2989 show_evpn_nh_vni_cmd
,
2990 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
2999 u_char uj
= use_json(argc
, argv
);
3001 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3002 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3007 DEFUN (show_evpn_nh_vni_all
,
3008 show_evpn_nh_vni_all_cmd
,
3009 "show evpn next-hops vni all [json]",
3017 u_char uj
= use_json(argc
, argv
);
3019 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3024 DEFUN (show_evpn_mac_vni
,
3025 show_evpn_mac_vni_cmd
,
3026 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3030 "VxLAN Network Identifier\n"
3034 struct zebra_vrf
*zvrf
;
3036 u_char uj
= use_json(argc
, argv
);
3038 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3039 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3040 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3044 DEFUN (show_evpn_mac_vni_all
,
3045 show_evpn_mac_vni_all_cmd
,
3046 "show evpn mac vni all [json]",
3050 "VxLAN Network Identifier\n"
3054 struct zebra_vrf
*zvrf
;
3055 u_char uj
= use_json(argc
, argv
);
3057 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3058 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, uj
);
3062 DEFUN (show_evpn_mac_vni_all_vtep
,
3063 show_evpn_mac_vni_all_vtep_cmd
,
3064 "show evpn mac vni all vtep A.B.C.D [json]",
3068 "VxLAN Network Identifier\n"
3071 "Remote VTEP IP address\n"
3074 struct zebra_vrf
*zvrf
;
3075 struct in_addr vtep_ip
;
3076 u_char uj
= use_json(argc
, argv
);
3078 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3080 vty_out(vty
, "%% Malformed VTEP IP address\n");
3083 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3084 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3090 DEFUN (show_evpn_mac_vni_mac
,
3091 show_evpn_mac_vni_mac_cmd
,
3092 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD",
3096 "VxLAN Network Identifier\n"
3099 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
3101 struct zebra_vrf
*zvrf
;
3105 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3106 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3107 vty_out(vty
, "%% Malformed MAC address");
3110 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3111 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
);
3115 DEFUN (show_evpn_mac_vni_vtep
,
3116 show_evpn_mac_vni_vtep_cmd
,
3117 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3121 "VxLAN Network Identifier\n"
3124 "Remote VTEP IP address\n"
3127 struct zebra_vrf
*zvrf
;
3129 struct in_addr vtep_ip
;
3130 u_char uj
= use_json(argc
, argv
);
3132 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3133 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3135 vty_out(vty
, "%% Malformed VTEP IP address\n");
3139 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3140 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3144 DEFUN (show_evpn_neigh_vni
,
3145 show_evpn_neigh_vni_cmd
,
3146 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3149 "ARP and ND cache\n"
3150 "VxLAN Network Identifier\n"
3154 struct zebra_vrf
*zvrf
;
3156 u_char uj
= use_json(argc
, argv
);
3158 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3159 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3160 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3164 DEFUN (show_evpn_neigh_vni_all
,
3165 show_evpn_neigh_vni_all_cmd
,
3166 "show evpn arp-cache vni all [json]",
3169 "ARP and ND cache\n"
3170 "VxLAN Network Identifier\n"
3174 struct zebra_vrf
*zvrf
;
3175 u_char uj
= use_json(argc
, argv
);
3177 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3178 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, uj
);
3182 DEFUN (show_evpn_neigh_vni_neigh
,
3183 show_evpn_neigh_vni_neigh_cmd
,
3184 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3187 "ARP and ND cache\n"
3188 "VxLAN Network Identifier\n"
3191 "Neighbor address (IPv4 or IPv6 address)\n"
3194 struct zebra_vrf
*zvrf
;
3197 u_char uj
= use_json(argc
, argv
);
3199 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3200 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3202 vty_out(vty
, "%% Malformed Neighbor address\n");
3205 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3206 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3210 DEFUN (show_evpn_neigh_vni_vtep
,
3211 show_evpn_neigh_vni_vtep_cmd
,
3212 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3215 "ARP and ND cache\n"
3216 "VxLAN Network Identifier\n"
3219 "Remote VTEP IP address\n"
3222 struct zebra_vrf
*zvrf
;
3224 struct in_addr vtep_ip
;
3225 u_char uj
= use_json(argc
, argv
);
3227 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3228 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3230 vty_out(vty
, "%% Malformed VTEP IP address\n");
3234 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3235 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3239 /* Static ip route configuration write function. */
3240 static int zebra_ip_config(struct vty
*vty
)
3244 write
+= zebra_import_table_config(vty
);
3249 DEFUN (ip_zebra_import_table_distance
,
3250 ip_zebra_import_table_distance_cmd
,
3251 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3253 "import routes from non-main kernel table\n"
3254 "kernel routing table id\n"
3255 "Distance for imported routes\n"
3256 "Default distance value\n"
3257 "route-map for filtering\n"
3260 u_int32_t table_id
= 0;
3262 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3263 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3265 strmatch(argv
[argc
- 2]->text
, "route-map")
3266 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3270 if (argc
== 7 || (argc
== 5 && !rmap
))
3271 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3273 if (!is_zebra_valid_kernel_table(table_id
)) {
3275 "Invalid routing table ID, %d. Must be in range 1-252\n",
3278 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3282 if (is_zebra_main_routing_table(table_id
)) {
3284 "Invalid routing table ID, %d. Must be non-default table\n",
3287 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3291 ret
= zebra_import_table(AFI_IP
, table_id
, distance
, rmap
, 1);
3293 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3298 DEFUN_HIDDEN (zebra_packet_process
,
3299 zebra_packet_process_cmd
,
3300 "zebra zapi-packets (1-10000)",
3303 "Number of packets to process before relinquishing thread\n")
3305 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3307 zebrad
.packets_to_process
= packets
;
3312 DEFUN_HIDDEN (no_zebra_packet_process
,
3313 no_zebra_packet_process_cmd
,
3314 "no zebra zapi-packets [(1-10000)]",
3318 "Number of packets to process before relinquishing thread\n")
3320 zebrad
.packets_to_process
= ZEBRA_ZAPI_PACKETS_TO_PROCESS
;
3325 DEFUN_HIDDEN (zebra_workqueue_timer
,
3326 zebra_workqueue_timer_cmd
,
3327 "zebra work-queue (0-10000)",
3330 "Time in milliseconds\n")
3332 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3333 zebrad
.ribq
->spec
.hold
= timer
;
3338 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3339 no_zebra_workqueue_timer_cmd
,
3340 "no zebra work-queue [(0-10000)]",
3344 "Time in milliseconds\n")
3346 zebrad
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3351 DEFUN (no_ip_zebra_import_table
,
3352 no_ip_zebra_import_table_cmd
,
3353 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3356 "import routes from non-main kernel table\n"
3357 "kernel routing table id\n"
3358 "Distance for imported routes\n"
3359 "Default distance value\n"
3360 "route-map for filtering\n"
3363 u_int32_t table_id
= 0;
3364 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3366 if (!is_zebra_valid_kernel_table(table_id
)) {
3368 "Invalid routing table ID. Must be in range 1-252\n");
3372 if (is_zebra_main_routing_table(table_id
)) {
3374 "Invalid routing table ID, %d. Must be non-default table\n",
3379 if (!is_zebra_import_table_enabled(AFI_IP
, table_id
))
3382 return (zebra_import_table(AFI_IP
, table_id
, 0, NULL
, 0));
3385 static int config_write_protocol(struct vty
*vty
)
3388 vty_out(vty
, "allow-external-route-update\n");
3390 if (zebra_rnh_ip_default_route
)
3391 vty_out(vty
, "ip nht resolve-via-default\n");
3393 if (zebra_rnh_ipv6_default_route
)
3394 vty_out(vty
, "ipv6 nht resolve-via-default\n");
3396 if (zebrad
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3397 vty_out(vty
, "zebra work-queue %u\n", zebrad
.ribq
->spec
.hold
);
3399 if (zebrad
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3400 vty_out(vty
, "zebra zapi-packets %u\n",
3401 zebrad
.packets_to_process
);
3403 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3405 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3406 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3407 ipv4_multicast_mode
== MCAST_URIB_ONLY
3409 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3411 : ipv4_multicast_mode
3412 == MCAST_MIX_MRIB_FIRST
3414 : ipv4_multicast_mode
3415 == MCAST_MIX_DISTANCE
3419 zebra_routemap_config_write_protocol(vty
);
3425 /* Display default rtm_table for all clients. */
3430 "default routing table to use for all clients\n")
3432 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3436 DEFUN (config_table
,
3439 "Configure target kernel routing table\n"
3442 zebrad
.rtm_table_default
= strtol(argv
[1]->arg
, (char **)0, 10);
3446 DEFUN (no_config_table
,
3447 no_config_table_cmd
,
3448 "no table [TABLENO]",
3450 "Configure target kernel routing table\n"
3453 zebrad
.rtm_table_default
= 0;
3467 " Route Route Neighbor LSP LSP\n");
3469 "VRF Installs Removals Updates Installs Removals\n");
3471 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3472 struct zebra_vrf
*zvrf
= vrf
->info
;
3474 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
3475 " %10" PRIu64
" %10" PRIu64
"\n",
3476 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
3477 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
3478 zvrf
->lsp_removals
);
3484 DEFUN (ip_forwarding
,
3488 "Turn on IP forwarding\n")
3494 ret
= ipforward_on();
3497 vty_out(vty
, "Can't turn on IP forwarding\n");
3498 return CMD_WARNING_CONFIG_FAILED
;
3504 DEFUN (no_ip_forwarding
,
3505 no_ip_forwarding_cmd
,
3509 "Turn off IP forwarding\n")
3515 ret
= ipforward_off();
3518 vty_out(vty
, "Can't turn off IP forwarding\n");
3519 return CMD_WARNING_CONFIG_FAILED
;
3525 /* Only display ip forwarding is enabled or not. */
3526 DEFUN (show_ip_forwarding
,
3527 show_ip_forwarding_cmd
,
3528 "show ip forwarding",
3531 "IP forwarding status\n")
3538 vty_out(vty
, "IP forwarding is off\n");
3540 vty_out(vty
, "IP forwarding is on\n");
3544 /* Only display ipv6 forwarding is enabled or not. */
3545 DEFUN (show_ipv6_forwarding
,
3546 show_ipv6_forwarding_cmd
,
3547 "show ipv6 forwarding",
3549 "IPv6 information\n"
3550 "Forwarding status\n")
3554 ret
= ipforward_ipv6();
3558 vty_out(vty
, "ipv6 forwarding is unknown\n");
3561 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3564 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
3567 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3573 DEFUN (ipv6_forwarding
,
3574 ipv6_forwarding_cmd
,
3577 "Turn on IPv6 forwarding\n")
3581 ret
= ipforward_ipv6();
3583 ret
= ipforward_ipv6_on();
3586 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
3587 return CMD_WARNING_CONFIG_FAILED
;
3593 DEFUN (no_ipv6_forwarding
,
3594 no_ipv6_forwarding_cmd
,
3595 "no ipv6 forwarding",
3598 "Turn off IPv6 forwarding\n")
3602 ret
= ipforward_ipv6();
3604 ret
= ipforward_ipv6_off();
3607 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
3608 return CMD_WARNING_CONFIG_FAILED
;
3614 /* Table configuration write function. */
3615 static int config_write_table(struct vty
*vty
)
3617 if (zebrad
.rtm_table_default
)
3618 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3622 /* IPForwarding configuration write function. */
3623 static int config_write_forwarding(struct vty
*vty
)
3625 /* FIXME: Find better place for that. */
3626 router_id_write(vty
);
3629 vty_out(vty
, "no ip forwarding\n");
3630 if (!ipforward_ipv6())
3631 vty_out(vty
, "no ipv6 forwarding\n");
3632 vty_out(vty
, "!\n");
3636 /* IP node for static routes. */
3637 static struct cmd_node ip_node
= {IP_NODE
, "", 1};
3638 static struct cmd_node protocol_node
= {PROTOCOL_NODE
, "", 1};
3639 /* table node for routing tables. */
3640 static struct cmd_node table_node
= {TABLE_NODE
,
3641 "", /* This node has no interface. */
3643 static struct cmd_node forwarding_node
= {FORWARDING_NODE
,
3644 "", /* This node has no interface. */
3648 void zebra_vty_init(void)
3650 /* Install configuration write function. */
3651 install_node(&table_node
, config_write_table
);
3652 install_node(&forwarding_node
, config_write_forwarding
);
3654 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
3655 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
3656 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
3657 install_element(ENABLE_NODE
, &show_zebra_cmd
);
3660 install_element(VIEW_NODE
, &show_table_cmd
);
3661 install_element(CONFIG_NODE
, &config_table_cmd
);
3662 install_element(CONFIG_NODE
, &no_config_table_cmd
);
3663 #endif /* HAVE_NETLINK */
3665 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
3666 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
3667 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
3670 zebra_route_map_init();
3672 install_node(&ip_node
, zebra_ip_config
);
3673 install_node(&protocol_node
, config_write_protocol
);
3675 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
3676 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
3677 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
3678 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
3679 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
3680 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
3681 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
3682 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
3683 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
3684 install_element(CONFIG_NODE
, &ip_route_cmd
);
3685 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
3686 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
3687 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
3688 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
3689 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
3690 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
3691 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
3693 install_element(VIEW_NODE
, &show_vrf_cmd
);
3694 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
3695 install_element(VIEW_NODE
, &show_route_cmd
);
3696 install_element(VIEW_NODE
, &show_route_table_cmd
);
3697 install_element(VIEW_NODE
, &show_route_detail_cmd
);
3698 install_element(VIEW_NODE
, &show_route_summary_cmd
);
3699 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
3700 install_element(VIEW_NODE
, &show_ip_nht_vrf_all_cmd
);
3701 install_element(VIEW_NODE
, &show_ipv6_nht_cmd
);
3702 install_element(VIEW_NODE
, &show_ipv6_nht_vrf_all_cmd
);
3704 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
3705 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
3707 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
3708 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
3709 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
3710 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
3711 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
3712 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
3713 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
3714 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
3715 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
3716 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
3717 install_element(VIEW_NODE
, &show_ipv6_mroute_cmd
);
3719 /* Commands for VRF */
3720 install_element(VIEW_NODE
, &show_ipv6_mroute_vrf_all_cmd
);
3722 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
3723 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
3724 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
3725 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
3726 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
3727 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
3728 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
3729 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
3730 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
3731 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
3732 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
3733 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
3734 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
3735 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
3736 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
3737 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
3738 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
3739 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
3741 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
3742 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
3743 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
3744 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
3746 static_list
= list_new();
3747 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
3748 static_list
->del
= (void (*)(void *))static_list_delete
;