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"
54 #include "zebra/zebra_pbr.h"
56 extern int allow_delete
;
58 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
59 safi_t safi
, bool use_fib
, uint8_t use_json
,
61 const struct prefix
*longer_prefix_p
,
62 bool supernets_only
, int type
,
63 unsigned short ospf_instance_id
);
64 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
66 static void vty_show_ip_route_summary(struct vty
*vty
,
67 struct route_table
*table
);
68 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
69 struct route_table
*table
);
72 * special macro to allow us to get the correct zebra_vrf
74 #define ZEBRA_DECLVAR_CONTEXT(A, B) \
75 struct vrf *A = VTY_GET_CONTEXT(vrf); \
76 struct zebra_vrf *B = (vrf) ? vrf->info : NULL;
78 /* VNI range as per RFC 7432 */
79 #define CMD_VNI_RANGE "(1-16777215)"
81 struct static_hold_route
{
97 /* processed & masked destination, used for config display */
101 static struct list
*static_list
;
103 static int static_list_compare_helper(const char *s1
, const char *s2
)
115 return strcmp(s1
, s2
);
118 static void static_list_delete(struct static_hold_route
*shr
)
121 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
123 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
125 XFREE(MTYPE_STATIC_ROUTE
, shr
->dest_str
);
127 XFREE(MTYPE_STATIC_ROUTE
, shr
->mask_str
);
129 XFREE(MTYPE_STATIC_ROUTE
, shr
->src_str
);
131 XFREE(MTYPE_STATIC_ROUTE
, shr
->gate_str
);
133 XFREE(MTYPE_STATIC_ROUTE
, shr
->ifname
);
135 XFREE(MTYPE_STATIC_ROUTE
, shr
->flag_str
);
137 XFREE(MTYPE_STATIC_ROUTE
, shr
->tag_str
);
138 if (shr
->distance_str
)
139 XFREE(MTYPE_STATIC_ROUTE
, shr
->distance_str
);
141 XFREE(MTYPE_STATIC_ROUTE
, shr
->label_str
);
143 XFREE(MTYPE_STATIC_ROUTE
, shr
);
146 static int static_list_compare(void *arg1
, void *arg2
)
148 struct static_hold_route
*shr1
= arg1
;
149 struct static_hold_route
*shr2
= arg2
;
152 ret
= strcmp(shr1
->vrf_name
, shr2
->vrf_name
);
156 ret
= strcmp(shr1
->nhvrf_name
, shr2
->nhvrf_name
);
160 ret
= shr1
->afi
- shr2
->afi
;
164 ret
= shr1
->safi
- shr2
->safi
;
168 ret
= prefix_cmp(&shr1
->dest
, &shr2
->dest
);
172 ret
= static_list_compare_helper(shr1
->src_str
, shr2
->src_str
);
176 ret
= static_list_compare_helper(shr1
->gate_str
, shr2
->gate_str
);
180 ret
= static_list_compare_helper(shr1
->ifname
, shr2
->ifname
);
184 ret
= static_list_compare_helper(shr1
->flag_str
, shr2
->flag_str
);
188 ret
= static_list_compare_helper(shr1
->tag_str
, shr2
->tag_str
);
192 ret
= static_list_compare_helper(shr1
->distance_str
,
197 ret
= static_list_compare_helper(shr1
->table_str
,
202 return static_list_compare_helper(shr1
->label_str
, shr2
->label_str
);
206 /* General function for static route. */
207 static int zebra_static_route_holdem(
208 struct zebra_vrf
*zvrf
, struct zebra_vrf
*nh_zvrf
, afi_t afi
,
209 safi_t safi
, const char *negate
, struct prefix
*dest
,
210 const char *dest_str
, const char *mask_str
, const char *src_str
,
211 const char *gate_str
, const char *ifname
, const char *flag_str
,
212 const char *tag_str
, const char *distance_str
, const char *label_str
,
213 const char *table_str
)
215 struct static_hold_route
*shr
, *lookup
;
216 struct listnode
*node
;
218 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
221 shr
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(*shr
));
222 shr
->vrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, zvrf
->vrf
->name
);
223 shr
->nhvrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, nh_zvrf
->vrf
->name
);
227 prefix_copy(&shr
->dest
, dest
);
229 shr
->dest_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, dest_str
);
231 shr
->mask_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, mask_str
);
233 shr
->src_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, src_str
);
235 shr
->gate_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, gate_str
);
237 shr
->ifname
= XSTRDUP(MTYPE_STATIC_ROUTE
, ifname
);
239 shr
->flag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, flag_str
);
241 shr
->tag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, tag_str
);
243 shr
->distance_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, distance_str
);
245 shr
->label_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, label_str
);
247 shr
->table_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, table_str
);
249 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, lookup
)) {
250 if (static_list_compare(shr
, lookup
) == 0)
256 listnode_delete(static_list
, lookup
);
257 static_list_delete(shr
);
258 static_list_delete(lookup
);
264 * If a person enters the same line again
265 * we need to silently accept it
271 listnode_add_sort(static_list
, shr
);
276 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
277 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
278 XFREE(MTYPE_STATIC_ROUTE
, shr
);
283 static int zebra_static_route_leak(
284 struct vty
*vty
, struct zebra_vrf
*zvrf
, struct zebra_vrf
*nh_zvrf
,
285 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
286 const char *mask_str
, const char *src_str
, const char *gate_str
,
287 const char *ifname
, const char *flag_str
, const char *tag_str
,
288 const char *distance_str
, const char *label_str
, const char *table_str
)
292 struct prefix p
, src
;
293 struct prefix_ipv6
*src_p
= NULL
;
295 union g_addr
*gatep
= NULL
;
297 enum static_blackhole_type bh_type
= 0;
300 struct static_nh_label snh_label
;
301 uint32_t table_id
= 0;
303 ret
= str2prefix(dest_str
, &p
);
306 vty_out(vty
, "%% Malformed address\n");
308 zlog_warn("%s: Malformed address: %s",
309 __PRETTY_FUNCTION__
, dest_str
);
310 return CMD_WARNING_CONFIG_FAILED
;
315 /* Cisco like mask notation. */
317 ret
= inet_aton(mask_str
, &mask
);
320 vty_out(vty
, "%% Malformed address\n");
322 zlog_warn("%s: Malformed address: %s",
325 return CMD_WARNING_CONFIG_FAILED
;
327 p
.prefixlen
= ip_masklen(mask
);
331 /* srcdest routing */
333 ret
= str2prefix(src_str
, &src
);
334 if (ret
<= 0 || src
.family
!= AF_INET6
) {
337 "%% Malformed source address\n");
340 "%s: Malformed Source address: %s",
341 __PRETTY_FUNCTION__
, src_str
);
342 return CMD_WARNING_CONFIG_FAILED
;
344 src_p
= (struct prefix_ipv6
*)&src
;
351 /* Apply mask for given prefix. */
354 if (zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
355 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
356 vrf_set_user_cfged(zvrf
->vrf
);
357 return zebra_static_route_holdem(
358 zvrf
, nh_zvrf
, afi
, safi
, negate
, &p
, dest_str
,
359 mask_str
, src_str
, gate_str
, ifname
, flag_str
, tag_str
,
360 distance_str
, label_str
, table_str
);
363 /* table configured. check consistent with vrf config
365 if (zvrf
->table_id
!= RT_TABLE_MAIN
&&
366 zvrf
->table_id
!= zebrad
.rtm_table_default
) {
369 "%% Table %s overlaps vrf table %u\n",
370 table_str
, zvrf
->table_id
);
373 "%s: Table %s overlaps vrf table %u",
375 table_str
, zvrf
->table_id
);
376 return CMD_WARNING_CONFIG_FAILED
;
380 /* Administrative distance. */
382 distance
= atoi(distance_str
);
384 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
388 tag
= strtoul(tag_str
, NULL
, 10);
391 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
396 "%% MPLS not turned on in kernel, ignoring command\n");
399 "%s: MPLS not turned on in kernel ignoring static route to %s",
400 __PRETTY_FUNCTION__
, dest_str
);
401 return CMD_WARNING_CONFIG_FAILED
;
403 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
409 vty_out(vty
, "%% Malformed label(s)\n");
412 "%s: Malformed labels specified for route %s",
413 __PRETTY_FUNCTION__
, dest_str
);
418 "%% Cannot use reserved label(s) (%d-%d)\n",
419 MPLS_LABEL_RESERVED_MIN
,
420 MPLS_LABEL_RESERVED_MAX
);
423 "%s: Cannot use reserved labels (%d-%d) for %s",
425 MPLS_LABEL_RESERVED_MIN
,
426 MPLS_LABEL_RESERVED_MAX
,
432 "%% Too many labels. Enter %d or fewer\n",
436 "%s: Too many labels, Enter %d or fewer for %s",
438 MPLS_MAX_LABELS
, dest_str
);
441 return CMD_WARNING_CONFIG_FAILED
;
446 table_id
= atol(table_str
);
448 /* Null0 static route. */
449 if (ifname
!= NULL
) {
450 if (strncasecmp(ifname
, "Null0", strlen(ifname
)) == 0
451 || strncasecmp(ifname
, "reject", strlen(ifname
)) == 0
452 || strncasecmp(ifname
, "blackhole", strlen(ifname
)) == 0) {
455 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
458 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
459 __PRETTY_FUNCTION__
, dest_str
);
460 return CMD_WARNING_CONFIG_FAILED
;
466 switch (flag_str
[0]) {
468 bh_type
= STATIC_BLACKHOLE_REJECT
;
471 bh_type
= STATIC_BLACKHOLE_DROP
;
474 bh_type
= STATIC_BLACKHOLE_NULL
;
478 vty_out(vty
, "%% Malformed flag %s \n",
481 zlog_warn("%s: Malformed flag %s for %s",
482 __PRETTY_FUNCTION__
, flag_str
,
484 return CMD_WARNING_CONFIG_FAILED
;
489 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
492 "%% Malformed nexthop address %s\n",
496 "%s: Malformed nexthop address %s for %s",
497 __PRETTY_FUNCTION__
, gate_str
,
499 return CMD_WARNING_CONFIG_FAILED
;
504 if (gate_str
== NULL
&& ifname
== NULL
)
505 type
= STATIC_BLACKHOLE
;
506 else if (gate_str
&& ifname
) {
508 type
= STATIC_IPV4_GATEWAY_IFNAME
;
510 type
= STATIC_IPV6_GATEWAY_IFNAME
;
512 type
= STATIC_IFNAME
;
515 type
= STATIC_IPV4_GATEWAY
;
517 type
= STATIC_IPV6_GATEWAY
;
521 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
522 bh_type
, tag
, distance
, zvrf
, nh_zvrf
,
523 &snh_label
, table_id
);
524 /* Mark as having FRR configuration */
525 vrf_set_user_cfged(zvrf
->vrf
);
527 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
528 tag
, distance
, zvrf
, &snh_label
, table_id
);
529 /* If no other FRR config for this VRF, mark accordingly. */
530 if (!zebra_vrf_has_config(zvrf
))
531 vrf_reset_user_cfged(zvrf
->vrf
);
537 static struct zebra_vrf
*zebra_vty_get_unknown_vrf(struct vty
*vty
,
538 const char *vrf_name
)
540 struct zebra_vrf
*zvrf
;
543 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
548 vrf
= vrf_get(VRF_UNKNOWN
, vrf_name
);
550 vty_out(vty
, "%% Could not create vrf %s\n", vrf_name
);
555 vty_out(vty
, "%% Could not create vrf-info %s\n",
559 /* Mark as having FRR configuration */
560 vrf_set_user_cfged(vrf
);
565 static int zebra_static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
566 const char *negate
, const char *dest_str
,
567 const char *mask_str
, const char *src_str
,
568 const char *gate_str
, const char *ifname
,
569 const char *flag_str
, const char *tag_str
,
570 const char *distance_str
, const char *vrf_name
,
571 const char *label_str
, const char *table_str
)
573 struct zebra_vrf
*zvrf
;
576 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
578 /* When trying to delete, the VRF must exist. */
579 if (negate
&& !zvrf
) {
580 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
581 return CMD_WARNING_CONFIG_FAILED
;
584 /* When trying to create, create the VRF if it doesn't exist.
585 * Note: The VRF isn't active until we hear about it from the kernel.
588 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf_name
);
590 return CMD_WARNING_CONFIG_FAILED
;
592 return zebra_static_route_leak(
593 vty
, zvrf
, zvrf
, afi
, safi
, negate
, dest_str
, mask_str
, src_str
,
594 gate_str
, ifname
, flag_str
, tag_str
, distance_str
, label_str
,
598 void static_config_install_delayed_routes(struct zebra_vrf
*zvrf
)
600 struct listnode
*node
, *nnode
;
601 struct static_hold_route
*shr
;
602 struct zebra_vrf
*ozvrf
, *nh_zvrf
;
605 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
606 ozvrf
= zebra_vrf_lookup_by_name(shr
->vrf_name
);
607 nh_zvrf
= zebra_vrf_lookup_by_name(shr
->nhvrf_name
);
609 if (ozvrf
!= zvrf
&& nh_zvrf
!= zvrf
)
612 if (ozvrf
->vrf
->vrf_id
== VRF_UNKNOWN
613 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
616 installed
= zebra_static_route_leak(
617 NULL
, ozvrf
, nh_zvrf
, shr
->afi
, shr
->safi
, NULL
,
618 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
619 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
620 shr
->distance_str
, shr
->label_str
, shr
->table_str
);
622 if (installed
!= CMD_SUCCESS
)
624 "%s: Attempt to install %s as a route and it was rejected",
625 __PRETTY_FUNCTION__
, shr
->dest_str
);
626 listnode_delete(static_list
, shr
);
627 static_list_delete(shr
);
630 /* Static unicast routes for multicast RPF lookup. */
631 DEFPY (ip_mroute_dist
,
633 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
636 "Configure static unicast route into MRIB for multicast RPF lookup\n"
637 "IP destination prefix (e.g. 10.0.0.0/8)\n"
639 "Nexthop interface name\n"
642 return zebra_static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
643 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
644 distance_str
, NULL
, NULL
, NULL
);
647 DEFUN (ip_multicast_mode
,
648 ip_multicast_mode_cmd
,
649 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
651 "Multicast options\n"
652 "RPF lookup behavior\n"
653 "Lookup in unicast RIB only\n"
654 "Lookup in multicast RIB only\n"
655 "Try multicast RIB first, fall back to unicast RIB\n"
656 "Lookup both, use entry with lower distance\n"
657 "Lookup both, use entry with longer prefix\n")
659 char *mode
= argv
[3]->text
;
661 if (strmatch(mode
, "urib-only"))
662 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
663 else if (strmatch(mode
, "mrib-only"))
664 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
665 else if (strmatch(mode
, "mrib-then-urib"))
666 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
667 else if (strmatch(mode
, "lower-distance"))
668 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
669 else if (strmatch(mode
, "longer-prefix"))
670 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
672 vty_out(vty
, "Invalid mode specified\n");
673 return CMD_WARNING_CONFIG_FAILED
;
679 DEFUN (no_ip_multicast_mode
,
680 no_ip_multicast_mode_cmd
,
681 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
684 "Multicast options\n"
685 "RPF lookup behavior\n"
686 "Lookup in unicast RIB only\n"
687 "Lookup in multicast RIB only\n"
688 "Try multicast RIB first, fall back to unicast RIB\n"
689 "Lookup both, use entry with lower distance\n"
690 "Lookup both, use entry with longer prefix\n")
692 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
699 "show ip rpf [json]",
702 "Display RPF information for multicast source\n"
705 int uj
= use_json(argc
, argv
);
706 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
707 false, uj
, 0, NULL
, false, 0, 0);
710 DEFUN (show_ip_rpf_addr
,
711 show_ip_rpf_addr_cmd
,
712 "show ip rpf A.B.C.D",
715 "Display RPF information for multicast source\n"
716 "IP multicast source address (e.g. 10.0.0.0)\n")
720 struct route_node
*rn
;
721 struct route_entry
*re
;
724 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
726 vty_out(vty
, "%% Malformed address\n");
730 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
733 vty_show_ip_route_detail(vty
, rn
, 1);
735 vty_out(vty
, "%% No match for RPF lookup\n");
740 /* Static route configuration. */
741 DEFPY(ip_route_blackhole
,
742 ip_route_blackhole_cmd
,
744 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
745 <reject|blackhole>$flag \
751 |table (1-4294967295) \
754 "Establish static routes\n"
755 "IP destination prefix (e.g. 10.0.0.0/8)\n"
756 "IP destination prefix\n"
757 "IP destination prefix mask\n"
758 "Emit an ICMP unreachable when matched\n"
759 "Silently discard pkts when matched\n"
760 "Set tag for this route\n"
762 "Distance value for this route\n"
765 "Table to configure\n"
766 "The table number to configure\n")
768 if (table_str
&& !vrf_is_backend_netns()) {
770 "%% table param only available when running on netns-based vrfs\n");
771 return CMD_WARNING_CONFIG_FAILED
;
773 return zebra_static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
774 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
775 distance_str
, vrf
, label
, table_str
);
778 DEFPY(ip_route_blackhole_vrf
,
779 ip_route_blackhole_vrf_cmd
,
781 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
782 <reject|blackhole>$flag \
787 |table (1-4294967295) \
790 "Establish static routes\n"
791 "IP destination prefix (e.g. 10.0.0.0/8)\n"
792 "IP destination prefix\n"
793 "IP destination prefix mask\n"
794 "Emit an ICMP unreachable when matched\n"
795 "Silently discard pkts when matched\n"
796 "Set tag for this route\n"
798 "Distance value for this route\n"
800 "Table to configure\n"
801 "The table number to configure\n")
803 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
804 struct zebra_vrf
*zvrf
= vrf
->info
;
806 if (table_str
&& !vrf_is_backend_netns()) {
808 "%% table param only available when running on netns-based vrfs\n");
809 return CMD_WARNING_CONFIG_FAILED
;
812 * Coverity is complaining that prefix could
813 * be dereferenced, but we know that prefix will
814 * valid. Add an assert to make it happy
817 return zebra_static_route_leak(vty
, zvrf
, zvrf
, AFI_IP
, SAFI_UNICAST
,
818 no
, prefix
, mask_str
, NULL
, NULL
, NULL
,
819 flag
, tag_str
, distance_str
, label
, table_str
);
822 DEFPY(ip_route_address_interface
,
823 ip_route_address_interface_cmd
,
825 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
833 |table (1-4294967295) \
837 "Establish static routes\n"
838 "IP destination prefix (e.g. 10.0.0.0/8)\n"
839 "IP destination prefix\n"
840 "IP destination prefix mask\n"
841 "IP gateway address\n"
842 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
844 "Set tag for this route\n"
846 "Distance value for this route\n"
849 "Table to configure\n"
850 "The table number to configure\n"
853 struct zebra_vrf
*zvrf
;
854 struct zebra_vrf
*nh_zvrf
;
856 const char *flag
= NULL
;
857 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
862 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
864 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
865 return CMD_WARNING_CONFIG_FAILED
;
868 if (table_str
&& !vrf_is_backend_netns()) {
870 "%% table param only available when running on netns-based vrfs\n");
871 return CMD_WARNING_CONFIG_FAILED
;
875 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
880 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
881 return CMD_WARNING_CONFIG_FAILED
;
884 return zebra_static_route_leak(
885 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
886 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
890 DEFPY(ip_route_address_interface_vrf
,
891 ip_route_address_interface_vrf_cmd
,
893 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
900 |table (1-4294967295) \
904 "Establish static routes\n"
905 "IP destination prefix (e.g. 10.0.0.0/8)\n"
906 "IP destination prefix\n"
907 "IP destination prefix mask\n"
908 "IP gateway address\n"
909 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
911 "Set tag for this route\n"
913 "Distance value for this route\n"
915 "Table to configure\n"
916 "The table number to configure\n"
919 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
920 const char *flag
= NULL
;
921 struct zebra_vrf
*zvrf
= vrf
->info
;
922 struct zebra_vrf
*nh_zvrf
;
924 if (table_str
&& !vrf_is_backend_netns()) {
926 "%% table param only available when running on netns-based vrfs\n");
927 return CMD_WARNING_CONFIG_FAILED
;
930 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
936 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
941 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
942 return CMD_WARNING_CONFIG_FAILED
;
945 return zebra_static_route_leak(
946 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
947 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
954 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
955 <A.B.C.D$gate|INTERFACE$ifname> \
961 |table (1-4294967295) \
965 "Establish static routes\n"
966 "IP destination prefix (e.g. 10.0.0.0/8)\n"
967 "IP destination prefix\n"
968 "IP destination prefix mask\n"
969 "IP gateway address\n"
970 "IP gateway interface name\n"
971 "Set tag for this route\n"
973 "Distance value for this route\n"
976 "Table to configure\n"
977 "The table number to configure\n"
980 struct zebra_vrf
*zvrf
;
981 struct zebra_vrf
*nh_zvrf
;
982 const char *flag
= NULL
;
984 if (table_str
&& !vrf_is_backend_netns()) {
986 "%% table param only available when running on netns-based vrfs\n");
987 return CMD_WARNING_CONFIG_FAILED
;
990 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
995 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
997 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
998 return CMD_WARNING_CONFIG_FAILED
;
1002 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1007 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1008 return CMD_WARNING_CONFIG_FAILED
;
1012 return zebra_static_route_leak(
1013 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1014 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1021 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1022 <A.B.C.D$gate|INTERFACE$ifname> \
1024 tag (1-4294967295) \
1027 |table (1-4294967295) \
1031 "Establish static routes\n"
1032 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1033 "IP destination prefix\n"
1034 "IP destination prefix mask\n"
1035 "IP gateway address\n"
1036 "IP gateway interface name\n"
1037 "Set tag for this route\n"
1039 "Distance value for this route\n"
1041 "Table to configure\n"
1042 "The table number to configure\n"
1045 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1046 struct zebra_vrf
*zvrf
= vrf
->info
;
1047 struct zebra_vrf
*nh_zvrf
;
1048 const char *flag
= NULL
;
1050 if (table_str
&& !vrf_is_backend_netns()) {
1052 "%% table param only available when running on netns-based vrfs\n");
1053 return CMD_WARNING_CONFIG_FAILED
;
1056 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1062 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1067 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1068 return CMD_WARNING_CONFIG_FAILED
;
1071 return zebra_static_route_leak(
1072 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1073 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1077 /* New RIB. Detailed information for IPv4 route. */
1078 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
1081 struct route_entry
*re
;
1082 struct nexthop
*nexthop
;
1083 char buf
[SRCDEST2STR_BUFFER
];
1084 struct zebra_vrf
*zvrf
;
1086 RNODE_FOREACH_RE (rn
, re
) {
1087 const char *mcast_info
= "";
1089 rib_table_info_t
*info
= srcdest_rnode_table_info(rn
);
1090 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
1091 ? " using Multicast RIB"
1092 : " using Unicast RIB";
1095 vty_out(vty
, "Routing entry for %s%s\n",
1096 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
1097 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
1099 vty_out(vty
, "[%d]", re
->instance
);
1101 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
1104 vty_out(vty
, ", tag %u", re
->tag
);
1105 #if defined(SUPPORT_REALMS)
1106 if (re
->tag
> 0 && re
->tag
<= 255)
1107 vty_out(vty
, "(realm)");
1111 vty_out(vty
, ", mtu %u", re
->mtu
);
1112 if (re
->vrf_id
!= VRF_DEFAULT
) {
1113 zvrf
= vrf_info_lookup(re
->vrf_id
);
1114 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
1116 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1117 vty_out(vty
, ", best");
1123 uptime
= time(NULL
);
1124 uptime
-= re
->uptime
;
1125 tm
= gmtime(&uptime
);
1127 vty_out(vty
, " Last update ");
1129 if (uptime
< ONE_DAY_SECOND
)
1130 vty_out(vty
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1132 else if (uptime
< ONE_WEEK_SECOND
)
1133 vty_out(vty
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1136 vty_out(vty
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1137 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1139 vty_out(vty
, " ago\n");
1141 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1144 vty_out(vty
, " %c%s",
1145 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1146 ? CHECK_FLAG(nexthop
->flags
,
1147 NEXTHOP_FLAG_DUPLICATE
)
1151 nexthop
->rparent
? " " : "");
1153 switch (nexthop
->type
) {
1154 case NEXTHOP_TYPE_IPV4
:
1155 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1157 inet_ntoa(nexthop
->gate
.ipv4
));
1158 if (nexthop
->ifindex
)
1159 vty_out(vty
, ", via %s",
1164 case NEXTHOP_TYPE_IPV6
:
1165 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1167 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1169 if (nexthop
->ifindex
)
1170 vty_out(vty
, ", via %s",
1175 case NEXTHOP_TYPE_IFINDEX
:
1176 vty_out(vty
, " directly connected, %s",
1177 ifindex2ifname(nexthop
->ifindex
,
1180 case NEXTHOP_TYPE_BLACKHOLE
:
1181 vty_out(vty
, " unreachable");
1182 switch (nexthop
->bh_type
) {
1183 case BLACKHOLE_REJECT
:
1184 vty_out(vty
, " (ICMP unreachable)");
1186 case BLACKHOLE_ADMINPROHIB
:
1188 " (ICMP admin-prohibited)");
1190 case BLACKHOLE_NULL
:
1191 vty_out(vty
, " (blackhole)");
1193 case BLACKHOLE_UNSPEC
:
1201 if ((re
->vrf_id
!= nexthop
->vrf_id
)
1202 && (nexthop
->type
!= NEXTHOP_TYPE_BLACKHOLE
)) {
1204 vrf_lookup_by_id(nexthop
->vrf_id
);
1207 vty_out(vty
, "(vrf %s)", vrf
->name
);
1209 vty_out(vty
, "(vrf UKNOWN)");
1212 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1213 vty_out(vty
, " (duplicate nexthop removed)");
1215 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1216 vty_out(vty
, " inactive");
1218 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1219 vty_out(vty
, " onlink");
1221 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1222 vty_out(vty
, " (recursive)");
1224 switch (nexthop
->type
) {
1225 case NEXTHOP_TYPE_IPV4
:
1226 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1227 if (nexthop
->src
.ipv4
.s_addr
) {
1228 if (inet_ntop(AF_INET
,
1230 addrstr
, sizeof addrstr
))
1231 vty_out(vty
, ", src %s",
1235 case NEXTHOP_TYPE_IPV6
:
1236 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1237 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1239 if (inet_ntop(AF_INET6
,
1241 addrstr
, sizeof addrstr
))
1242 vty_out(vty
, ", src %s",
1250 if (re
->nexthop_mtu
)
1251 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
1253 /* Label information */
1254 if (nexthop
->nh_label
1255 && nexthop
->nh_label
->num_labels
) {
1256 vty_out(vty
, ", label %s",
1258 nexthop
->nh_label
->num_labels
,
1259 nexthop
->nh_label
->label
, buf
,
1269 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
1270 struct route_entry
*re
, json_object
*json
)
1272 struct nexthop
*nexthop
;
1274 char buf
[SRCDEST2STR_BUFFER
];
1275 json_object
*json_nexthops
= NULL
;
1276 json_object
*json_nexthop
= NULL
;
1277 json_object
*json_route
= NULL
;
1278 json_object
*json_labels
= NULL
;
1282 uptime
= time(NULL
);
1283 uptime
-= re
->uptime
;
1284 tm
= gmtime(&uptime
);
1287 json_route
= json_object_new_object();
1288 json_nexthops
= json_object_new_array();
1290 json_object_string_add(json_route
, "prefix",
1291 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1292 json_object_string_add(json_route
, "protocol",
1293 zebra_route_string(re
->type
));
1296 json_object_int_add(json_route
, "instance",
1300 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
1302 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1303 json_object_boolean_true_add(json_route
, "selected");
1305 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
1306 json_object_int_add(json_route
, "distance",
1308 json_object_int_add(json_route
, "metric", re
->metric
);
1311 json_object_int_add(json_route
, "internalStatus",
1313 json_object_int_add(json_route
, "internalFlags",
1315 if (uptime
< ONE_DAY_SECOND
)
1316 sprintf(buf
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1318 else if (uptime
< ONE_WEEK_SECOND
)
1319 sprintf(buf
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1322 sprintf(buf
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1323 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1326 json_object_string_add(json_route
, "uptime", buf
);
1328 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1329 json_nexthop
= json_object_new_object();
1331 json_object_int_add(json_nexthop
, "flags",
1334 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1335 json_object_boolean_true_add(json_nexthop
,
1338 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1339 json_object_boolean_true_add(json_nexthop
,
1342 switch (nexthop
->type
) {
1343 case NEXTHOP_TYPE_IPV4
:
1344 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1345 json_object_string_add(
1347 inet_ntoa(nexthop
->gate
.ipv4
));
1348 json_object_string_add(json_nexthop
, "afi",
1351 if (nexthop
->ifindex
) {
1352 json_object_int_add(json_nexthop
,
1355 json_object_string_add(
1356 json_nexthop
, "interfaceName",
1362 case NEXTHOP_TYPE_IPV6
:
1363 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1364 json_object_string_add(
1366 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1368 json_object_string_add(json_nexthop
, "afi",
1371 if (nexthop
->ifindex
) {
1372 json_object_int_add(json_nexthop
,
1375 json_object_string_add(
1376 json_nexthop
, "interfaceName",
1383 case NEXTHOP_TYPE_IFINDEX
:
1384 json_object_boolean_true_add(
1385 json_nexthop
, "directlyConnected");
1386 json_object_int_add(json_nexthop
,
1389 json_object_string_add(
1390 json_nexthop
, "interfaceName",
1391 ifindex2ifname(nexthop
->ifindex
,
1394 case NEXTHOP_TYPE_BLACKHOLE
:
1395 json_object_boolean_true_add(json_nexthop
,
1397 switch (nexthop
->bh_type
) {
1398 case BLACKHOLE_REJECT
:
1399 json_object_boolean_true_add(
1400 json_nexthop
, "reject");
1402 case BLACKHOLE_ADMINPROHIB
:
1403 json_object_boolean_true_add(
1405 "admin-prohibited");
1407 case BLACKHOLE_NULL
:
1408 json_object_boolean_true_add(
1409 json_nexthop
, "blackhole");
1411 case BLACKHOLE_UNSPEC
:
1419 if ((nexthop
->vrf_id
!= re
->vrf_id
)
1420 && (nexthop
->type
!= NEXTHOP_TYPE_BLACKHOLE
)) {
1422 vrf_lookup_by_id(nexthop
->vrf_id
);
1424 json_object_string_add(json_nexthop
, "vrf",
1427 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1428 json_object_boolean_true_add(json_nexthop
,
1431 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1432 json_object_boolean_true_add(json_nexthop
,
1435 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1436 json_object_boolean_true_add(json_nexthop
,
1439 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1440 json_object_boolean_true_add(json_nexthop
,
1443 switch (nexthop
->type
) {
1444 case NEXTHOP_TYPE_IPV4
:
1445 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1446 if (nexthop
->src
.ipv4
.s_addr
) {
1447 if (inet_ntop(AF_INET
,
1448 &nexthop
->src
.ipv4
, buf
,
1450 json_object_string_add(
1451 json_nexthop
, "source",
1455 case NEXTHOP_TYPE_IPV6
:
1456 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1457 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1459 if (inet_ntop(AF_INET6
,
1460 &nexthop
->src
.ipv6
, buf
,
1462 json_object_string_add(
1463 json_nexthop
, "source",
1471 if (nexthop
->nh_label
1472 && nexthop
->nh_label
->num_labels
) {
1473 json_labels
= json_object_new_array();
1475 for (int label_index
= 0;
1477 < nexthop
->nh_label
->num_labels
;
1479 json_object_array_add(
1481 json_object_new_int(
1482 nexthop
->nh_label
->label
1485 json_object_object_add(json_nexthop
, "labels",
1489 json_object_array_add(json_nexthops
, json_nexthop
);
1492 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1493 json_object_array_add(json
, json_route
);
1497 /* Nexthop information. */
1498 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1499 if (nexthop
== re
->ng
.nexthop
) {
1500 /* Prefix information. */
1501 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1503 len
+= vty_out(vty
, "[%d]", re
->instance
);
1506 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)
1509 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1512 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1514 /* Distance and metric display. */
1515 if (re
->type
!= ZEBRA_ROUTE_CONNECT
)
1516 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1519 vty_out(vty
, " %c%*c",
1520 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1521 ? CHECK_FLAG(nexthop
->flags
,
1522 NEXTHOP_FLAG_DUPLICATE
)
1526 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1529 switch (nexthop
->type
) {
1530 case NEXTHOP_TYPE_IPV4
:
1531 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1532 vty_out(vty
, " via %s", inet_ntoa(nexthop
->gate
.ipv4
));
1533 if (nexthop
->ifindex
)
1534 vty_out(vty
, ", %s",
1535 ifindex2ifname(nexthop
->ifindex
,
1538 case NEXTHOP_TYPE_IPV6
:
1539 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1540 vty_out(vty
, " via %s",
1541 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
1543 if (nexthop
->ifindex
)
1544 vty_out(vty
, ", %s",
1545 ifindex2ifname(nexthop
->ifindex
,
1549 case NEXTHOP_TYPE_IFINDEX
:
1550 vty_out(vty
, " is directly connected, %s",
1551 ifindex2ifname(nexthop
->ifindex
,
1554 case NEXTHOP_TYPE_BLACKHOLE
:
1555 vty_out(vty
, " unreachable");
1556 switch (nexthop
->bh_type
) {
1557 case BLACKHOLE_REJECT
:
1558 vty_out(vty
, " (ICMP unreachable)");
1560 case BLACKHOLE_ADMINPROHIB
:
1561 vty_out(vty
, " (ICMP admin-prohibited)");
1563 case BLACKHOLE_NULL
:
1564 vty_out(vty
, " (blackhole)");
1566 case BLACKHOLE_UNSPEC
:
1574 if ((nexthop
->vrf_id
!= re
->vrf_id
)
1575 && (nexthop
->type
!= NEXTHOP_TYPE_BLACKHOLE
)) {
1576 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
1579 vty_out(vty
, "(vrf %s)", vrf
->name
);
1581 vty_out(vty
, "(vrf UKNOWN)");
1584 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1585 vty_out(vty
, " inactive");
1587 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1588 vty_out(vty
, " onlink");
1590 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1591 vty_out(vty
, " (recursive)");
1593 switch (nexthop
->type
) {
1594 case NEXTHOP_TYPE_IPV4
:
1595 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1596 if (nexthop
->src
.ipv4
.s_addr
) {
1597 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
1599 vty_out(vty
, ", src %s", buf
);
1602 case NEXTHOP_TYPE_IPV6
:
1603 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1604 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
1605 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
1607 vty_out(vty
, ", src %s", buf
);
1614 /* Label information */
1615 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
1616 vty_out(vty
, ", label %s",
1617 mpls_label2str(nexthop
->nh_label
->num_labels
,
1618 nexthop
->nh_label
->label
, buf
,
1622 if (uptime
< ONE_DAY_SECOND
)
1623 vty_out(vty
, ", %02d:%02d:%02d", tm
->tm_hour
,
1624 tm
->tm_min
, tm
->tm_sec
);
1625 else if (uptime
< ONE_WEEK_SECOND
)
1626 vty_out(vty
, ", %dd%02dh%02dm", tm
->tm_yday
,
1627 tm
->tm_hour
, tm
->tm_min
);
1629 vty_out(vty
, ", %02dw%dd%02dh", tm
->tm_yday
/ 7,
1630 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1636 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1637 struct route_table
*table
, afi_t afi
,
1638 bool use_fib
, route_tag_t tag
,
1639 const struct prefix
*longer_prefix_p
,
1640 bool supernets_only
, int type
,
1641 unsigned short ospf_instance_id
,
1644 struct route_node
*rn
;
1645 struct route_entry
*re
;
1648 json_object
*json
= NULL
;
1649 json_object
*json_prefix
= NULL
;
1654 json
= json_object_new_object();
1656 /* Show all routes. */
1657 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
1658 dest
= rib_dest_from_rnode(rn
);
1660 RNODE_FOREACH_RE (rn
, re
) {
1661 if (use_fib
&& re
!= dest
->selected_fib
)
1664 if (tag
&& re
->tag
!= tag
)
1668 && !prefix_match(longer_prefix_p
, &rn
->p
))
1671 /* This can only be true when the afi is IPv4 */
1672 if (supernets_only
) {
1673 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1675 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1678 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1681 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1685 if (type
&& re
->type
!= type
)
1688 if (ospf_instance_id
1689 && (re
->type
!= ZEBRA_ROUTE_OSPF
1690 || re
->instance
!= ospf_instance_id
))
1695 json_prefix
= json_object_new_array();
1700 SHOW_ROUTE_V4_HEADER
);
1703 SHOW_ROUTE_V6_HEADER
);
1705 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1706 vty_out(vty
, "\nVRF %s:\n",
1713 vty_show_ip_route(vty
, rn
, re
, json_prefix
);
1717 prefix2str(&rn
->p
, buf
, sizeof buf
);
1718 json_object_object_add(json
, buf
, json_prefix
);
1724 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1725 json
, JSON_C_TO_STRING_PRETTY
));
1726 json_object_free(json
);
1730 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1731 safi_t safi
, bool use_fib
, uint8_t use_json
,
1733 const struct prefix
*longer_prefix_p
,
1734 bool supernets_only
, int type
,
1735 unsigned short ospf_instance_id
)
1737 struct route_table
*table
;
1738 struct zebra_vrf
*zvrf
= NULL
;
1740 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1742 vty_out(vty
, "{}\n");
1744 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1748 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1750 vty_out(vty
, "{}\n");
1752 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1756 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1759 vty_out(vty
, "{}\n");
1763 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1764 longer_prefix_p
, supernets_only
, type
,
1765 ospf_instance_id
, use_json
);
1770 DEFPY (show_route_table
,
1771 show_route_table_cmd
,
1772 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1776 "IP routing table\n"
1777 "Table to display\n"
1778 "The table number to display, if available\n"
1781 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1782 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1783 struct route_table
*t
;
1785 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1787 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1793 DEFPY (show_route_table_vrf
,
1794 show_route_table_vrf_cmd
,
1795 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
1799 "IP routing table\n"
1800 "Table to display\n"
1801 "The table number to display, if available\n"
1805 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1806 struct zebra_vrf
*zvrf
;
1807 struct route_table
*t
;
1808 vrf_id_t vrf_id
= VRF_DEFAULT
;
1811 VRF_GET_ID(vrf_id
, vrf_name
);
1812 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
1814 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1816 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1824 "show ip nht [vrf NAME]",
1827 "IP nexthop tracking table\n"
1831 vrf_id_t vrf_id
= VRF_DEFAULT
;
1834 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1836 zebra_print_rnh_table(vrf_id
, AF_INET
, vty
, RNH_NEXTHOP_TYPE
);
1841 DEFUN (show_ip_nht_vrf_all
,
1842 show_ip_nht_vrf_all_cmd
,
1843 "show ip nht vrf all",
1846 "IP nexthop tracking table\n"
1847 VRF_ALL_CMD_HELP_STR
)
1850 struct zebra_vrf
*zvrf
;
1852 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1853 if ((zvrf
= vrf
->info
) != NULL
) {
1854 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1855 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET
, vty
,
1862 DEFUN (show_ipv6_nht
,
1864 "show ipv6 nht [vrf NAME]",
1867 "IPv6 nexthop tracking table\n"
1871 vrf_id_t vrf_id
= VRF_DEFAULT
;
1874 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1876 zebra_print_rnh_table(vrf_id
, AF_INET6
, vty
, RNH_NEXTHOP_TYPE
);
1881 DEFUN (show_ipv6_nht_vrf_all
,
1882 show_ipv6_nht_vrf_all_cmd
,
1883 "show ipv6 nht vrf all",
1886 "IPv6 nexthop tracking table\n"
1887 VRF_ALL_CMD_HELP_STR
)
1890 struct zebra_vrf
*zvrf
;
1892 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1893 if ((zvrf
= vrf
->info
) != NULL
) {
1894 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1895 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET6
, vty
,
1902 DEFUN (ip_nht_default_route
,
1903 ip_nht_default_route_cmd
,
1904 "ip nht resolve-via-default",
1906 "Filter Next Hop tracking route resolution\n"
1907 "Resolve via default route\n")
1909 if (zebra_rnh_ip_default_route
)
1912 zebra_rnh_ip_default_route
= 1;
1913 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1917 DEFUN (no_ip_nht_default_route
,
1918 no_ip_nht_default_route_cmd
,
1919 "no ip nht resolve-via-default",
1922 "Filter Next Hop tracking route resolution\n"
1923 "Resolve via default route\n")
1925 if (!zebra_rnh_ip_default_route
)
1928 zebra_rnh_ip_default_route
= 0;
1929 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1933 DEFUN (ipv6_nht_default_route
,
1934 ipv6_nht_default_route_cmd
,
1935 "ipv6 nht resolve-via-default",
1937 "Filter Next Hop tracking route resolution\n"
1938 "Resolve via default route\n")
1940 if (zebra_rnh_ipv6_default_route
)
1943 zebra_rnh_ipv6_default_route
= 1;
1944 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1948 DEFUN (no_ipv6_nht_default_route
,
1949 no_ipv6_nht_default_route_cmd
,
1950 "no ipv6 nht resolve-via-default",
1953 "Filter Next Hop tracking route resolution\n"
1954 "Resolve via default route\n")
1956 if (!zebra_rnh_ipv6_default_route
)
1959 zebra_rnh_ipv6_default_route
= 0;
1960 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1968 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1971 |A.B.C.D/M$prefix longer-prefixes\
1972 |supernets-only$supernets_only\
1975 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1976 |ospf$type_str (1-65535)$ospf_instance_id\
1978 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1981 |X:X::X:X/M$prefix longer-prefixes\
1983 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1988 "IP forwarding table\n"
1989 "IP routing table\n"
1990 VRF_FULL_CMD_HELP_STR
1991 "Show only routes with tag\n"
1993 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1994 "Show route matching the specified Network/Mask pair only\n"
1995 "Show supernet entries only\n"
1996 FRR_IP_REDIST_HELP_STR_ZEBRA
1997 "Open Shortest Path First (OSPFv2)\n"
2000 "IP forwarding table\n"
2001 "IP routing table\n"
2002 VRF_FULL_CMD_HELP_STR
2003 "Show only routes with tag\n"
2006 "Show route matching the specified Network/Mask pair only\n"
2007 FRR_IP6_REDIST_HELP_STR_ZEBRA
2010 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2015 type
= proto_redistnum(afi
, type_str
);
2017 vty_out(vty
, "Unknown route type\n");
2023 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2024 struct zebra_vrf
*zvrf
;
2025 struct route_table
*table
;
2027 if ((zvrf
= vrf
->info
) == NULL
2028 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2032 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
, !!fib
,
2033 !!json
, tag
, prefix_str
? prefix
: NULL
,
2034 !!supernets_only
, type
, ospf_instance_id
);
2037 vrf_id_t vrf_id
= VRF_DEFAULT
;
2040 VRF_GET_ID(vrf_id
, vrf_name
);
2041 vrf
= vrf_lookup_by_id(vrf_id
);
2042 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
, !!fib
,
2043 !!json
, tag
, prefix_str
? prefix
: NULL
,
2044 !!supernets_only
, type
, ospf_instance_id
);
2050 DEFPY (show_route_detail
,
2051 show_route_detail_cmd
,
2054 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2059 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2067 "IP routing table\n"
2068 VRF_FULL_CMD_HELP_STR
2069 "Network in the IP routing table to display\n"
2070 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2072 "IP routing table\n"
2073 VRF_FULL_CMD_HELP_STR
2077 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2078 struct route_table
*table
;
2080 struct route_node
*rn
;
2083 prefix_str
= address_str
;
2084 if (str2prefix(prefix_str
, &p
) < 0) {
2085 vty_out(vty
, "%% Malformed address\n");
2091 struct zebra_vrf
*zvrf
;
2093 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2094 if ((zvrf
= vrf
->info
) == NULL
2095 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2098 rn
= route_node_match(table
, &p
);
2101 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2102 route_unlock_node(rn
);
2106 vty_show_ip_route_detail(vty
, rn
, 0);
2108 route_unlock_node(rn
);
2111 vrf_id_t vrf_id
= VRF_DEFAULT
;
2114 VRF_GET_ID(vrf_id
, vrf_name
);
2116 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2120 rn
= route_node_match(table
, &p
);
2122 vty_out(vty
, "%% Network not in table\n");
2125 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2126 vty_out(vty
, "%% Network not in table\n");
2127 route_unlock_node(rn
);
2131 vty_show_ip_route_detail(vty
, rn
, 0);
2133 route_unlock_node(rn
);
2139 DEFPY (show_route_summary
,
2140 show_route_summary_cmd
,
2143 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2144 summary [prefix$prefix]\
2145 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2146 summary [prefix$prefix]\
2150 "IP routing table\n"
2151 VRF_FULL_CMD_HELP_STR
2152 "Summary of all routes\n"
2155 "IP routing table\n"
2156 VRF_FULL_CMD_HELP_STR
2157 "Summary of all routes\n"
2160 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2161 struct route_table
*table
;
2165 struct zebra_vrf
*zvrf
;
2167 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2168 if ((zvrf
= vrf
->info
) == NULL
2169 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2173 vty_show_ip_route_summary_prefix(vty
, table
);
2175 vty_show_ip_route_summary(vty
, table
);
2178 vrf_id_t vrf_id
= VRF_DEFAULT
;
2181 VRF_GET_ID(vrf_id
, vrf_name
);
2183 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2188 vty_show_ip_route_summary_prefix(vty
, table
);
2190 vty_show_ip_route_summary(vty
, table
);
2196 static void vty_show_ip_route_summary(struct vty
*vty
,
2197 struct route_table
*table
)
2199 struct route_node
*rn
;
2200 struct route_entry
*re
;
2201 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2202 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2203 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2204 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2208 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2209 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2210 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2211 RNODE_FOREACH_RE (rn
, re
) {
2212 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2213 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2215 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2217 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2219 rib_cnt
[re
->type
]++;
2221 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)) {
2222 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2225 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2227 fib_cnt
[re
->type
]++;
2231 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2232 "FIB", zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2234 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2235 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2236 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2237 if (i
== ZEBRA_ROUTE_BGP
) {
2238 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2239 rib_cnt
[ZEBRA_ROUTE_BGP
],
2240 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2241 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2242 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2243 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2245 vty_out(vty
, "%-20s %-20d %-20d \n",
2246 zebra_route_string(i
), rib_cnt
[i
],
2251 vty_out(vty
, "------\n");
2252 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2253 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2258 * Implementation of the ip route summary prefix command.
2260 * This command prints the primary prefixes that have been installed by various
2261 * protocols on the box.
2264 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2265 struct route_table
*table
)
2267 struct route_node
*rn
;
2268 struct route_entry
*re
;
2269 struct nexthop
*nexthop
;
2270 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2271 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2272 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2273 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2277 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2278 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2279 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2280 RNODE_FOREACH_RE (rn
, re
) {
2283 * In case of ECMP, count only once.
2286 for (nexthop
= re
->ng
.nexthop
; (!cnt
&& nexthop
);
2287 nexthop
= nexthop
->next
) {
2289 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2290 rib_cnt
[re
->type
]++;
2291 if (CHECK_FLAG(nexthop
->flags
,
2292 NEXTHOP_FLAG_FIB
)) {
2293 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2294 fib_cnt
[re
->type
]++;
2296 if (re
->type
== ZEBRA_ROUTE_BGP
2297 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2298 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2299 if (CHECK_FLAG(nexthop
->flags
,
2301 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2306 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2307 "Prefix Routes", "FIB",
2308 zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2310 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2311 if (rib_cnt
[i
] > 0) {
2312 if (i
== ZEBRA_ROUTE_BGP
) {
2313 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2314 rib_cnt
[ZEBRA_ROUTE_BGP
]
2315 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2316 fib_cnt
[ZEBRA_ROUTE_BGP
]
2317 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2318 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2319 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2320 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2322 vty_out(vty
, "%-20s %-20d %-20d \n",
2323 zebra_route_string(i
), rib_cnt
[i
],
2328 vty_out(vty
, "------\n");
2329 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2330 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2334 /* Write static route configuration. */
2335 int static_config(struct vty
*vty
, struct zebra_vrf
*zvrf
, afi_t afi
,
2336 safi_t safi
, const char *cmd
)
2338 struct static_hold_route
*shr
;
2339 struct listnode
*node
;
2341 struct route_node
*rn
;
2342 struct static_route
*si
;
2343 struct route_table
*stable
;
2344 char buf
[SRCDEST2STR_BUFFER
];
2347 if ((stable
= zvrf
->stable
[afi
][safi
]) == NULL
)
2350 sprintf(spacing
, "%s%s", (zvrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
2354 * Static routes for vrfs not fully inited
2356 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
2357 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
2360 if (strcmp(zvrf
->vrf
->name
, shr
->vrf_name
) != 0)
2363 char dest_str
[PREFIX_STRLEN
];
2365 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
2367 vty_out(vty
, "%s ", spacing
);
2369 vty_out(vty
, "%s ", dest_str
);
2371 vty_out(vty
, "from %s ", shr
->src_str
);
2373 vty_out(vty
, "%s ", shr
->gate_str
);
2375 vty_out(vty
, "%s ", shr
->ifname
);
2377 vty_out(vty
, "%s ", shr
->flag_str
);
2379 vty_out(vty
, "tag %s ", shr
->tag_str
);
2380 if (shr
->distance_str
)
2381 vty_out(vty
, "%s ", shr
->distance_str
);
2383 vty_out(vty
, "label %s ", shr
->label_str
);
2385 vty_out(vty
, "table %s ", shr
->table_str
);
2386 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
2387 vty_out(vty
, "nexthop-vrf %s", shr
->nhvrf_name
);
2391 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
2392 for (si
= rn
->info
; si
; si
= si
->next
) {
2393 vty_out(vty
, "%s %s", spacing
,
2394 srcdest_rnode2str(rn
, buf
, sizeof buf
));
2397 case STATIC_IPV4_GATEWAY
:
2398 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
2400 case STATIC_IPV6_GATEWAY
:
2402 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2406 vty_out(vty
, " %s", si
->ifname
);
2408 case STATIC_BLACKHOLE
:
2409 switch (si
->bh_type
) {
2410 case STATIC_BLACKHOLE_DROP
:
2411 vty_out(vty
, " blackhole");
2413 case STATIC_BLACKHOLE_NULL
:
2414 vty_out(vty
, " Null0");
2416 case STATIC_BLACKHOLE_REJECT
:
2417 vty_out(vty
, " reject");
2421 case STATIC_IPV4_GATEWAY_IFNAME
:
2422 vty_out(vty
, " %s %s",
2423 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
2427 case STATIC_IPV6_GATEWAY_IFNAME
:
2428 vty_out(vty
, " %s %s",
2429 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2436 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
2438 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
2439 vty_out(vty
, " %d", si
->distance
);
2441 /* Label information */
2442 if (si
->snh_label
.num_labels
)
2443 vty_out(vty
, " label %s",
2444 mpls_label2str(si
->snh_label
.num_labels
,
2445 si
->snh_label
.label
, buf
,
2448 if (si
->nh_vrf_id
!= si
->vrf_id
) {
2449 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
2452 /* table ID from VRF overrides configured
2454 if (si
->table_id
&& zvrf
->table_id
== RT_TABLE_MAIN
)
2455 vty_out(vty
, " table %u", si
->table_id
);
2464 DEFPY(ipv6_route_blackhole
,
2465 ipv6_route_blackhole_cmd
,
2466 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2467 <Null0|reject|blackhole>$flag \
2469 tag (1-4294967295) \
2473 |table (1-4294967295) \
2477 "Establish static routes\n"
2478 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2479 "IPv6 source-dest route\n"
2480 "IPv6 source prefix\n"
2482 "Emit an ICMP unreachable when matched\n"
2483 "Silently discard pkts when matched\n"
2484 "Set tag for this route\n"
2486 "Distance value for this prefix\n"
2489 "Table to configure\n"
2490 "The table number to configure\n")
2492 if (table_str
&& !vrf_is_backend_netns()) {
2494 "%% table param only available when running on netns-based vrfs\n");
2495 return CMD_WARNING_CONFIG_FAILED
;
2498 return zebra_static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
2499 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
2500 distance_str
, vrf
, label
, table_str
);
2503 DEFPY(ipv6_route_blackhole_vrf
,
2504 ipv6_route_blackhole_vrf_cmd
,
2505 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2506 <Null0|reject|blackhole>$flag \
2508 tag (1-4294967295) \
2511 |table (1-4294967295) \
2515 "Establish static routes\n"
2516 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2517 "IPv6 source-dest route\n"
2518 "IPv6 source prefix\n"
2520 "Emit an ICMP unreachable when matched\n"
2521 "Silently discard pkts when matched\n"
2522 "Set tag for this route\n"
2524 "Distance value for this prefix\n"
2526 "Table to configure\n"
2527 "The table number to configure\n")
2529 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2530 struct zebra_vrf
*zvrf
= vrf
->info
;
2532 if (table_str
&& !vrf_is_backend_netns()) {
2534 "%% table param only available when running on netns-based vrfs\n");
2535 return CMD_WARNING_CONFIG_FAILED
;
2538 * Coverity is complaining that prefix could
2539 * be dereferenced, but we know that prefix will
2540 * valid. Add an assert to make it happy
2543 return zebra_static_route_leak(
2544 vty
, zvrf
, zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2545 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
2549 DEFPY(ipv6_route_address_interface
,
2550 ipv6_route_address_interface_cmd
,
2551 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2555 tag (1-4294967295) \
2559 |table (1-4294967295) \
2564 "Establish static routes\n"
2565 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2566 "IPv6 source-dest route\n"
2567 "IPv6 source prefix\n"
2568 "IPv6 gateway address\n"
2569 "IPv6 gateway interface name\n"
2570 "Set tag for this route\n"
2572 "Distance value for this prefix\n"
2575 "Table to configure\n"
2576 "The table number to configure\n"
2579 struct zebra_vrf
*zvrf
;
2580 struct zebra_vrf
*nh_zvrf
;
2582 if (table_str
&& !vrf_is_backend_netns()) {
2584 "%% table param only available when running on netns-based vrfs\n");
2585 return CMD_WARNING_CONFIG_FAILED
;
2588 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2590 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2591 return CMD_WARNING_CONFIG_FAILED
;
2595 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2600 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2601 return CMD_WARNING_CONFIG_FAILED
;
2604 return zebra_static_route_leak(
2605 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2606 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2610 DEFPY(ipv6_route_address_interface_vrf
,
2611 ipv6_route_address_interface_vrf_cmd
,
2612 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2616 tag (1-4294967295) \
2619 |table (1-4294967295) \
2624 "Establish static routes\n"
2625 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2626 "IPv6 source-dest route\n"
2627 "IPv6 source prefix\n"
2628 "IPv6 gateway address\n"
2629 "IPv6 gateway interface name\n"
2630 "Set tag for this route\n"
2632 "Distance value for this prefix\n"
2634 "Table to configure\n"
2635 "The table number to configure\n"
2638 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2639 struct zebra_vrf
*zvrf
= vrf
->info
;
2640 struct zebra_vrf
*nh_zvrf
;
2642 if (table_str
&& !vrf_is_backend_netns()) {
2644 "%% table param only available when running on netns-based vrfs\n");
2645 return CMD_WARNING_CONFIG_FAILED
;
2649 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2654 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2655 return CMD_WARNING_CONFIG_FAILED
;
2658 return zebra_static_route_leak(
2659 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2660 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2666 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2667 <X:X::X:X$gate|INTERFACE$ifname> \
2669 tag (1-4294967295) \
2673 |table (1-4294967295) \
2678 "Establish static routes\n"
2679 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2680 "IPv6 source-dest route\n"
2681 "IPv6 source prefix\n"
2682 "IPv6 gateway address\n"
2683 "IPv6 gateway interface name\n"
2684 "Set tag for this route\n"
2686 "Distance value for this prefix\n"
2689 "Table to configure\n"
2690 "The table number to configure\n"
2693 struct zebra_vrf
*zvrf
;
2694 struct zebra_vrf
*nh_zvrf
;
2696 if (table_str
&& !vrf_is_backend_netns()) {
2698 "%% table param only available when running on netns-based vrfs\n");
2699 return CMD_WARNING_CONFIG_FAILED
;
2702 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2704 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2705 return CMD_WARNING_CONFIG_FAILED
;
2709 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2714 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2715 return CMD_WARNING_CONFIG_FAILED
;
2718 return zebra_static_route_leak(
2719 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2720 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2724 DEFPY(ipv6_route_vrf
,
2726 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2727 <X:X::X:X$gate|INTERFACE$ifname> \
2729 tag (1-4294967295) \
2732 |table (1-4294967295) \
2737 "Establish static routes\n"
2738 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2739 "IPv6 source-dest route\n"
2740 "IPv6 source prefix\n"
2741 "IPv6 gateway address\n"
2742 "IPv6 gateway interface name\n"
2743 "Set tag for this route\n"
2745 "Distance value for this prefix\n"
2747 "Table to configure\n"
2748 "The table number to configure\n"
2751 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2752 struct zebra_vrf
*zvrf
= vrf
->info
;
2753 struct zebra_vrf
*nh_zvrf
;
2755 if (table_str
&& !vrf_is_backend_netns()) {
2757 "%% table param only available when running on netns-based vrfs\n");
2758 return CMD_WARNING_CONFIG_FAILED
;
2762 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2767 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2768 return CMD_WARNING_CONFIG_FAILED
;
2771 return zebra_static_route_leak(
2772 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2773 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2778 * Show IPv6 mroute command.Used to dump
2779 * the Multicast routing table.
2781 DEFUN (show_ipv6_mroute
,
2782 show_ipv6_mroute_cmd
,
2783 "show ipv6 mroute [vrf NAME]",
2786 "IPv6 Multicast routing table\n"
2789 struct route_table
*table
;
2790 struct route_node
*rn
;
2791 struct route_entry
*re
;
2793 vrf_id_t vrf_id
= VRF_DEFAULT
;
2796 VRF_GET_ID(vrf_id
, argv
[4]->arg
);
2798 table
= zebra_vrf_table(AFI_IP6
, SAFI_MULTICAST
, vrf_id
);
2802 /* Show all IPv6 route. */
2803 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2804 RNODE_FOREACH_RE (rn
, re
) {
2806 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2809 vty_show_ip_route(vty
, rn
, re
, NULL
);
2814 DEFUN (show_ipv6_mroute_vrf_all
,
2815 show_ipv6_mroute_vrf_all_cmd
,
2816 "show ipv6 mroute vrf all",
2819 "IPv6 Multicast routing table\n"
2820 VRF_ALL_CMD_HELP_STR
)
2822 struct route_table
*table
;
2823 struct route_node
*rn
;
2824 struct route_entry
*re
;
2826 struct zebra_vrf
*zvrf
;
2829 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2830 if ((zvrf
= vrf
->info
) == NULL
2831 || (table
= zvrf
->table
[AFI_IP6
][SAFI_MULTICAST
]) == NULL
)
2834 /* Show all IPv6 route. */
2835 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2836 RNODE_FOREACH_RE (rn
, re
) {
2838 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2841 vty_show_ip_route(vty
, rn
, re
, NULL
);
2847 DEFUN (allow_external_route_update
,
2848 allow_external_route_update_cmd
,
2849 "allow-external-route-update",
2850 "Allow FRR routes to be overwritten by external processes\n")
2857 DEFUN (no_allow_external_route_update
,
2858 no_allow_external_route_update_cmd
,
2859 "no allow-external-route-update",
2861 "Allow FRR routes to be overwritten by external processes\n")
2876 struct zebra_vrf
*zvrf
;
2878 if (vrf_is_backend_netns())
2879 vty_out(vty
, "netns-based vrfs\n");
2881 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2882 if (!(zvrf
= vrf
->info
))
2884 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2887 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2888 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2889 vty_out(vty
, "inactive");
2890 else if (zvrf_ns_name(zvrf
))
2891 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2892 zvrf_ns_name(zvrf
));
2894 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2896 if (vrf_is_user_cfged(vrf
))
2897 vty_out(vty
, " (configured)");
2904 DEFUN_HIDDEN (default_vrf_vni_mapping
,
2905 default_vrf_vni_mapping_cmd
,
2906 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2907 "VNI corresponding to the DEFAULT VRF\n"
2909 "Prefix routes only \n")
2912 char err
[ERR_STR_SZ
];
2913 struct zebra_vrf
*zvrf
= NULL
;
2914 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2917 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2924 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2927 vty_out(vty
, "%s\n", err
);
2934 DEFUN_HIDDEN (no_default_vrf_vni_mapping
,
2935 no_default_vrf_vni_mapping_cmd
,
2936 "no vni " CMD_VNI_RANGE
,
2938 "VNI corresponding to DEFAULT VRF\n"
2942 char err
[ERR_STR_SZ
];
2943 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2944 struct zebra_vrf
*zvrf
= NULL
;
2946 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2950 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
, 0, 0);
2952 vty_out(vty
, "%s\n", err
);
2959 DEFUN (vrf_vni_mapping
,
2960 vrf_vni_mapping_cmd
,
2961 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2962 "VNI corresponding to tenant VRF\n"
2964 "prefix-routes-only\n")
2969 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2970 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2971 char err
[ERR_STR_SZ
];
2979 /* Mark as having FRR configuration */
2980 vrf_set_user_cfged(vrf
);
2981 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2984 vty_out(vty
, "%s\n", err
);
2991 DEFUN (no_vrf_vni_mapping
,
2992 no_vrf_vni_mapping_cmd
,
2993 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2995 "VNI corresponding to tenant VRF\n"
2997 "prefix-routes-only\n")
3001 char err
[ERR_STR_SZ
];
3002 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3004 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
3012 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
,
3013 ERR_STR_SZ
, filter
, 0);
3015 vty_out(vty
, "%s\n", err
);
3019 /* If no other FRR config for this VRF, mark accordingly. */
3020 if (!zebra_vrf_has_config(zvrf
))
3021 vrf_reset_user_cfged(vrf
);
3027 DEFUN (show_vrf_vni
,
3029 "show vrf vni [json]",
3036 struct zebra_vrf
*zvrf
;
3037 json_object
*json
= NULL
;
3038 json_object
*json_vrfs
= NULL
;
3039 uint8_t uj
= use_json(argc
, argv
);
3042 json
= json_object_new_object();
3043 json_vrfs
= json_object_new_array();
3047 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3048 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3050 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3055 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3059 json_object_object_add(json
, "vrfs", json_vrfs
);
3060 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3061 json
, JSON_C_TO_STRING_PRETTY
));
3062 json_object_free(json
);
3068 DEFUN (show_evpn_global
,
3069 show_evpn_global_cmd
,
3075 uint8_t uj
= use_json(argc
, argv
);
3077 zebra_vxlan_print_evpn(vty
, uj
);
3081 DEFUN (show_evpn_vni
,
3083 "show evpn vni [json]",
3086 "VxLAN information\n"
3089 struct zebra_vrf
*zvrf
;
3090 uint8_t uj
= use_json(argc
, argv
);
3092 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3093 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3097 DEFUN (show_evpn_vni_vni
,
3098 show_evpn_vni_vni_cmd
,
3099 "show evpn vni " CMD_VNI_RANGE
"[json]",
3102 "VxLAN Network Identifier\n"
3106 struct zebra_vrf
*zvrf
;
3108 uint8_t uj
= use_json(argc
, argv
);
3110 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3111 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3112 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
);
3116 DEFUN (show_evpn_rmac_vni_mac
,
3117 show_evpn_rmac_vni_mac_cmd
,
3118 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3125 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3130 uint8_t uj
= use_json(argc
, argv
);
3132 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3133 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3134 vty_out(vty
, "%% Malformed MAC address\n");
3137 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3141 DEFUN (show_evpn_rmac_vni
,
3142 show_evpn_rmac_vni_cmd
,
3143 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3152 uint8_t uj
= use_json(argc
, argv
);
3154 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3155 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3160 DEFUN (show_evpn_rmac_vni_all
,
3161 show_evpn_rmac_vni_all_cmd
,
3162 "show evpn rmac vni all [json]",
3170 uint8_t uj
= use_json(argc
, argv
);
3172 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3177 DEFUN (show_evpn_nh_vni_ip
,
3178 show_evpn_nh_vni_ip_cmd
,
3179 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3186 "Host address (ipv4 or ipv6)\n"
3191 uint8_t uj
= use_json(argc
, argv
);
3193 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3194 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3196 vty_out(vty
, "%% Malformed Neighbor address\n");
3199 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3204 DEFUN (show_evpn_nh_vni
,
3205 show_evpn_nh_vni_cmd
,
3206 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3215 uint8_t uj
= use_json(argc
, argv
);
3217 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3218 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3223 DEFUN (show_evpn_nh_vni_all
,
3224 show_evpn_nh_vni_all_cmd
,
3225 "show evpn next-hops vni all [json]",
3233 uint8_t uj
= use_json(argc
, argv
);
3235 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3240 DEFUN (show_evpn_mac_vni
,
3241 show_evpn_mac_vni_cmd
,
3242 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3246 "VxLAN Network Identifier\n"
3250 struct zebra_vrf
*zvrf
;
3252 uint8_t uj
= use_json(argc
, argv
);
3254 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3255 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3256 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3260 DEFUN (show_evpn_mac_vni_all
,
3261 show_evpn_mac_vni_all_cmd
,
3262 "show evpn mac vni all [json]",
3266 "VxLAN Network Identifier\n"
3270 struct zebra_vrf
*zvrf
;
3271 uint8_t uj
= use_json(argc
, argv
);
3273 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3274 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, uj
);
3278 DEFUN (show_evpn_mac_vni_all_vtep
,
3279 show_evpn_mac_vni_all_vtep_cmd
,
3280 "show evpn mac vni all vtep A.B.C.D [json]",
3284 "VxLAN Network Identifier\n"
3287 "Remote VTEP IP address\n"
3290 struct zebra_vrf
*zvrf
;
3291 struct in_addr vtep_ip
;
3292 uint8_t uj
= use_json(argc
, argv
);
3294 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3296 vty_out(vty
, "%% Malformed VTEP IP address\n");
3299 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3300 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3306 DEFUN (show_evpn_mac_vni_mac
,
3307 show_evpn_mac_vni_mac_cmd
,
3308 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD",
3312 "VxLAN Network Identifier\n"
3315 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
3317 struct zebra_vrf
*zvrf
;
3321 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3322 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3323 vty_out(vty
, "%% Malformed MAC address");
3326 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3327 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
);
3331 DEFUN (show_evpn_mac_vni_vtep
,
3332 show_evpn_mac_vni_vtep_cmd
,
3333 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3337 "VxLAN Network Identifier\n"
3340 "Remote VTEP IP address\n"
3343 struct zebra_vrf
*zvrf
;
3345 struct in_addr vtep_ip
;
3346 uint8_t uj
= use_json(argc
, argv
);
3348 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3349 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3351 vty_out(vty
, "%% Malformed VTEP IP address\n");
3355 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3356 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3360 DEFUN (show_evpn_neigh_vni
,
3361 show_evpn_neigh_vni_cmd
,
3362 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3365 "ARP and ND cache\n"
3366 "VxLAN Network Identifier\n"
3370 struct zebra_vrf
*zvrf
;
3372 uint8_t uj
= use_json(argc
, argv
);
3374 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3375 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3376 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3380 DEFUN (show_evpn_neigh_vni_all
,
3381 show_evpn_neigh_vni_all_cmd
,
3382 "show evpn arp-cache vni all [json]",
3385 "ARP and ND cache\n"
3386 "VxLAN Network Identifier\n"
3390 struct zebra_vrf
*zvrf
;
3391 uint8_t uj
= use_json(argc
, argv
);
3393 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3394 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, uj
);
3398 DEFUN (show_evpn_neigh_vni_neigh
,
3399 show_evpn_neigh_vni_neigh_cmd
,
3400 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3403 "ARP and ND cache\n"
3404 "VxLAN Network Identifier\n"
3407 "Neighbor address (IPv4 or IPv6 address)\n"
3410 struct zebra_vrf
*zvrf
;
3413 uint8_t uj
= use_json(argc
, argv
);
3415 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3416 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3418 vty_out(vty
, "%% Malformed Neighbor address\n");
3421 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3422 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3426 DEFUN (show_evpn_neigh_vni_vtep
,
3427 show_evpn_neigh_vni_vtep_cmd
,
3428 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3431 "ARP and ND cache\n"
3432 "VxLAN Network Identifier\n"
3435 "Remote VTEP IP address\n"
3438 struct zebra_vrf
*zvrf
;
3440 struct in_addr vtep_ip
;
3441 uint8_t uj
= use_json(argc
, argv
);
3443 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3444 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3446 vty_out(vty
, "%% Malformed VTEP IP address\n");
3450 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3451 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3455 /* policy routing contexts */
3456 DEFUN (show_pbr_ipset
,
3458 "show pbr ipset [WORD]",
3460 "Policy-Based Routing\n"
3461 "IPset Context information\n"
3462 "IPset Name information\n")
3466 found
= argv_find(argv
, argc
, "WORD", &idx
);
3468 zebra_pbr_show_ipset_list(vty
, NULL
);
3470 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3474 /* policy routing contexts */
3475 DEFUN (show_pbr_iptable
,
3476 show_pbr_iptable_cmd
,
3479 "Policy-Based Routing\n"
3480 "IPtable Context information\n")
3482 zebra_pbr_show_iptable(vty
);
3486 /* Static ip route configuration write function. */
3487 static int zebra_ip_config(struct vty
*vty
)
3491 write
+= zebra_import_table_config(vty
);
3496 DEFUN (ip_zebra_import_table_distance
,
3497 ip_zebra_import_table_distance_cmd
,
3498 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3500 "import routes from non-main kernel table\n"
3501 "kernel routing table id\n"
3502 "Distance for imported routes\n"
3503 "Default distance value\n"
3504 "route-map for filtering\n"
3507 uint32_t table_id
= 0;
3509 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3510 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3512 strmatch(argv
[argc
- 2]->text
, "route-map")
3513 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3517 if (argc
== 7 || (argc
== 5 && !rmap
))
3518 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3520 if (!is_zebra_valid_kernel_table(table_id
)) {
3522 "Invalid routing table ID, %d. Must be in range 1-252\n",
3525 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3529 if (is_zebra_main_routing_table(table_id
)) {
3531 "Invalid routing table ID, %d. Must be non-default table\n",
3534 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3538 ret
= zebra_import_table(AFI_IP
, table_id
, distance
, rmap
, 1);
3540 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3545 DEFUN_HIDDEN (zebra_packet_process
,
3546 zebra_packet_process_cmd
,
3547 "zebra zapi-packets (1-10000)",
3550 "Number of packets to process before relinquishing thread\n")
3552 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3554 atomic_store_explicit(&zebrad
.packets_to_process
, packets
,
3555 memory_order_relaxed
);
3560 DEFUN_HIDDEN (no_zebra_packet_process
,
3561 no_zebra_packet_process_cmd
,
3562 "no zebra zapi-packets [(1-10000)]",
3566 "Number of packets to process before relinquishing thread\n")
3568 atomic_store_explicit(&zebrad
.packets_to_process
,
3569 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3570 memory_order_relaxed
);
3575 DEFUN_HIDDEN (zebra_workqueue_timer
,
3576 zebra_workqueue_timer_cmd
,
3577 "zebra work-queue (0-10000)",
3580 "Time in milliseconds\n")
3582 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3583 zebrad
.ribq
->spec
.hold
= timer
;
3588 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3589 no_zebra_workqueue_timer_cmd
,
3590 "no zebra work-queue [(0-10000)]",
3594 "Time in milliseconds\n")
3596 zebrad
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3601 DEFUN (no_ip_zebra_import_table
,
3602 no_ip_zebra_import_table_cmd
,
3603 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3606 "import routes from non-main kernel table\n"
3607 "kernel routing table id\n"
3608 "Distance for imported routes\n"
3609 "Default distance value\n"
3610 "route-map for filtering\n"
3613 uint32_t table_id
= 0;
3614 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3616 if (!is_zebra_valid_kernel_table(table_id
)) {
3618 "Invalid routing table ID. Must be in range 1-252\n");
3622 if (is_zebra_main_routing_table(table_id
)) {
3624 "Invalid routing table ID, %d. Must be non-default table\n",
3629 if (!is_zebra_import_table_enabled(AFI_IP
, table_id
))
3632 return (zebra_import_table(AFI_IP
, table_id
, 0, NULL
, 0));
3635 static int config_write_protocol(struct vty
*vty
)
3638 vty_out(vty
, "allow-external-route-update\n");
3640 if (zebra_rnh_ip_default_route
)
3641 vty_out(vty
, "ip nht resolve-via-default\n");
3643 if (zebra_rnh_ipv6_default_route
)
3644 vty_out(vty
, "ipv6 nht resolve-via-default\n");
3646 if (zebrad
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3647 vty_out(vty
, "zebra work-queue %u\n", zebrad
.ribq
->spec
.hold
);
3649 if (zebrad
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3650 vty_out(vty
, "zebra zapi-packets %u\n",
3651 zebrad
.packets_to_process
);
3653 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3655 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3656 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3657 ipv4_multicast_mode
== MCAST_URIB_ONLY
3659 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3661 : ipv4_multicast_mode
3662 == MCAST_MIX_MRIB_FIRST
3664 : ipv4_multicast_mode
3665 == MCAST_MIX_DISTANCE
3669 zebra_routemap_config_write_protocol(vty
);
3675 /* Display default rtm_table for all clients. */
3680 "default routing table to use for all clients\n")
3682 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3686 DEFUN (config_table
,
3689 "Configure target kernel routing table\n"
3692 zebrad
.rtm_table_default
= strtol(argv
[1]->arg
, (char **)0, 10);
3696 DEFUN (no_config_table
,
3697 no_config_table_cmd
,
3698 "no table [TABLENO]",
3700 "Configure target kernel routing table\n"
3703 zebrad
.rtm_table_default
= 0;
3717 " Route Route Neighbor LSP LSP\n");
3719 "VRF Installs Removals Updates Installs Removals\n");
3721 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3722 struct zebra_vrf
*zvrf
= vrf
->info
;
3724 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
3725 " %10" PRIu64
" %10" PRIu64
"\n",
3726 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
3727 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
3728 zvrf
->lsp_removals
);
3734 DEFUN (ip_forwarding
,
3738 "Turn on IP forwarding\n")
3744 ret
= ipforward_on();
3747 vty_out(vty
, "Can't turn on IP forwarding\n");
3748 return CMD_WARNING_CONFIG_FAILED
;
3754 DEFUN (no_ip_forwarding
,
3755 no_ip_forwarding_cmd
,
3759 "Turn off IP forwarding\n")
3765 ret
= ipforward_off();
3768 vty_out(vty
, "Can't turn off IP forwarding\n");
3769 return CMD_WARNING_CONFIG_FAILED
;
3775 /* Only display ip forwarding is enabled or not. */
3776 DEFUN (show_ip_forwarding
,
3777 show_ip_forwarding_cmd
,
3778 "show ip forwarding",
3781 "IP forwarding status\n")
3788 vty_out(vty
, "IP forwarding is off\n");
3790 vty_out(vty
, "IP forwarding is on\n");
3794 /* Only display ipv6 forwarding is enabled or not. */
3795 DEFUN (show_ipv6_forwarding
,
3796 show_ipv6_forwarding_cmd
,
3797 "show ipv6 forwarding",
3799 "IPv6 information\n"
3800 "Forwarding status\n")
3804 ret
= ipforward_ipv6();
3808 vty_out(vty
, "ipv6 forwarding is unknown\n");
3811 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3814 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
3817 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3823 DEFUN (ipv6_forwarding
,
3824 ipv6_forwarding_cmd
,
3827 "Turn on IPv6 forwarding\n")
3831 ret
= ipforward_ipv6();
3833 ret
= ipforward_ipv6_on();
3836 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
3837 return CMD_WARNING_CONFIG_FAILED
;
3843 DEFUN (no_ipv6_forwarding
,
3844 no_ipv6_forwarding_cmd
,
3845 "no ipv6 forwarding",
3848 "Turn off IPv6 forwarding\n")
3852 ret
= ipforward_ipv6();
3854 ret
= ipforward_ipv6_off();
3857 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
3858 return CMD_WARNING_CONFIG_FAILED
;
3864 /* Table configuration write function. */
3865 static int config_write_table(struct vty
*vty
)
3867 if (zebrad
.rtm_table_default
)
3868 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3872 /* IPForwarding configuration write function. */
3873 static int config_write_forwarding(struct vty
*vty
)
3875 /* FIXME: Find better place for that. */
3876 router_id_write(vty
);
3879 vty_out(vty
, "no ip forwarding\n");
3880 if (!ipforward_ipv6())
3881 vty_out(vty
, "no ipv6 forwarding\n");
3882 vty_out(vty
, "!\n");
3886 /* IP node for static routes. */
3887 static struct cmd_node ip_node
= {IP_NODE
, "", 1};
3888 static struct cmd_node protocol_node
= {PROTOCOL_NODE
, "", 1};
3889 /* table node for routing tables. */
3890 static struct cmd_node table_node
= {TABLE_NODE
,
3891 "", /* This node has no interface. */
3893 static struct cmd_node forwarding_node
= {FORWARDING_NODE
,
3894 "", /* This node has no interface. */
3898 void zebra_vty_init(void)
3900 /* Install configuration write function. */
3901 install_node(&table_node
, config_write_table
);
3902 install_node(&forwarding_node
, config_write_forwarding
);
3904 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
3905 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
3906 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
3907 install_element(ENABLE_NODE
, &show_zebra_cmd
);
3910 install_element(VIEW_NODE
, &show_table_cmd
);
3911 install_element(CONFIG_NODE
, &config_table_cmd
);
3912 install_element(CONFIG_NODE
, &no_config_table_cmd
);
3913 #endif /* HAVE_NETLINK */
3915 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
3916 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
3917 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
3920 zebra_route_map_init();
3922 install_node(&ip_node
, zebra_ip_config
);
3923 install_node(&protocol_node
, config_write_protocol
);
3925 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
3926 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
3927 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
3928 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
3929 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
3930 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
3931 install_element(CONFIG_NODE
,
3932 &ip_route_address_interface_cmd
);
3933 install_element(CONFIG_NODE
, &ip_route_cmd
);
3934 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
3935 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
3936 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
3938 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
3939 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
3940 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
3941 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
3942 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
3943 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
3945 install_element(VIEW_NODE
, &show_vrf_cmd
);
3946 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
3947 install_element(VIEW_NODE
, &show_route_cmd
);
3948 install_element(VIEW_NODE
, &show_route_table_cmd
);
3949 if (vrf_is_backend_netns())
3950 install_element(VIEW_NODE
, &show_route_table_vrf_cmd
);
3951 install_element(VIEW_NODE
, &show_route_detail_cmd
);
3952 install_element(VIEW_NODE
, &show_route_summary_cmd
);
3953 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
3954 install_element(VIEW_NODE
, &show_ip_nht_vrf_all_cmd
);
3955 install_element(VIEW_NODE
, &show_ipv6_nht_cmd
);
3956 install_element(VIEW_NODE
, &show_ipv6_nht_vrf_all_cmd
);
3958 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
3959 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
3961 install_element(CONFIG_NODE
,
3962 &ipv6_route_blackhole_cmd
);
3963 install_element(CONFIG_NODE
,
3964 &ipv6_route_address_interface_cmd
);
3965 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
3966 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
3967 install_element(VRF_NODE
,
3968 &ipv6_route_address_interface_vrf_cmd
);
3969 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
3970 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
3971 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
3972 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
3973 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
3974 install_element(VIEW_NODE
, &show_ipv6_mroute_cmd
);
3976 /* Commands for VRF */
3977 install_element(VIEW_NODE
, &show_ipv6_mroute_vrf_all_cmd
);
3979 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
3980 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
3981 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
3982 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
3983 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
3984 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
3985 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
3986 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
3987 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
3988 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
3989 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
3990 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
3991 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
3992 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
3993 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
3994 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
3995 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
3996 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
3998 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
3999 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4001 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4002 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4003 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4004 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4006 static_list
= list_new();
4007 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
4008 static_list
->del
= (void (*)(void *))static_list_delete
;