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
) {
1203 vrf_lookup_by_id(nexthop
->vrf_id
);
1206 vty_out(vty
, "(vrf %s)", vrf
->name
);
1208 vty_out(vty
, "(vrf UKNOWN)");
1211 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1212 vty_out(vty
, " (duplicate nexthop removed)");
1214 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1215 vty_out(vty
, " inactive");
1217 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1218 vty_out(vty
, " onlink");
1220 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1221 vty_out(vty
, " (recursive)");
1223 switch (nexthop
->type
) {
1224 case NEXTHOP_TYPE_IPV4
:
1225 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1226 if (nexthop
->src
.ipv4
.s_addr
) {
1227 if (inet_ntop(AF_INET
,
1229 addrstr
, sizeof addrstr
))
1230 vty_out(vty
, ", src %s",
1234 case NEXTHOP_TYPE_IPV6
:
1235 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1236 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1238 if (inet_ntop(AF_INET6
,
1240 addrstr
, sizeof addrstr
))
1241 vty_out(vty
, ", src %s",
1249 if (re
->nexthop_mtu
)
1250 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
1252 /* Label information */
1253 if (nexthop
->nh_label
1254 && nexthop
->nh_label
->num_labels
) {
1255 vty_out(vty
, ", label %s",
1257 nexthop
->nh_label
->num_labels
,
1258 nexthop
->nh_label
->label
, buf
,
1268 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
1269 struct route_entry
*re
, json_object
*json
)
1271 struct nexthop
*nexthop
;
1273 char buf
[SRCDEST2STR_BUFFER
];
1274 json_object
*json_nexthops
= NULL
;
1275 json_object
*json_nexthop
= NULL
;
1276 json_object
*json_route
= NULL
;
1277 json_object
*json_labels
= NULL
;
1281 uptime
= time(NULL
);
1282 uptime
-= re
->uptime
;
1283 tm
= gmtime(&uptime
);
1286 json_route
= json_object_new_object();
1287 json_nexthops
= json_object_new_array();
1289 json_object_string_add(json_route
, "prefix",
1290 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1291 json_object_string_add(json_route
, "protocol",
1292 zebra_route_string(re
->type
));
1295 json_object_int_add(json_route
, "instance",
1299 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
1301 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1302 json_object_boolean_true_add(json_route
, "selected");
1304 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
1305 json_object_int_add(json_route
, "distance",
1307 json_object_int_add(json_route
, "metric", re
->metric
);
1310 json_object_int_add(json_route
, "internalStatus",
1312 json_object_int_add(json_route
, "internalFlags",
1314 if (uptime
< ONE_DAY_SECOND
)
1315 sprintf(buf
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1317 else if (uptime
< ONE_WEEK_SECOND
)
1318 sprintf(buf
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1321 sprintf(buf
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1322 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1325 json_object_string_add(json_route
, "uptime", buf
);
1327 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1328 json_nexthop
= json_object_new_object();
1330 json_object_int_add(json_nexthop
, "flags",
1333 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1334 json_object_boolean_true_add(json_nexthop
,
1337 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1338 json_object_boolean_true_add(json_nexthop
,
1341 switch (nexthop
->type
) {
1342 case NEXTHOP_TYPE_IPV4
:
1343 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1344 json_object_string_add(
1346 inet_ntoa(nexthop
->gate
.ipv4
));
1347 json_object_string_add(json_nexthop
, "afi",
1350 if (nexthop
->ifindex
) {
1351 json_object_int_add(json_nexthop
,
1354 json_object_string_add(
1355 json_nexthop
, "interfaceName",
1361 case NEXTHOP_TYPE_IPV6
:
1362 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1363 json_object_string_add(
1365 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1367 json_object_string_add(json_nexthop
, "afi",
1370 if (nexthop
->ifindex
) {
1371 json_object_int_add(json_nexthop
,
1374 json_object_string_add(
1375 json_nexthop
, "interfaceName",
1382 case NEXTHOP_TYPE_IFINDEX
:
1383 json_object_boolean_true_add(
1384 json_nexthop
, "directlyConnected");
1385 json_object_int_add(json_nexthop
,
1388 json_object_string_add(
1389 json_nexthop
, "interfaceName",
1390 ifindex2ifname(nexthop
->ifindex
,
1393 case NEXTHOP_TYPE_BLACKHOLE
:
1394 json_object_boolean_true_add(json_nexthop
,
1396 switch (nexthop
->bh_type
) {
1397 case BLACKHOLE_REJECT
:
1398 json_object_boolean_true_add(
1399 json_nexthop
, "reject");
1401 case BLACKHOLE_ADMINPROHIB
:
1402 json_object_boolean_true_add(
1404 "admin-prohibited");
1406 case BLACKHOLE_NULL
:
1407 json_object_boolean_true_add(
1408 json_nexthop
, "blackhole");
1410 case BLACKHOLE_UNSPEC
:
1418 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1420 vrf_lookup_by_id(nexthop
->vrf_id
);
1422 json_object_string_add(json_nexthop
, "vrf",
1425 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1426 json_object_boolean_true_add(json_nexthop
,
1429 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1430 json_object_boolean_true_add(json_nexthop
,
1433 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1434 json_object_boolean_true_add(json_nexthop
,
1437 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1438 json_object_boolean_true_add(json_nexthop
,
1441 switch (nexthop
->type
) {
1442 case NEXTHOP_TYPE_IPV4
:
1443 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1444 if (nexthop
->src
.ipv4
.s_addr
) {
1445 if (inet_ntop(AF_INET
,
1446 &nexthop
->src
.ipv4
, buf
,
1448 json_object_string_add(
1449 json_nexthop
, "source",
1453 case NEXTHOP_TYPE_IPV6
:
1454 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1455 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1457 if (inet_ntop(AF_INET6
,
1458 &nexthop
->src
.ipv6
, buf
,
1460 json_object_string_add(
1461 json_nexthop
, "source",
1469 if (nexthop
->nh_label
1470 && nexthop
->nh_label
->num_labels
) {
1471 json_labels
= json_object_new_array();
1473 for (int label_index
= 0;
1475 < nexthop
->nh_label
->num_labels
;
1477 json_object_array_add(
1479 json_object_new_int(
1480 nexthop
->nh_label
->label
1483 json_object_object_add(json_nexthop
, "labels",
1487 json_object_array_add(json_nexthops
, json_nexthop
);
1490 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1491 json_object_array_add(json
, json_route
);
1495 /* Nexthop information. */
1496 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1497 if (nexthop
== re
->ng
.nexthop
) {
1498 /* Prefix information. */
1499 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1501 len
+= vty_out(vty
, "[%d]", re
->instance
);
1504 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)
1507 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1510 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1512 /* Distance and metric display. */
1513 if (re
->type
!= ZEBRA_ROUTE_CONNECT
)
1514 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1517 vty_out(vty
, " %c%*c",
1518 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1519 ? CHECK_FLAG(nexthop
->flags
,
1520 NEXTHOP_FLAG_DUPLICATE
)
1524 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1527 switch (nexthop
->type
) {
1528 case NEXTHOP_TYPE_IPV4
:
1529 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1530 vty_out(vty
, " via %s", inet_ntoa(nexthop
->gate
.ipv4
));
1531 if (nexthop
->ifindex
)
1532 vty_out(vty
, ", %s",
1533 ifindex2ifname(nexthop
->ifindex
,
1536 case NEXTHOP_TYPE_IPV6
:
1537 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1538 vty_out(vty
, " via %s",
1539 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
1541 if (nexthop
->ifindex
)
1542 vty_out(vty
, ", %s",
1543 ifindex2ifname(nexthop
->ifindex
,
1547 case NEXTHOP_TYPE_IFINDEX
:
1548 vty_out(vty
, " is directly connected, %s",
1549 ifindex2ifname(nexthop
->ifindex
,
1552 case NEXTHOP_TYPE_BLACKHOLE
:
1553 vty_out(vty
, " unreachable");
1554 switch (nexthop
->bh_type
) {
1555 case BLACKHOLE_REJECT
:
1556 vty_out(vty
, " (ICMP unreachable)");
1558 case BLACKHOLE_ADMINPROHIB
:
1559 vty_out(vty
, " (ICMP admin-prohibited)");
1561 case BLACKHOLE_NULL
:
1562 vty_out(vty
, " (blackhole)");
1564 case BLACKHOLE_UNSPEC
:
1572 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1573 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
1576 vty_out(vty
, "(vrf %s)", vrf
->name
);
1578 vty_out(vty
, "(vrf UKNOWN)");
1581 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1582 vty_out(vty
, " inactive");
1584 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1585 vty_out(vty
, " onlink");
1587 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1588 vty_out(vty
, " (recursive)");
1590 switch (nexthop
->type
) {
1591 case NEXTHOP_TYPE_IPV4
:
1592 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1593 if (nexthop
->src
.ipv4
.s_addr
) {
1594 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
1596 vty_out(vty
, ", src %s", buf
);
1599 case NEXTHOP_TYPE_IPV6
:
1600 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1601 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
1602 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
1604 vty_out(vty
, ", src %s", buf
);
1611 /* Label information */
1612 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
1613 vty_out(vty
, ", label %s",
1614 mpls_label2str(nexthop
->nh_label
->num_labels
,
1615 nexthop
->nh_label
->label
, buf
,
1619 if (uptime
< ONE_DAY_SECOND
)
1620 vty_out(vty
, ", %02d:%02d:%02d", tm
->tm_hour
,
1621 tm
->tm_min
, tm
->tm_sec
);
1622 else if (uptime
< ONE_WEEK_SECOND
)
1623 vty_out(vty
, ", %dd%02dh%02dm", tm
->tm_yday
,
1624 tm
->tm_hour
, tm
->tm_min
);
1626 vty_out(vty
, ", %02dw%dd%02dh", tm
->tm_yday
/ 7,
1627 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1633 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1634 struct route_table
*table
, afi_t afi
,
1635 bool use_fib
, route_tag_t tag
,
1636 const struct prefix
*longer_prefix_p
,
1637 bool supernets_only
, int type
,
1638 unsigned short ospf_instance_id
,
1641 struct route_node
*rn
;
1642 struct route_entry
*re
;
1645 json_object
*json
= NULL
;
1646 json_object
*json_prefix
= NULL
;
1651 json
= json_object_new_object();
1653 /* Show all routes. */
1654 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
1655 dest
= rib_dest_from_rnode(rn
);
1657 RNODE_FOREACH_RE (rn
, re
) {
1658 if (use_fib
&& re
!= dest
->selected_fib
)
1661 if (tag
&& re
->tag
!= tag
)
1665 && !prefix_match(longer_prefix_p
, &rn
->p
))
1668 /* This can only be true when the afi is IPv4 */
1669 if (supernets_only
) {
1670 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1672 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1675 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1678 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1682 if (type
&& re
->type
!= type
)
1685 if (ospf_instance_id
1686 && (re
->type
!= ZEBRA_ROUTE_OSPF
1687 || re
->instance
!= ospf_instance_id
))
1692 json_prefix
= json_object_new_array();
1697 SHOW_ROUTE_V4_HEADER
);
1700 SHOW_ROUTE_V6_HEADER
);
1702 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1703 vty_out(vty
, "\nVRF %s:\n",
1710 vty_show_ip_route(vty
, rn
, re
, json_prefix
);
1714 prefix2str(&rn
->p
, buf
, sizeof buf
);
1715 json_object_object_add(json
, buf
, json_prefix
);
1721 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1722 json
, JSON_C_TO_STRING_PRETTY
));
1723 json_object_free(json
);
1727 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1728 safi_t safi
, bool use_fib
, uint8_t use_json
,
1730 const struct prefix
*longer_prefix_p
,
1731 bool supernets_only
, int type
,
1732 unsigned short ospf_instance_id
)
1734 struct route_table
*table
;
1735 struct zebra_vrf
*zvrf
= NULL
;
1737 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1739 vty_out(vty
, "{}\n");
1741 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1745 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1747 vty_out(vty
, "{}\n");
1749 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1753 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1756 vty_out(vty
, "{}\n");
1760 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1761 longer_prefix_p
, supernets_only
, type
,
1762 ospf_instance_id
, use_json
);
1767 DEFPY (show_route_table
,
1768 show_route_table_cmd
,
1769 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1773 "IP routing table\n"
1774 "Table to display\n"
1775 "The table number to display, if available\n"
1778 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1779 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1780 struct route_table
*t
;
1782 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1784 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1790 DEFPY (show_route_table_vrf
,
1791 show_route_table_vrf_cmd
,
1792 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
1796 "IP routing table\n"
1797 "Table to display\n"
1798 "The table number to display, if available\n"
1802 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1803 struct zebra_vrf
*zvrf
;
1804 struct route_table
*t
;
1805 vrf_id_t vrf_id
= VRF_DEFAULT
;
1808 VRF_GET_ID(vrf_id
, vrf_name
);
1809 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
1811 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1813 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1821 "show ip nht [vrf NAME]",
1824 "IP nexthop tracking table\n"
1828 vrf_id_t vrf_id
= VRF_DEFAULT
;
1831 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1833 zebra_print_rnh_table(vrf_id
, AF_INET
, vty
, RNH_NEXTHOP_TYPE
);
1838 DEFUN (show_ip_nht_vrf_all
,
1839 show_ip_nht_vrf_all_cmd
,
1840 "show ip nht vrf all",
1843 "IP nexthop tracking table\n"
1844 VRF_ALL_CMD_HELP_STR
)
1847 struct zebra_vrf
*zvrf
;
1849 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1850 if ((zvrf
= vrf
->info
) != NULL
) {
1851 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1852 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET
, vty
,
1859 DEFUN (show_ipv6_nht
,
1861 "show ipv6 nht [vrf NAME]",
1864 "IPv6 nexthop tracking table\n"
1868 vrf_id_t vrf_id
= VRF_DEFAULT
;
1871 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1873 zebra_print_rnh_table(vrf_id
, AF_INET6
, vty
, RNH_NEXTHOP_TYPE
);
1878 DEFUN (show_ipv6_nht_vrf_all
,
1879 show_ipv6_nht_vrf_all_cmd
,
1880 "show ipv6 nht vrf all",
1883 "IPv6 nexthop tracking table\n"
1884 VRF_ALL_CMD_HELP_STR
)
1887 struct zebra_vrf
*zvrf
;
1889 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1890 if ((zvrf
= vrf
->info
) != NULL
) {
1891 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1892 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET6
, vty
,
1899 DEFUN (ip_nht_default_route
,
1900 ip_nht_default_route_cmd
,
1901 "ip nht resolve-via-default",
1903 "Filter Next Hop tracking route resolution\n"
1904 "Resolve via default route\n")
1906 if (zebra_rnh_ip_default_route
)
1909 zebra_rnh_ip_default_route
= 1;
1910 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1914 DEFUN (no_ip_nht_default_route
,
1915 no_ip_nht_default_route_cmd
,
1916 "no ip nht resolve-via-default",
1919 "Filter Next Hop tracking route resolution\n"
1920 "Resolve via default route\n")
1922 if (!zebra_rnh_ip_default_route
)
1925 zebra_rnh_ip_default_route
= 0;
1926 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1930 DEFUN (ipv6_nht_default_route
,
1931 ipv6_nht_default_route_cmd
,
1932 "ipv6 nht resolve-via-default",
1934 "Filter Next Hop tracking route resolution\n"
1935 "Resolve via default route\n")
1937 if (zebra_rnh_ipv6_default_route
)
1940 zebra_rnh_ipv6_default_route
= 1;
1941 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1945 DEFUN (no_ipv6_nht_default_route
,
1946 no_ipv6_nht_default_route_cmd
,
1947 "no ipv6 nht resolve-via-default",
1950 "Filter Next Hop tracking route resolution\n"
1951 "Resolve via default route\n")
1953 if (!zebra_rnh_ipv6_default_route
)
1956 zebra_rnh_ipv6_default_route
= 0;
1957 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1965 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1968 |A.B.C.D/M$prefix longer-prefixes\
1969 |supernets-only$supernets_only\
1972 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1973 |ospf$type_str (1-65535)$ospf_instance_id\
1975 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1978 |X:X::X:X/M$prefix longer-prefixes\
1980 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1985 "IP forwarding table\n"
1986 "IP routing table\n"
1987 VRF_FULL_CMD_HELP_STR
1988 "Show only routes with tag\n"
1990 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1991 "Show route matching the specified Network/Mask pair only\n"
1992 "Show supernet entries only\n"
1993 FRR_IP_REDIST_HELP_STR_ZEBRA
1994 "Open Shortest Path First (OSPFv2)\n"
1997 "IP forwarding table\n"
1998 "IP routing table\n"
1999 VRF_FULL_CMD_HELP_STR
2000 "Show only routes with tag\n"
2003 "Show route matching the specified Network/Mask pair only\n"
2004 FRR_IP6_REDIST_HELP_STR_ZEBRA
2007 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2012 type
= proto_redistnum(afi
, type_str
);
2014 vty_out(vty
, "Unknown route type\n");
2020 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2021 struct zebra_vrf
*zvrf
;
2022 struct route_table
*table
;
2024 if ((zvrf
= vrf
->info
) == NULL
2025 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2029 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
, !!fib
,
2030 !!json
, tag
, prefix_str
? prefix
: NULL
,
2031 !!supernets_only
, type
, ospf_instance_id
);
2034 vrf_id_t vrf_id
= VRF_DEFAULT
;
2037 VRF_GET_ID(vrf_id
, vrf_name
);
2038 vrf
= vrf_lookup_by_id(vrf_id
);
2039 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
, !!fib
,
2040 !!json
, tag
, prefix_str
? prefix
: NULL
,
2041 !!supernets_only
, type
, ospf_instance_id
);
2047 DEFPY (show_route_detail
,
2048 show_route_detail_cmd
,
2051 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2056 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2064 "IP routing table\n"
2065 VRF_FULL_CMD_HELP_STR
2066 "Network in the IP routing table to display\n"
2067 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2069 "IP routing table\n"
2070 VRF_FULL_CMD_HELP_STR
2074 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2075 struct route_table
*table
;
2077 struct route_node
*rn
;
2080 prefix_str
= address_str
;
2081 if (str2prefix(prefix_str
, &p
) < 0) {
2082 vty_out(vty
, "%% Malformed address\n");
2088 struct zebra_vrf
*zvrf
;
2090 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2091 if ((zvrf
= vrf
->info
) == NULL
2092 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2095 rn
= route_node_match(table
, &p
);
2098 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2099 route_unlock_node(rn
);
2103 vty_show_ip_route_detail(vty
, rn
, 0);
2105 route_unlock_node(rn
);
2108 vrf_id_t vrf_id
= VRF_DEFAULT
;
2111 VRF_GET_ID(vrf_id
, vrf_name
);
2113 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2117 rn
= route_node_match(table
, &p
);
2119 vty_out(vty
, "%% Network not in table\n");
2122 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2123 vty_out(vty
, "%% Network not in table\n");
2124 route_unlock_node(rn
);
2128 vty_show_ip_route_detail(vty
, rn
, 0);
2130 route_unlock_node(rn
);
2136 DEFPY (show_route_summary
,
2137 show_route_summary_cmd
,
2140 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2141 summary [prefix$prefix]\
2142 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2143 summary [prefix$prefix]\
2147 "IP routing table\n"
2148 VRF_FULL_CMD_HELP_STR
2149 "Summary of all routes\n"
2152 "IP routing table\n"
2153 VRF_FULL_CMD_HELP_STR
2154 "Summary of all routes\n"
2157 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2158 struct route_table
*table
;
2162 struct zebra_vrf
*zvrf
;
2164 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2165 if ((zvrf
= vrf
->info
) == NULL
2166 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2170 vty_show_ip_route_summary_prefix(vty
, table
);
2172 vty_show_ip_route_summary(vty
, table
);
2175 vrf_id_t vrf_id
= VRF_DEFAULT
;
2178 VRF_GET_ID(vrf_id
, vrf_name
);
2180 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2185 vty_show_ip_route_summary_prefix(vty
, table
);
2187 vty_show_ip_route_summary(vty
, table
);
2193 static void vty_show_ip_route_summary(struct vty
*vty
,
2194 struct route_table
*table
)
2196 struct route_node
*rn
;
2197 struct route_entry
*re
;
2198 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2199 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2200 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2201 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2205 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2206 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2207 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2208 RNODE_FOREACH_RE (rn
, re
) {
2209 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2210 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2212 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2214 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2216 rib_cnt
[re
->type
]++;
2218 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)) {
2219 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2222 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2224 fib_cnt
[re
->type
]++;
2228 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2229 "FIB", zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2231 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2232 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2233 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2234 if (i
== ZEBRA_ROUTE_BGP
) {
2235 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2236 rib_cnt
[ZEBRA_ROUTE_BGP
],
2237 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2238 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2239 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2240 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2242 vty_out(vty
, "%-20s %-20d %-20d \n",
2243 zebra_route_string(i
), rib_cnt
[i
],
2248 vty_out(vty
, "------\n");
2249 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2250 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2255 * Implementation of the ip route summary prefix command.
2257 * This command prints the primary prefixes that have been installed by various
2258 * protocols on the box.
2261 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2262 struct route_table
*table
)
2264 struct route_node
*rn
;
2265 struct route_entry
*re
;
2266 struct nexthop
*nexthop
;
2267 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2268 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2269 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2270 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2274 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2275 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2276 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2277 RNODE_FOREACH_RE (rn
, re
) {
2280 * In case of ECMP, count only once.
2283 for (nexthop
= re
->ng
.nexthop
; (!cnt
&& nexthop
);
2284 nexthop
= nexthop
->next
) {
2286 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2287 rib_cnt
[re
->type
]++;
2288 if (CHECK_FLAG(nexthop
->flags
,
2289 NEXTHOP_FLAG_FIB
)) {
2290 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2291 fib_cnt
[re
->type
]++;
2293 if (re
->type
== ZEBRA_ROUTE_BGP
2294 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2295 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2296 if (CHECK_FLAG(nexthop
->flags
,
2298 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2303 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2304 "Prefix Routes", "FIB",
2305 zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2307 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2308 if (rib_cnt
[i
] > 0) {
2309 if (i
== ZEBRA_ROUTE_BGP
) {
2310 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2311 rib_cnt
[ZEBRA_ROUTE_BGP
]
2312 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2313 fib_cnt
[ZEBRA_ROUTE_BGP
]
2314 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2315 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2316 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2317 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2319 vty_out(vty
, "%-20s %-20d %-20d \n",
2320 zebra_route_string(i
), rib_cnt
[i
],
2325 vty_out(vty
, "------\n");
2326 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2327 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2331 /* Write static route configuration. */
2332 int static_config(struct vty
*vty
, struct zebra_vrf
*zvrf
, afi_t afi
,
2333 safi_t safi
, const char *cmd
)
2335 struct static_hold_route
*shr
;
2336 struct listnode
*node
;
2338 struct route_node
*rn
;
2339 struct static_route
*si
;
2340 struct route_table
*stable
;
2341 char buf
[SRCDEST2STR_BUFFER
];
2344 if ((stable
= zvrf
->stable
[afi
][safi
]) == NULL
)
2347 sprintf(spacing
, "%s%s", (zvrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
2351 * Static routes for vrfs not fully inited
2353 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
2354 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
2357 if (strcmp(zvrf
->vrf
->name
, shr
->vrf_name
) != 0)
2360 char dest_str
[PREFIX_STRLEN
];
2362 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
2364 vty_out(vty
, "%s ", spacing
);
2366 vty_out(vty
, "%s ", dest_str
);
2368 vty_out(vty
, "from %s ", shr
->src_str
);
2370 vty_out(vty
, "%s ", shr
->gate_str
);
2372 vty_out(vty
, "%s ", shr
->ifname
);
2374 vty_out(vty
, "%s ", shr
->flag_str
);
2376 vty_out(vty
, "tag %s ", shr
->tag_str
);
2377 if (shr
->distance_str
)
2378 vty_out(vty
, "%s ", shr
->distance_str
);
2380 vty_out(vty
, "label %s ", shr
->label_str
);
2382 vty_out(vty
, "table %s ", shr
->table_str
);
2383 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
2384 vty_out(vty
, "nexthop-vrf %s", shr
->nhvrf_name
);
2388 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
2389 for (si
= rn
->info
; si
; si
= si
->next
) {
2390 vty_out(vty
, "%s %s", spacing
,
2391 srcdest_rnode2str(rn
, buf
, sizeof buf
));
2394 case STATIC_IPV4_GATEWAY
:
2395 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
2397 case STATIC_IPV6_GATEWAY
:
2399 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2403 vty_out(vty
, " %s", si
->ifname
);
2405 case STATIC_BLACKHOLE
:
2406 switch (si
->bh_type
) {
2407 case STATIC_BLACKHOLE_DROP
:
2408 vty_out(vty
, " blackhole");
2410 case STATIC_BLACKHOLE_NULL
:
2411 vty_out(vty
, " Null0");
2413 case STATIC_BLACKHOLE_REJECT
:
2414 vty_out(vty
, " reject");
2418 case STATIC_IPV4_GATEWAY_IFNAME
:
2419 vty_out(vty
, " %s %s",
2420 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
2424 case STATIC_IPV6_GATEWAY_IFNAME
:
2425 vty_out(vty
, " %s %s",
2426 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2433 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
2435 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
2436 vty_out(vty
, " %d", si
->distance
);
2438 /* Label information */
2439 if (si
->snh_label
.num_labels
)
2440 vty_out(vty
, " label %s",
2441 mpls_label2str(si
->snh_label
.num_labels
,
2442 si
->snh_label
.label
, buf
,
2445 if (si
->nh_vrf_id
!= si
->vrf_id
) {
2446 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
2449 /* table ID from VRF overrides configured
2451 if (si
->table_id
&& zvrf
->table_id
== RT_TABLE_MAIN
)
2452 vty_out(vty
, " table %u", si
->table_id
);
2461 DEFPY(ipv6_route_blackhole
,
2462 ipv6_route_blackhole_cmd
,
2463 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2464 <Null0|reject|blackhole>$flag \
2466 tag (1-4294967295) \
2470 |table (1-4294967295) \
2474 "Establish static routes\n"
2475 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2476 "IPv6 source-dest route\n"
2477 "IPv6 source prefix\n"
2479 "Emit an ICMP unreachable when matched\n"
2480 "Silently discard pkts when matched\n"
2481 "Set tag for this route\n"
2483 "Distance value for this prefix\n"
2486 "Table to configure\n"
2487 "The table number to configure\n")
2489 if (table_str
&& !vrf_is_backend_netns()) {
2491 "%% table param only available when running on netns-based vrfs\n");
2492 return CMD_WARNING_CONFIG_FAILED
;
2495 return zebra_static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
2496 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
2497 distance_str
, vrf
, label
, table_str
);
2500 DEFPY(ipv6_route_blackhole_vrf
,
2501 ipv6_route_blackhole_vrf_cmd
,
2502 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2503 <Null0|reject|blackhole>$flag \
2505 tag (1-4294967295) \
2508 |table (1-4294967295) \
2512 "Establish static routes\n"
2513 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2514 "IPv6 source-dest route\n"
2515 "IPv6 source prefix\n"
2517 "Emit an ICMP unreachable when matched\n"
2518 "Silently discard pkts when matched\n"
2519 "Set tag for this route\n"
2521 "Distance value for this prefix\n"
2523 "Table to configure\n"
2524 "The table number to configure\n")
2526 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2527 struct zebra_vrf
*zvrf
= vrf
->info
;
2529 if (table_str
&& !vrf_is_backend_netns()) {
2531 "%% table param only available when running on netns-based vrfs\n");
2532 return CMD_WARNING_CONFIG_FAILED
;
2535 * Coverity is complaining that prefix could
2536 * be dereferenced, but we know that prefix will
2537 * valid. Add an assert to make it happy
2540 return zebra_static_route_leak(
2541 vty
, zvrf
, zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2542 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
2546 DEFPY(ipv6_route_address_interface
,
2547 ipv6_route_address_interface_cmd
,
2548 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2552 tag (1-4294967295) \
2556 |table (1-4294967295) \
2561 "Establish static routes\n"
2562 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2563 "IPv6 source-dest route\n"
2564 "IPv6 source prefix\n"
2565 "IPv6 gateway address\n"
2566 "IPv6 gateway interface name\n"
2567 "Set tag for this route\n"
2569 "Distance value for this prefix\n"
2572 "Table to configure\n"
2573 "The table number to configure\n"
2576 struct zebra_vrf
*zvrf
;
2577 struct zebra_vrf
*nh_zvrf
;
2579 if (table_str
&& !vrf_is_backend_netns()) {
2581 "%% table param only available when running on netns-based vrfs\n");
2582 return CMD_WARNING_CONFIG_FAILED
;
2585 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2587 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2588 return CMD_WARNING_CONFIG_FAILED
;
2592 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2597 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2598 return CMD_WARNING_CONFIG_FAILED
;
2601 return zebra_static_route_leak(
2602 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2603 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2607 DEFPY(ipv6_route_address_interface_vrf
,
2608 ipv6_route_address_interface_vrf_cmd
,
2609 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2613 tag (1-4294967295) \
2616 |table (1-4294967295) \
2621 "Establish static routes\n"
2622 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2623 "IPv6 source-dest route\n"
2624 "IPv6 source prefix\n"
2625 "IPv6 gateway address\n"
2626 "IPv6 gateway interface name\n"
2627 "Set tag for this route\n"
2629 "Distance value for this prefix\n"
2631 "Table to configure\n"
2632 "The table number to configure\n"
2635 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2636 struct zebra_vrf
*zvrf
= vrf
->info
;
2637 struct zebra_vrf
*nh_zvrf
;
2639 if (table_str
&& !vrf_is_backend_netns()) {
2641 "%% table param only available when running on netns-based vrfs\n");
2642 return CMD_WARNING_CONFIG_FAILED
;
2646 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2651 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2652 return CMD_WARNING_CONFIG_FAILED
;
2655 return zebra_static_route_leak(
2656 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2657 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2663 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2664 <X:X::X:X$gate|INTERFACE$ifname> \
2666 tag (1-4294967295) \
2670 |table (1-4294967295) \
2675 "Establish static routes\n"
2676 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2677 "IPv6 source-dest route\n"
2678 "IPv6 source prefix\n"
2679 "IPv6 gateway address\n"
2680 "IPv6 gateway interface name\n"
2681 "Set tag for this route\n"
2683 "Distance value for this prefix\n"
2686 "Table to configure\n"
2687 "The table number to configure\n"
2690 struct zebra_vrf
*zvrf
;
2691 struct zebra_vrf
*nh_zvrf
;
2693 if (table_str
&& !vrf_is_backend_netns()) {
2695 "%% table param only available when running on netns-based vrfs\n");
2696 return CMD_WARNING_CONFIG_FAILED
;
2699 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2701 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2702 return CMD_WARNING_CONFIG_FAILED
;
2706 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2711 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2712 return CMD_WARNING_CONFIG_FAILED
;
2715 return zebra_static_route_leak(
2716 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2717 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2721 DEFPY(ipv6_route_vrf
,
2723 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2724 <X:X::X:X$gate|INTERFACE$ifname> \
2726 tag (1-4294967295) \
2729 |table (1-4294967295) \
2734 "Establish static routes\n"
2735 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2736 "IPv6 source-dest route\n"
2737 "IPv6 source prefix\n"
2738 "IPv6 gateway address\n"
2739 "IPv6 gateway interface name\n"
2740 "Set tag for this route\n"
2742 "Distance value for this prefix\n"
2744 "Table to configure\n"
2745 "The table number to configure\n"
2748 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2749 struct zebra_vrf
*zvrf
= vrf
->info
;
2750 struct zebra_vrf
*nh_zvrf
;
2752 if (table_str
&& !vrf_is_backend_netns()) {
2754 "%% table param only available when running on netns-based vrfs\n");
2755 return CMD_WARNING_CONFIG_FAILED
;
2759 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2764 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2765 return CMD_WARNING_CONFIG_FAILED
;
2768 return zebra_static_route_leak(
2769 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2770 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2775 * Show IPv6 mroute command.Used to dump
2776 * the Multicast routing table.
2778 DEFUN (show_ipv6_mroute
,
2779 show_ipv6_mroute_cmd
,
2780 "show ipv6 mroute [vrf NAME]",
2783 "IPv6 Multicast routing table\n"
2786 struct route_table
*table
;
2787 struct route_node
*rn
;
2788 struct route_entry
*re
;
2790 vrf_id_t vrf_id
= VRF_DEFAULT
;
2793 VRF_GET_ID(vrf_id
, argv
[4]->arg
);
2795 table
= zebra_vrf_table(AFI_IP6
, SAFI_MULTICAST
, vrf_id
);
2799 /* Show all IPv6 route. */
2800 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2801 RNODE_FOREACH_RE (rn
, re
) {
2803 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2806 vty_show_ip_route(vty
, rn
, re
, NULL
);
2811 DEFUN (show_ipv6_mroute_vrf_all
,
2812 show_ipv6_mroute_vrf_all_cmd
,
2813 "show ipv6 mroute vrf all",
2816 "IPv6 Multicast routing table\n"
2817 VRF_ALL_CMD_HELP_STR
)
2819 struct route_table
*table
;
2820 struct route_node
*rn
;
2821 struct route_entry
*re
;
2823 struct zebra_vrf
*zvrf
;
2826 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2827 if ((zvrf
= vrf
->info
) == NULL
2828 || (table
= zvrf
->table
[AFI_IP6
][SAFI_MULTICAST
]) == NULL
)
2831 /* Show all IPv6 route. */
2832 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2833 RNODE_FOREACH_RE (rn
, re
) {
2835 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2838 vty_show_ip_route(vty
, rn
, re
, NULL
);
2844 DEFUN (allow_external_route_update
,
2845 allow_external_route_update_cmd
,
2846 "allow-external-route-update",
2847 "Allow FRR routes to be overwritten by external processes\n")
2854 DEFUN (no_allow_external_route_update
,
2855 no_allow_external_route_update_cmd
,
2856 "no allow-external-route-update",
2858 "Allow FRR routes to be overwritten by external processes\n")
2873 struct zebra_vrf
*zvrf
;
2875 if (vrf_is_backend_netns())
2876 vty_out(vty
, "netns-based vrfs\n");
2878 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2879 if (!(zvrf
= vrf
->info
))
2881 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2884 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2885 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2886 vty_out(vty
, "inactive");
2887 else if (zvrf_ns_name(zvrf
))
2888 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2889 zvrf_ns_name(zvrf
));
2891 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2893 if (vrf_is_user_cfged(vrf
))
2894 vty_out(vty
, " (configured)");
2901 DEFUN (default_vrf_vni_mapping
,
2902 default_vrf_vni_mapping_cmd
,
2903 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2904 "VNI corresponding to the DEFAULT VRF\n"
2906 "Prefix routes only \n")
2909 char err
[ERR_STR_SZ
];
2910 struct zebra_vrf
*zvrf
= NULL
;
2911 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2914 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2921 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2924 vty_out(vty
, "%s\n", err
);
2931 DEFUN (no_default_vrf_vni_mapping
,
2932 no_default_vrf_vni_mapping_cmd
,
2933 "no vni " CMD_VNI_RANGE
,
2935 "VNI corresponding to DEFAULT VRF\n"
2939 char err
[ERR_STR_SZ
];
2940 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2941 struct zebra_vrf
*zvrf
= NULL
;
2943 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2947 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
, 0, 0);
2949 vty_out(vty
, "%s\n", err
);
2956 DEFUN (vrf_vni_mapping
,
2957 vrf_vni_mapping_cmd
,
2958 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2959 "VNI corresponding to tenant VRF\n"
2961 "prefix-routes-only\n")
2966 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2967 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2968 char err
[ERR_STR_SZ
];
2976 /* Mark as having FRR configuration */
2977 vrf_set_user_cfged(vrf
);
2978 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2981 vty_out(vty
, "%s\n", err
);
2988 DEFUN (no_vrf_vni_mapping
,
2989 no_vrf_vni_mapping_cmd
,
2990 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2992 "VNI corresponding to tenant VRF\n"
2994 "prefix-routes-only\n")
2998 char err
[ERR_STR_SZ
];
2999 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3001 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
3009 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
,
3010 ERR_STR_SZ
, filter
, 0);
3012 vty_out(vty
, "%s\n", err
);
3016 /* If no other FRR config for this VRF, mark accordingly. */
3017 if (!zebra_vrf_has_config(zvrf
))
3018 vrf_reset_user_cfged(vrf
);
3024 DEFUN (show_vrf_vni
,
3026 "show vrf vni [json]",
3033 struct zebra_vrf
*zvrf
;
3034 json_object
*json
= NULL
;
3035 json_object
*json_vrfs
= NULL
;
3036 uint8_t uj
= use_json(argc
, argv
);
3039 json
= json_object_new_object();
3040 json_vrfs
= json_object_new_array();
3044 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3045 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3047 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3052 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3056 json_object_object_add(json
, "vrfs", json_vrfs
);
3057 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3058 json
, JSON_C_TO_STRING_PRETTY
));
3059 json_object_free(json
);
3065 DEFUN (show_evpn_global
,
3066 show_evpn_global_cmd
,
3072 uint8_t uj
= use_json(argc
, argv
);
3074 zebra_vxlan_print_evpn(vty
, uj
);
3078 DEFUN (show_evpn_vni
,
3080 "show evpn vni [json]",
3083 "VxLAN information\n"
3086 struct zebra_vrf
*zvrf
;
3087 uint8_t uj
= use_json(argc
, argv
);
3089 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3090 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3094 DEFUN (show_evpn_vni_vni
,
3095 show_evpn_vni_vni_cmd
,
3096 "show evpn vni " CMD_VNI_RANGE
"[json]",
3099 "VxLAN Network Identifier\n"
3103 struct zebra_vrf
*zvrf
;
3105 uint8_t uj
= use_json(argc
, argv
);
3107 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3108 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3109 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
);
3113 DEFUN (show_evpn_rmac_vni_mac
,
3114 show_evpn_rmac_vni_mac_cmd
,
3115 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3122 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3127 uint8_t uj
= use_json(argc
, argv
);
3129 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3130 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3131 vty_out(vty
, "%% Malformed MAC address\n");
3134 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3138 DEFUN (show_evpn_rmac_vni
,
3139 show_evpn_rmac_vni_cmd
,
3140 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3149 uint8_t uj
= use_json(argc
, argv
);
3151 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3152 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3157 DEFUN (show_evpn_rmac_vni_all
,
3158 show_evpn_rmac_vni_all_cmd
,
3159 "show evpn rmac vni all [json]",
3167 uint8_t uj
= use_json(argc
, argv
);
3169 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3174 DEFUN (show_evpn_nh_vni_ip
,
3175 show_evpn_nh_vni_ip_cmd
,
3176 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3183 "Host address (ipv4 or ipv6)\n"
3188 uint8_t uj
= use_json(argc
, argv
);
3190 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3191 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3193 vty_out(vty
, "%% Malformed Neighbor address\n");
3196 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3201 DEFUN (show_evpn_nh_vni
,
3202 show_evpn_nh_vni_cmd
,
3203 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3212 uint8_t uj
= use_json(argc
, argv
);
3214 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3215 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3220 DEFUN (show_evpn_nh_vni_all
,
3221 show_evpn_nh_vni_all_cmd
,
3222 "show evpn next-hops vni all [json]",
3230 uint8_t uj
= use_json(argc
, argv
);
3232 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3237 DEFUN (show_evpn_mac_vni
,
3238 show_evpn_mac_vni_cmd
,
3239 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3243 "VxLAN Network Identifier\n"
3247 struct zebra_vrf
*zvrf
;
3249 uint8_t uj
= use_json(argc
, argv
);
3251 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3252 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3253 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3257 DEFUN (show_evpn_mac_vni_all
,
3258 show_evpn_mac_vni_all_cmd
,
3259 "show evpn mac vni all [json]",
3263 "VxLAN Network Identifier\n"
3267 struct zebra_vrf
*zvrf
;
3268 uint8_t uj
= use_json(argc
, argv
);
3270 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3271 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, uj
);
3275 DEFUN (show_evpn_mac_vni_all_vtep
,
3276 show_evpn_mac_vni_all_vtep_cmd
,
3277 "show evpn mac vni all vtep A.B.C.D [json]",
3281 "VxLAN Network Identifier\n"
3284 "Remote VTEP IP address\n"
3287 struct zebra_vrf
*zvrf
;
3288 struct in_addr vtep_ip
;
3289 uint8_t uj
= use_json(argc
, argv
);
3291 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3293 vty_out(vty
, "%% Malformed VTEP IP address\n");
3296 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3297 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3303 DEFUN (show_evpn_mac_vni_mac
,
3304 show_evpn_mac_vni_mac_cmd
,
3305 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD",
3309 "VxLAN Network Identifier\n"
3312 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
3314 struct zebra_vrf
*zvrf
;
3318 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3319 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3320 vty_out(vty
, "%% Malformed MAC address");
3323 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3324 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
);
3328 DEFUN (show_evpn_mac_vni_vtep
,
3329 show_evpn_mac_vni_vtep_cmd
,
3330 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3334 "VxLAN Network Identifier\n"
3337 "Remote VTEP IP address\n"
3340 struct zebra_vrf
*zvrf
;
3342 struct in_addr vtep_ip
;
3343 uint8_t uj
= use_json(argc
, argv
);
3345 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3346 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3348 vty_out(vty
, "%% Malformed VTEP IP address\n");
3352 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3353 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3357 DEFUN (show_evpn_neigh_vni
,
3358 show_evpn_neigh_vni_cmd
,
3359 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3362 "ARP and ND cache\n"
3363 "VxLAN Network Identifier\n"
3367 struct zebra_vrf
*zvrf
;
3369 uint8_t uj
= use_json(argc
, argv
);
3371 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3372 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3373 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3377 DEFUN (show_evpn_neigh_vni_all
,
3378 show_evpn_neigh_vni_all_cmd
,
3379 "show evpn arp-cache vni all [json]",
3382 "ARP and ND cache\n"
3383 "VxLAN Network Identifier\n"
3387 struct zebra_vrf
*zvrf
;
3388 uint8_t uj
= use_json(argc
, argv
);
3390 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3391 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, uj
);
3395 DEFUN (show_evpn_neigh_vni_neigh
,
3396 show_evpn_neigh_vni_neigh_cmd
,
3397 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3400 "ARP and ND cache\n"
3401 "VxLAN Network Identifier\n"
3404 "Neighbor address (IPv4 or IPv6 address)\n"
3407 struct zebra_vrf
*zvrf
;
3410 uint8_t uj
= use_json(argc
, argv
);
3412 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3413 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3415 vty_out(vty
, "%% Malformed Neighbor address\n");
3418 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3419 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3423 DEFUN (show_evpn_neigh_vni_vtep
,
3424 show_evpn_neigh_vni_vtep_cmd
,
3425 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3428 "ARP and ND cache\n"
3429 "VxLAN Network Identifier\n"
3432 "Remote VTEP IP address\n"
3435 struct zebra_vrf
*zvrf
;
3437 struct in_addr vtep_ip
;
3438 uint8_t uj
= use_json(argc
, argv
);
3440 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3441 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3443 vty_out(vty
, "%% Malformed VTEP IP address\n");
3447 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3448 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3452 /* policy routing contexts */
3453 DEFUN (show_pbr_ipset
,
3455 "show pbr ipset [WORD]",
3457 "Policy-Based Routing\n"
3458 "IPset Context information\n"
3459 "IPset Name information\n")
3463 found
= argv_find(argv
, argc
, "WORD", &idx
);
3465 zebra_pbr_show_ipset_list(vty
, NULL
);
3467 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3471 /* policy routing contexts */
3472 DEFUN (show_pbr_iptable
,
3473 show_pbr_iptable_cmd
,
3476 "Policy-Based Routing\n"
3477 "IPtable Context information\n")
3479 zebra_pbr_show_iptable(vty
);
3483 /* Static ip route configuration write function. */
3484 static int zebra_ip_config(struct vty
*vty
)
3488 write
+= zebra_import_table_config(vty
);
3493 DEFUN (ip_zebra_import_table_distance
,
3494 ip_zebra_import_table_distance_cmd
,
3495 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3497 "import routes from non-main kernel table\n"
3498 "kernel routing table id\n"
3499 "Distance for imported routes\n"
3500 "Default distance value\n"
3501 "route-map for filtering\n"
3504 uint32_t table_id
= 0;
3506 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3507 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3509 strmatch(argv
[argc
- 2]->text
, "route-map")
3510 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3514 if (argc
== 7 || (argc
== 5 && !rmap
))
3515 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3517 if (!is_zebra_valid_kernel_table(table_id
)) {
3519 "Invalid routing table ID, %d. Must be in range 1-252\n",
3522 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3526 if (is_zebra_main_routing_table(table_id
)) {
3528 "Invalid routing table ID, %d. Must be non-default table\n",
3531 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3535 ret
= zebra_import_table(AFI_IP
, table_id
, distance
, rmap
, 1);
3537 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3542 DEFUN_HIDDEN (zebra_packet_process
,
3543 zebra_packet_process_cmd
,
3544 "zebra zapi-packets (1-10000)",
3547 "Number of packets to process before relinquishing thread\n")
3549 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3551 atomic_store_explicit(&zebrad
.packets_to_process
, packets
,
3552 memory_order_relaxed
);
3557 DEFUN_HIDDEN (no_zebra_packet_process
,
3558 no_zebra_packet_process_cmd
,
3559 "no zebra zapi-packets [(1-10000)]",
3563 "Number of packets to process before relinquishing thread\n")
3565 atomic_store_explicit(&zebrad
.packets_to_process
,
3566 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3567 memory_order_relaxed
);
3572 DEFUN_HIDDEN (zebra_workqueue_timer
,
3573 zebra_workqueue_timer_cmd
,
3574 "zebra work-queue (0-10000)",
3577 "Time in milliseconds\n")
3579 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3580 zebrad
.ribq
->spec
.hold
= timer
;
3585 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3586 no_zebra_workqueue_timer_cmd
,
3587 "no zebra work-queue [(0-10000)]",
3591 "Time in milliseconds\n")
3593 zebrad
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3598 DEFUN (no_ip_zebra_import_table
,
3599 no_ip_zebra_import_table_cmd
,
3600 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3603 "import routes from non-main kernel table\n"
3604 "kernel routing table id\n"
3605 "Distance for imported routes\n"
3606 "Default distance value\n"
3607 "route-map for filtering\n"
3610 uint32_t table_id
= 0;
3611 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3613 if (!is_zebra_valid_kernel_table(table_id
)) {
3615 "Invalid routing table ID. Must be in range 1-252\n");
3619 if (is_zebra_main_routing_table(table_id
)) {
3621 "Invalid routing table ID, %d. Must be non-default table\n",
3626 if (!is_zebra_import_table_enabled(AFI_IP
, table_id
))
3629 return (zebra_import_table(AFI_IP
, table_id
, 0, NULL
, 0));
3632 static int config_write_protocol(struct vty
*vty
)
3635 vty_out(vty
, "allow-external-route-update\n");
3637 if (zebra_rnh_ip_default_route
)
3638 vty_out(vty
, "ip nht resolve-via-default\n");
3640 if (zebra_rnh_ipv6_default_route
)
3641 vty_out(vty
, "ipv6 nht resolve-via-default\n");
3643 if (zebrad
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3644 vty_out(vty
, "zebra work-queue %u\n", zebrad
.ribq
->spec
.hold
);
3646 if (zebrad
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3647 vty_out(vty
, "zebra zapi-packets %u\n",
3648 zebrad
.packets_to_process
);
3650 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3652 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3653 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3654 ipv4_multicast_mode
== MCAST_URIB_ONLY
3656 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3658 : ipv4_multicast_mode
3659 == MCAST_MIX_MRIB_FIRST
3661 : ipv4_multicast_mode
3662 == MCAST_MIX_DISTANCE
3666 zebra_routemap_config_write_protocol(vty
);
3672 /* Display default rtm_table for all clients. */
3677 "default routing table to use for all clients\n")
3679 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3683 DEFUN (config_table
,
3686 "Configure target kernel routing table\n"
3689 zebrad
.rtm_table_default
= strtol(argv
[1]->arg
, (char **)0, 10);
3693 DEFUN (no_config_table
,
3694 no_config_table_cmd
,
3695 "no table [TABLENO]",
3697 "Configure target kernel routing table\n"
3700 zebrad
.rtm_table_default
= 0;
3714 " Route Route Neighbor LSP LSP\n");
3716 "VRF Installs Removals Updates Installs Removals\n");
3718 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3719 struct zebra_vrf
*zvrf
= vrf
->info
;
3721 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
3722 " %10" PRIu64
" %10" PRIu64
"\n",
3723 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
3724 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
3725 zvrf
->lsp_removals
);
3731 DEFUN (ip_forwarding
,
3735 "Turn on IP forwarding\n")
3741 ret
= ipforward_on();
3744 vty_out(vty
, "Can't turn on IP forwarding\n");
3745 return CMD_WARNING_CONFIG_FAILED
;
3751 DEFUN (no_ip_forwarding
,
3752 no_ip_forwarding_cmd
,
3756 "Turn off IP forwarding\n")
3762 ret
= ipforward_off();
3765 vty_out(vty
, "Can't turn off IP forwarding\n");
3766 return CMD_WARNING_CONFIG_FAILED
;
3772 /* Only display ip forwarding is enabled or not. */
3773 DEFUN (show_ip_forwarding
,
3774 show_ip_forwarding_cmd
,
3775 "show ip forwarding",
3778 "IP forwarding status\n")
3785 vty_out(vty
, "IP forwarding is off\n");
3787 vty_out(vty
, "IP forwarding is on\n");
3791 /* Only display ipv6 forwarding is enabled or not. */
3792 DEFUN (show_ipv6_forwarding
,
3793 show_ipv6_forwarding_cmd
,
3794 "show ipv6 forwarding",
3796 "IPv6 information\n"
3797 "Forwarding status\n")
3801 ret
= ipforward_ipv6();
3805 vty_out(vty
, "ipv6 forwarding is unknown\n");
3808 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3811 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
3814 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3820 DEFUN (ipv6_forwarding
,
3821 ipv6_forwarding_cmd
,
3824 "Turn on IPv6 forwarding\n")
3828 ret
= ipforward_ipv6();
3830 ret
= ipforward_ipv6_on();
3833 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
3834 return CMD_WARNING_CONFIG_FAILED
;
3840 DEFUN (no_ipv6_forwarding
,
3841 no_ipv6_forwarding_cmd
,
3842 "no ipv6 forwarding",
3845 "Turn off IPv6 forwarding\n")
3849 ret
= ipforward_ipv6();
3851 ret
= ipforward_ipv6_off();
3854 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
3855 return CMD_WARNING_CONFIG_FAILED
;
3861 /* Table configuration write function. */
3862 static int config_write_table(struct vty
*vty
)
3864 if (zebrad
.rtm_table_default
)
3865 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3869 /* IPForwarding configuration write function. */
3870 static int config_write_forwarding(struct vty
*vty
)
3872 /* FIXME: Find better place for that. */
3873 router_id_write(vty
);
3876 vty_out(vty
, "no ip forwarding\n");
3877 if (!ipforward_ipv6())
3878 vty_out(vty
, "no ipv6 forwarding\n");
3879 vty_out(vty
, "!\n");
3883 /* IP node for static routes. */
3884 static struct cmd_node ip_node
= {IP_NODE
, "", 1};
3885 static struct cmd_node protocol_node
= {PROTOCOL_NODE
, "", 1};
3886 /* table node for routing tables. */
3887 static struct cmd_node table_node
= {TABLE_NODE
,
3888 "", /* This node has no interface. */
3890 static struct cmd_node forwarding_node
= {FORWARDING_NODE
,
3891 "", /* This node has no interface. */
3895 void zebra_vty_init(void)
3897 /* Install configuration write function. */
3898 install_node(&table_node
, config_write_table
);
3899 install_node(&forwarding_node
, config_write_forwarding
);
3901 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
3902 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
3903 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
3904 install_element(ENABLE_NODE
, &show_zebra_cmd
);
3907 install_element(VIEW_NODE
, &show_table_cmd
);
3908 install_element(CONFIG_NODE
, &config_table_cmd
);
3909 install_element(CONFIG_NODE
, &no_config_table_cmd
);
3910 #endif /* HAVE_NETLINK */
3912 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
3913 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
3914 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
3917 zebra_route_map_init();
3919 install_node(&ip_node
, zebra_ip_config
);
3920 install_node(&protocol_node
, config_write_protocol
);
3922 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
3923 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
3924 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
3925 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
3926 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
3927 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
3928 install_element(CONFIG_NODE
,
3929 &ip_route_address_interface_cmd
);
3930 install_element(CONFIG_NODE
, &ip_route_cmd
);
3931 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
3932 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
3933 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
3935 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
3936 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
3937 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
3938 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
3939 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
3940 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
3942 install_element(VIEW_NODE
, &show_vrf_cmd
);
3943 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
3944 install_element(VIEW_NODE
, &show_route_cmd
);
3945 install_element(VIEW_NODE
, &show_route_table_cmd
);
3946 if (vrf_is_backend_netns())
3947 install_element(VIEW_NODE
, &show_route_table_vrf_cmd
);
3948 install_element(VIEW_NODE
, &show_route_detail_cmd
);
3949 install_element(VIEW_NODE
, &show_route_summary_cmd
);
3950 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
3951 install_element(VIEW_NODE
, &show_ip_nht_vrf_all_cmd
);
3952 install_element(VIEW_NODE
, &show_ipv6_nht_cmd
);
3953 install_element(VIEW_NODE
, &show_ipv6_nht_vrf_all_cmd
);
3955 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
3956 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
3958 install_element(CONFIG_NODE
,
3959 &ipv6_route_blackhole_cmd
);
3960 install_element(CONFIG_NODE
,
3961 &ipv6_route_address_interface_cmd
);
3962 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
3963 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
3964 install_element(VRF_NODE
,
3965 &ipv6_route_address_interface_vrf_cmd
);
3966 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
3967 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
3968 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
3969 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
3970 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
3971 install_element(VIEW_NODE
, &show_ipv6_mroute_cmd
);
3973 /* Commands for VRF */
3974 install_element(VIEW_NODE
, &show_ipv6_mroute_vrf_all_cmd
);
3976 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
3977 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
3978 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
3979 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
3980 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
3981 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
3982 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
3983 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
3984 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
3985 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
3986 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
3987 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
3988 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
3989 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
3990 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
3991 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
3992 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
3993 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
3995 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
3996 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
3998 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
3999 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4000 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4001 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4003 static_list
= list_new();
4004 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
4005 static_list
->del
= (void (*)(void *))static_list_delete
;