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
);
263 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
264 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
265 XFREE(MTYPE_STATIC_ROUTE
, shr
);
267 * If a person enters the same line again
268 * we need to silently accept it
274 listnode_add_sort(static_list
, shr
);
279 static int zebra_static_route_leak(
280 struct vty
*vty
, struct zebra_vrf
*zvrf
, struct zebra_vrf
*nh_zvrf
,
281 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
282 const char *mask_str
, const char *src_str
, const char *gate_str
,
283 const char *ifname
, const char *flag_str
, const char *tag_str
,
284 const char *distance_str
, const char *label_str
, const char *table_str
)
288 struct prefix p
, src
;
289 struct prefix_ipv6
*src_p
= NULL
;
291 union g_addr
*gatep
= NULL
;
293 enum static_blackhole_type bh_type
= 0;
296 struct static_nh_label snh_label
;
297 uint32_t table_id
= 0;
299 ret
= str2prefix(dest_str
, &p
);
302 vty_out(vty
, "%% Malformed address\n");
304 zlog_warn("%s: Malformed address: %s",
305 __PRETTY_FUNCTION__
, dest_str
);
306 return CMD_WARNING_CONFIG_FAILED
;
311 /* Cisco like mask notation. */
313 ret
= inet_aton(mask_str
, &mask
);
316 vty_out(vty
, "%% Malformed address\n");
318 zlog_warn("%s: Malformed address: %s",
321 return CMD_WARNING_CONFIG_FAILED
;
323 p
.prefixlen
= ip_masklen(mask
);
327 /* srcdest routing */
329 ret
= str2prefix(src_str
, &src
);
330 if (ret
<= 0 || src
.family
!= AF_INET6
) {
333 "%% Malformed source address\n");
336 "%s: Malformed Source address: %s",
337 __PRETTY_FUNCTION__
, src_str
);
338 return CMD_WARNING_CONFIG_FAILED
;
340 src_p
= (struct prefix_ipv6
*)&src
;
347 /* Apply mask for given prefix. */
350 if (zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
351 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
352 vrf_set_user_cfged(zvrf
->vrf
);
353 return zebra_static_route_holdem(
354 zvrf
, nh_zvrf
, afi
, safi
, negate
, &p
, dest_str
,
355 mask_str
, src_str
, gate_str
, ifname
, flag_str
, tag_str
,
356 distance_str
, label_str
, table_str
);
359 /* table configured. check consistent with vrf config
361 if (zvrf
->table_id
!= RT_TABLE_MAIN
&&
362 zvrf
->table_id
!= zebrad
.rtm_table_default
) {
365 "%% Table %s overlaps vrf table %u\n",
366 table_str
, zvrf
->table_id
);
369 "%s: Table %s overlaps vrf table %u",
371 table_str
, zvrf
->table_id
);
372 return CMD_WARNING_CONFIG_FAILED
;
376 /* Administrative distance. */
378 distance
= atoi(distance_str
);
380 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
384 tag
= strtoul(tag_str
, NULL
, 10);
387 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
392 "%% MPLS not turned on in kernel, ignoring command\n");
395 "%s: MPLS not turned on in kernel ignoring static route to %s",
396 __PRETTY_FUNCTION__
, dest_str
);
397 return CMD_WARNING_CONFIG_FAILED
;
399 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
405 vty_out(vty
, "%% Malformed label(s)\n");
408 "%s: Malformed labels specified for route %s",
409 __PRETTY_FUNCTION__
, dest_str
);
414 "%% Cannot use reserved label(s) (%d-%d)\n",
415 MPLS_LABEL_RESERVED_MIN
,
416 MPLS_LABEL_RESERVED_MAX
);
419 "%s: Cannot use reserved labels (%d-%d) for %s",
421 MPLS_LABEL_RESERVED_MIN
,
422 MPLS_LABEL_RESERVED_MAX
,
428 "%% Too many labels. Enter %d or fewer\n",
432 "%s: Too many labels, Enter %d or fewer for %s",
434 MPLS_MAX_LABELS
, dest_str
);
437 return CMD_WARNING_CONFIG_FAILED
;
442 table_id
= atol(table_str
);
444 /* Null0 static route. */
445 if (ifname
!= NULL
) {
446 if (strncasecmp(ifname
, "Null0", strlen(ifname
)) == 0
447 || strncasecmp(ifname
, "reject", strlen(ifname
)) == 0
448 || strncasecmp(ifname
, "blackhole", strlen(ifname
)) == 0) {
451 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
454 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
455 __PRETTY_FUNCTION__
, dest_str
);
456 return CMD_WARNING_CONFIG_FAILED
;
462 switch (flag_str
[0]) {
464 bh_type
= STATIC_BLACKHOLE_REJECT
;
467 bh_type
= STATIC_BLACKHOLE_DROP
;
470 bh_type
= STATIC_BLACKHOLE_NULL
;
474 vty_out(vty
, "%% Malformed flag %s \n",
477 zlog_warn("%s: Malformed flag %s for %s",
478 __PRETTY_FUNCTION__
, flag_str
,
480 return CMD_WARNING_CONFIG_FAILED
;
485 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
488 "%% Malformed nexthop address %s\n",
492 "%s: Malformed nexthop address %s for %s",
493 __PRETTY_FUNCTION__
, gate_str
,
495 return CMD_WARNING_CONFIG_FAILED
;
500 if (gate_str
== NULL
&& ifname
== NULL
)
501 type
= STATIC_BLACKHOLE
;
502 else if (gate_str
&& ifname
) {
504 type
= STATIC_IPV4_GATEWAY_IFNAME
;
506 type
= STATIC_IPV6_GATEWAY_IFNAME
;
508 type
= STATIC_IFNAME
;
511 type
= STATIC_IPV4_GATEWAY
;
513 type
= STATIC_IPV6_GATEWAY
;
517 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
518 bh_type
, tag
, distance
, zvrf
, nh_zvrf
,
519 &snh_label
, table_id
);
520 /* Mark as having FRR configuration */
521 vrf_set_user_cfged(zvrf
->vrf
);
523 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
524 tag
, distance
, zvrf
, &snh_label
, table_id
);
525 /* If no other FRR config for this VRF, mark accordingly. */
526 if (!zebra_vrf_has_config(zvrf
))
527 vrf_reset_user_cfged(zvrf
->vrf
);
533 static struct zebra_vrf
*zebra_vty_get_unknown_vrf(struct vty
*vty
,
534 const char *vrf_name
)
536 struct zebra_vrf
*zvrf
;
539 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
544 vrf
= vrf_get(VRF_UNKNOWN
, vrf_name
);
546 vty_out(vty
, "%% Could not create vrf %s\n", vrf_name
);
551 vty_out(vty
, "%% Could not create vrf-info %s\n",
555 /* Mark as having FRR configuration */
556 vrf_set_user_cfged(vrf
);
561 static int zebra_static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
562 const char *negate
, const char *dest_str
,
563 const char *mask_str
, const char *src_str
,
564 const char *gate_str
, const char *ifname
,
565 const char *flag_str
, const char *tag_str
,
566 const char *distance_str
, const char *vrf_name
,
567 const char *label_str
, const char *table_str
)
569 struct zebra_vrf
*zvrf
;
572 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
574 /* When trying to delete, the VRF must exist. */
575 if (negate
&& !zvrf
) {
576 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
577 return CMD_WARNING_CONFIG_FAILED
;
580 /* When trying to create, create the VRF if it doesn't exist.
581 * Note: The VRF isn't active until we hear about it from the kernel.
584 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf_name
);
586 return CMD_WARNING_CONFIG_FAILED
;
588 return zebra_static_route_leak(
589 vty
, zvrf
, zvrf
, afi
, safi
, negate
, dest_str
, mask_str
, src_str
,
590 gate_str
, ifname
, flag_str
, tag_str
, distance_str
, label_str
,
594 void static_config_install_delayed_routes(struct zebra_vrf
*zvrf
)
596 struct listnode
*node
, *nnode
;
597 struct static_hold_route
*shr
;
598 struct zebra_vrf
*ozvrf
, *nh_zvrf
;
601 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
602 ozvrf
= zebra_vrf_lookup_by_name(shr
->vrf_name
);
603 nh_zvrf
= zebra_vrf_lookup_by_name(shr
->nhvrf_name
);
605 if (ozvrf
!= zvrf
&& nh_zvrf
!= zvrf
)
608 if (ozvrf
->vrf
->vrf_id
== VRF_UNKNOWN
609 || nh_zvrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
612 installed
= zebra_static_route_leak(
613 NULL
, ozvrf
, nh_zvrf
, shr
->afi
, shr
->safi
, NULL
,
614 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
615 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
616 shr
->distance_str
, shr
->label_str
, shr
->table_str
);
618 if (installed
!= CMD_SUCCESS
)
620 "%s: Attempt to install %s as a route and it was rejected",
621 __PRETTY_FUNCTION__
, shr
->dest_str
);
622 listnode_delete(static_list
, shr
);
623 static_list_delete(shr
);
626 /* Static unicast routes for multicast RPF lookup. */
627 DEFPY (ip_mroute_dist
,
629 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
632 "Configure static unicast route into MRIB for multicast RPF lookup\n"
633 "IP destination prefix (e.g. 10.0.0.0/8)\n"
635 "Nexthop interface name\n"
638 return zebra_static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
639 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
640 distance_str
, NULL
, NULL
, NULL
);
643 DEFUN (ip_multicast_mode
,
644 ip_multicast_mode_cmd
,
645 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
647 "Multicast options\n"
648 "RPF lookup behavior\n"
649 "Lookup in unicast RIB only\n"
650 "Lookup in multicast RIB only\n"
651 "Try multicast RIB first, fall back to unicast RIB\n"
652 "Lookup both, use entry with lower distance\n"
653 "Lookup both, use entry with longer prefix\n")
655 char *mode
= argv
[3]->text
;
657 if (strmatch(mode
, "urib-only"))
658 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
659 else if (strmatch(mode
, "mrib-only"))
660 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
661 else if (strmatch(mode
, "mrib-then-urib"))
662 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
663 else if (strmatch(mode
, "lower-distance"))
664 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
665 else if (strmatch(mode
, "longer-prefix"))
666 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
668 vty_out(vty
, "Invalid mode specified\n");
669 return CMD_WARNING_CONFIG_FAILED
;
675 DEFUN (no_ip_multicast_mode
,
676 no_ip_multicast_mode_cmd
,
677 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
680 "Multicast options\n"
681 "RPF lookup behavior\n"
682 "Lookup in unicast RIB only\n"
683 "Lookup in multicast RIB only\n"
684 "Try multicast RIB first, fall back to unicast RIB\n"
685 "Lookup both, use entry with lower distance\n"
686 "Lookup both, use entry with longer prefix\n")
688 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
695 "show ip rpf [json]",
698 "Display RPF information for multicast source\n"
701 int uj
= use_json(argc
, argv
);
702 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
703 false, uj
, 0, NULL
, false, 0, 0);
706 DEFUN (show_ip_rpf_addr
,
707 show_ip_rpf_addr_cmd
,
708 "show ip rpf A.B.C.D",
711 "Display RPF information for multicast source\n"
712 "IP multicast source address (e.g. 10.0.0.0)\n")
716 struct route_node
*rn
;
717 struct route_entry
*re
;
720 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
722 vty_out(vty
, "%% Malformed address\n");
726 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
729 vty_show_ip_route_detail(vty
, rn
, 1);
731 vty_out(vty
, "%% No match for RPF lookup\n");
736 /* Static route configuration. */
737 DEFPY(ip_route_blackhole
,
738 ip_route_blackhole_cmd
,
740 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
741 <reject|blackhole>$flag \
747 |table (1-4294967295) \
750 "Establish static routes\n"
751 "IP destination prefix (e.g. 10.0.0.0/8)\n"
752 "IP destination prefix\n"
753 "IP destination prefix mask\n"
754 "Emit an ICMP unreachable when matched\n"
755 "Silently discard pkts when matched\n"
756 "Set tag for this route\n"
758 "Distance value for this route\n"
761 "Table to configure\n"
762 "The table number to configure\n")
764 if (table_str
&& !vrf_is_backend_netns()) {
766 "%% table param only available when running on netns-based vrfs\n");
767 return CMD_WARNING_CONFIG_FAILED
;
769 return zebra_static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
770 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
771 distance_str
, vrf
, label
, table_str
);
774 DEFPY(ip_route_blackhole_vrf
,
775 ip_route_blackhole_vrf_cmd
,
777 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
778 <reject|blackhole>$flag \
783 |table (1-4294967295) \
786 "Establish static routes\n"
787 "IP destination prefix (e.g. 10.0.0.0/8)\n"
788 "IP destination prefix\n"
789 "IP destination prefix mask\n"
790 "Emit an ICMP unreachable when matched\n"
791 "Silently discard pkts when matched\n"
792 "Set tag for this route\n"
794 "Distance value for this route\n"
796 "Table to configure\n"
797 "The table number to configure\n")
799 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
800 struct zebra_vrf
*zvrf
= vrf
->info
;
802 if (table_str
&& !vrf_is_backend_netns()) {
804 "%% table param only available when running on netns-based vrfs\n");
805 return CMD_WARNING_CONFIG_FAILED
;
808 * Coverity is complaining that prefix could
809 * be dereferenced, but we know that prefix will
810 * valid. Add an assert to make it happy
813 return zebra_static_route_leak(vty
, zvrf
, zvrf
, AFI_IP
, SAFI_UNICAST
,
814 no
, prefix
, mask_str
, NULL
, NULL
, NULL
,
815 flag
, tag_str
, distance_str
, label
, table_str
);
818 DEFPY(ip_route_address_interface
,
819 ip_route_address_interface_cmd
,
821 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
829 |table (1-4294967295) \
833 "Establish static routes\n"
834 "IP destination prefix (e.g. 10.0.0.0/8)\n"
835 "IP destination prefix\n"
836 "IP destination prefix mask\n"
837 "IP gateway address\n"
838 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
840 "Set tag for this route\n"
842 "Distance value for this route\n"
845 "Table to configure\n"
846 "The table number to configure\n"
849 struct zebra_vrf
*zvrf
;
850 struct zebra_vrf
*nh_zvrf
;
852 const char *flag
= NULL
;
853 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
858 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
860 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
861 return CMD_WARNING_CONFIG_FAILED
;
864 if (table_str
&& !vrf_is_backend_netns()) {
866 "%% table param only available when running on netns-based vrfs\n");
867 return CMD_WARNING_CONFIG_FAILED
;
871 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
876 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
877 return CMD_WARNING_CONFIG_FAILED
;
880 return zebra_static_route_leak(
881 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
882 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
886 DEFPY(ip_route_address_interface_vrf
,
887 ip_route_address_interface_vrf_cmd
,
889 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
896 |table (1-4294967295) \
900 "Establish static routes\n"
901 "IP destination prefix (e.g. 10.0.0.0/8)\n"
902 "IP destination prefix\n"
903 "IP destination prefix mask\n"
904 "IP gateway address\n"
905 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
907 "Set tag for this route\n"
909 "Distance value for this route\n"
911 "Table to configure\n"
912 "The table number to configure\n"
915 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
916 const char *flag
= NULL
;
917 struct zebra_vrf
*zvrf
= vrf
->info
;
918 struct zebra_vrf
*nh_zvrf
;
920 if (table_str
&& !vrf_is_backend_netns()) {
922 "%% table param only available when running on netns-based vrfs\n");
923 return CMD_WARNING_CONFIG_FAILED
;
926 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
932 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
937 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
938 return CMD_WARNING_CONFIG_FAILED
;
941 return zebra_static_route_leak(
942 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
943 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
950 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
951 <A.B.C.D$gate|INTERFACE$ifname> \
957 |table (1-4294967295) \
961 "Establish static routes\n"
962 "IP destination prefix (e.g. 10.0.0.0/8)\n"
963 "IP destination prefix\n"
964 "IP destination prefix mask\n"
965 "IP gateway address\n"
966 "IP gateway interface name\n"
967 "Set tag for this route\n"
969 "Distance value for this route\n"
972 "Table to configure\n"
973 "The table number to configure\n"
976 struct zebra_vrf
*zvrf
;
977 struct zebra_vrf
*nh_zvrf
;
978 const char *flag
= NULL
;
980 if (table_str
&& !vrf_is_backend_netns()) {
982 "%% table param only available when running on netns-based vrfs\n");
983 return CMD_WARNING_CONFIG_FAILED
;
986 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
991 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
993 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
994 return CMD_WARNING_CONFIG_FAILED
;
998 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1003 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1004 return CMD_WARNING_CONFIG_FAILED
;
1008 return zebra_static_route_leak(
1009 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1010 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1017 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1018 <A.B.C.D$gate|INTERFACE$ifname> \
1020 tag (1-4294967295) \
1023 |table (1-4294967295) \
1027 "Establish static routes\n"
1028 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1029 "IP destination prefix\n"
1030 "IP destination prefix mask\n"
1031 "IP gateway address\n"
1032 "IP gateway interface name\n"
1033 "Set tag for this route\n"
1035 "Distance value for this route\n"
1037 "Table to configure\n"
1038 "The table number to configure\n"
1041 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1042 struct zebra_vrf
*zvrf
= vrf
->info
;
1043 struct zebra_vrf
*nh_zvrf
;
1044 const char *flag
= NULL
;
1046 if (table_str
&& !vrf_is_backend_netns()) {
1048 "%% table param only available when running on netns-based vrfs\n");
1049 return CMD_WARNING_CONFIG_FAILED
;
1052 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1058 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1063 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1064 return CMD_WARNING_CONFIG_FAILED
;
1067 return zebra_static_route_leak(
1068 vty
, zvrf
, nh_zvrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1069 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1073 /* New RIB. Detailed information for IPv4 route. */
1074 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
1077 struct route_entry
*re
;
1078 struct nexthop
*nexthop
;
1079 char buf
[SRCDEST2STR_BUFFER
];
1080 struct zebra_vrf
*zvrf
;
1082 RNODE_FOREACH_RE (rn
, re
) {
1083 const char *mcast_info
= "";
1085 rib_table_info_t
*info
= srcdest_rnode_table_info(rn
);
1086 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
1087 ? " using Multicast RIB"
1088 : " using Unicast RIB";
1091 vty_out(vty
, "Routing entry for %s%s\n",
1092 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
1093 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
1095 vty_out(vty
, "[%d]", re
->instance
);
1097 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
1100 vty_out(vty
, ", tag %u", re
->tag
);
1101 #if defined(SUPPORT_REALMS)
1102 if (re
->tag
> 0 && re
->tag
<= 255)
1103 vty_out(vty
, "(realm)");
1107 vty_out(vty
, ", mtu %u", re
->mtu
);
1108 if (re
->vrf_id
!= VRF_DEFAULT
) {
1109 zvrf
= vrf_info_lookup(re
->vrf_id
);
1110 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
1112 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1113 vty_out(vty
, ", best");
1119 uptime
= time(NULL
);
1120 uptime
-= re
->uptime
;
1121 tm
= gmtime(&uptime
);
1123 vty_out(vty
, " Last update ");
1125 if (uptime
< ONE_DAY_SECOND
)
1126 vty_out(vty
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1128 else if (uptime
< ONE_WEEK_SECOND
)
1129 vty_out(vty
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1132 vty_out(vty
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1133 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1135 vty_out(vty
, " ago\n");
1137 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1140 vty_out(vty
, " %c%s",
1141 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1142 ? CHECK_FLAG(nexthop
->flags
,
1143 NEXTHOP_FLAG_DUPLICATE
)
1147 nexthop
->rparent
? " " : "");
1149 switch (nexthop
->type
) {
1150 case NEXTHOP_TYPE_IPV4
:
1151 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1153 inet_ntoa(nexthop
->gate
.ipv4
));
1154 if (nexthop
->ifindex
)
1155 vty_out(vty
, ", via %s",
1160 case NEXTHOP_TYPE_IPV6
:
1161 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1163 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1165 if (nexthop
->ifindex
)
1166 vty_out(vty
, ", via %s",
1171 case NEXTHOP_TYPE_IFINDEX
:
1172 vty_out(vty
, " directly connected, %s",
1173 ifindex2ifname(nexthop
->ifindex
,
1176 case NEXTHOP_TYPE_BLACKHOLE
:
1177 vty_out(vty
, " unreachable");
1178 switch (nexthop
->bh_type
) {
1179 case BLACKHOLE_REJECT
:
1180 vty_out(vty
, " (ICMP unreachable)");
1182 case BLACKHOLE_ADMINPROHIB
:
1184 " (ICMP admin-prohibited)");
1186 case BLACKHOLE_NULL
:
1187 vty_out(vty
, " (blackhole)");
1189 case BLACKHOLE_UNSPEC
:
1197 if (re
->vrf_id
!= nexthop
->vrf_id
) {
1199 vrf_lookup_by_id(nexthop
->vrf_id
);
1202 vty_out(vty
, "(vrf %s)", vrf
->name
);
1204 vty_out(vty
, "(vrf UKNOWN)");
1207 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1208 vty_out(vty
, " (duplicate nexthop removed)");
1210 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1211 vty_out(vty
, " inactive");
1213 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1214 vty_out(vty
, " onlink");
1216 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1217 vty_out(vty
, " (recursive)");
1219 switch (nexthop
->type
) {
1220 case NEXTHOP_TYPE_IPV4
:
1221 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1222 if (nexthop
->src
.ipv4
.s_addr
) {
1223 if (inet_ntop(AF_INET
,
1225 addrstr
, sizeof addrstr
))
1226 vty_out(vty
, ", src %s",
1230 case NEXTHOP_TYPE_IPV6
:
1231 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1232 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1234 if (inet_ntop(AF_INET6
,
1236 addrstr
, sizeof addrstr
))
1237 vty_out(vty
, ", src %s",
1245 if (re
->nexthop_mtu
)
1246 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
1248 /* Label information */
1249 if (nexthop
->nh_label
1250 && nexthop
->nh_label
->num_labels
) {
1251 vty_out(vty
, ", label %s",
1253 nexthop
->nh_label
->num_labels
,
1254 nexthop
->nh_label
->label
, buf
,
1264 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
1265 struct route_entry
*re
, json_object
*json
)
1267 struct nexthop
*nexthop
;
1269 char buf
[SRCDEST2STR_BUFFER
];
1270 json_object
*json_nexthops
= NULL
;
1271 json_object
*json_nexthop
= NULL
;
1272 json_object
*json_route
= NULL
;
1273 json_object
*json_labels
= NULL
;
1277 uptime
= time(NULL
);
1278 uptime
-= re
->uptime
;
1279 tm
= gmtime(&uptime
);
1282 json_route
= json_object_new_object();
1283 json_nexthops
= json_object_new_array();
1285 json_object_string_add(json_route
, "prefix",
1286 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1287 json_object_string_add(json_route
, "protocol",
1288 zebra_route_string(re
->type
));
1291 json_object_int_add(json_route
, "instance",
1295 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
1297 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
1298 json_object_boolean_true_add(json_route
, "selected");
1300 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
1301 json_object_int_add(json_route
, "distance",
1303 json_object_int_add(json_route
, "metric", re
->metric
);
1306 json_object_int_add(json_route
, "internalStatus",
1308 json_object_int_add(json_route
, "internalFlags",
1310 if (uptime
< ONE_DAY_SECOND
)
1311 sprintf(buf
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
1313 else if (uptime
< ONE_WEEK_SECOND
)
1314 sprintf(buf
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
1317 sprintf(buf
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
1318 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1321 json_object_string_add(json_route
, "uptime", buf
);
1323 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1324 json_nexthop
= json_object_new_object();
1326 json_object_int_add(json_nexthop
, "flags",
1329 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1330 json_object_boolean_true_add(json_nexthop
,
1333 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1334 json_object_boolean_true_add(json_nexthop
,
1337 switch (nexthop
->type
) {
1338 case NEXTHOP_TYPE_IPV4
:
1339 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1340 json_object_string_add(
1342 inet_ntoa(nexthop
->gate
.ipv4
));
1343 json_object_string_add(json_nexthop
, "afi",
1346 if (nexthop
->ifindex
) {
1347 json_object_int_add(json_nexthop
,
1350 json_object_string_add(
1351 json_nexthop
, "interfaceName",
1357 case NEXTHOP_TYPE_IPV6
:
1358 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1359 json_object_string_add(
1361 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
1363 json_object_string_add(json_nexthop
, "afi",
1366 if (nexthop
->ifindex
) {
1367 json_object_int_add(json_nexthop
,
1370 json_object_string_add(
1371 json_nexthop
, "interfaceName",
1378 case NEXTHOP_TYPE_IFINDEX
:
1379 json_object_boolean_true_add(
1380 json_nexthop
, "directlyConnected");
1381 json_object_int_add(json_nexthop
,
1384 json_object_string_add(
1385 json_nexthop
, "interfaceName",
1386 ifindex2ifname(nexthop
->ifindex
,
1389 case NEXTHOP_TYPE_BLACKHOLE
:
1390 json_object_boolean_true_add(json_nexthop
,
1392 switch (nexthop
->bh_type
) {
1393 case BLACKHOLE_REJECT
:
1394 json_object_boolean_true_add(
1395 json_nexthop
, "reject");
1397 case BLACKHOLE_ADMINPROHIB
:
1398 json_object_boolean_true_add(
1400 "admin-prohibited");
1402 case BLACKHOLE_NULL
:
1403 json_object_boolean_true_add(
1404 json_nexthop
, "blackhole");
1406 case BLACKHOLE_UNSPEC
:
1414 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1416 vrf_lookup_by_id(nexthop
->vrf_id
);
1418 json_object_string_add(json_nexthop
, "vrf",
1421 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
1422 json_object_boolean_true_add(json_nexthop
,
1425 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1426 json_object_boolean_true_add(json_nexthop
,
1429 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1430 json_object_boolean_true_add(json_nexthop
,
1433 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1434 json_object_boolean_true_add(json_nexthop
,
1437 switch (nexthop
->type
) {
1438 case NEXTHOP_TYPE_IPV4
:
1439 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1440 if (nexthop
->src
.ipv4
.s_addr
) {
1441 if (inet_ntop(AF_INET
,
1442 &nexthop
->src
.ipv4
, buf
,
1444 json_object_string_add(
1445 json_nexthop
, "source",
1449 case NEXTHOP_TYPE_IPV6
:
1450 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1451 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
1453 if (inet_ntop(AF_INET6
,
1454 &nexthop
->src
.ipv6
, buf
,
1456 json_object_string_add(
1457 json_nexthop
, "source",
1465 if (nexthop
->nh_label
1466 && nexthop
->nh_label
->num_labels
) {
1467 json_labels
= json_object_new_array();
1469 for (int label_index
= 0;
1471 < nexthop
->nh_label
->num_labels
;
1473 json_object_array_add(
1475 json_object_new_int(
1476 nexthop
->nh_label
->label
1479 json_object_object_add(json_nexthop
, "labels",
1483 json_object_array_add(json_nexthops
, json_nexthop
);
1486 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1487 json_object_array_add(json
, json_route
);
1491 /* Nexthop information. */
1492 for (ALL_NEXTHOPS(re
->ng
, nexthop
)) {
1493 if (nexthop
== re
->ng
.nexthop
) {
1494 /* Prefix information. */
1495 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1497 len
+= vty_out(vty
, "[%d]", re
->instance
);
1500 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)
1503 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1506 srcdest_rnode2str(rn
, buf
, sizeof buf
));
1508 /* Distance and metric display. */
1509 if (re
->type
!= ZEBRA_ROUTE_CONNECT
)
1510 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1513 vty_out(vty
, " %c%*c",
1514 CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)
1515 ? CHECK_FLAG(nexthop
->flags
,
1516 NEXTHOP_FLAG_DUPLICATE
)
1520 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1523 switch (nexthop
->type
) {
1524 case NEXTHOP_TYPE_IPV4
:
1525 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1526 vty_out(vty
, " via %s", inet_ntoa(nexthop
->gate
.ipv4
));
1527 if (nexthop
->ifindex
)
1528 vty_out(vty
, ", %s",
1529 ifindex2ifname(nexthop
->ifindex
,
1532 case NEXTHOP_TYPE_IPV6
:
1533 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1534 vty_out(vty
, " via %s",
1535 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
1537 if (nexthop
->ifindex
)
1538 vty_out(vty
, ", %s",
1539 ifindex2ifname(nexthop
->ifindex
,
1543 case NEXTHOP_TYPE_IFINDEX
:
1544 vty_out(vty
, " is directly connected, %s",
1545 ifindex2ifname(nexthop
->ifindex
,
1548 case NEXTHOP_TYPE_BLACKHOLE
:
1549 vty_out(vty
, " unreachable");
1550 switch (nexthop
->bh_type
) {
1551 case BLACKHOLE_REJECT
:
1552 vty_out(vty
, " (ICMP unreachable)");
1554 case BLACKHOLE_ADMINPROHIB
:
1555 vty_out(vty
, " (ICMP admin-prohibited)");
1557 case BLACKHOLE_NULL
:
1558 vty_out(vty
, " (blackhole)");
1560 case BLACKHOLE_UNSPEC
:
1568 if (nexthop
->vrf_id
!= re
->vrf_id
) {
1569 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
1572 vty_out(vty
, "(vrf %s)", vrf
->name
);
1574 vty_out(vty
, "(vrf UKNOWN)");
1577 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1578 vty_out(vty
, " inactive");
1580 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1581 vty_out(vty
, " onlink");
1583 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1584 vty_out(vty
, " (recursive)");
1586 switch (nexthop
->type
) {
1587 case NEXTHOP_TYPE_IPV4
:
1588 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1589 if (nexthop
->src
.ipv4
.s_addr
) {
1590 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
1592 vty_out(vty
, ", src %s", buf
);
1595 case NEXTHOP_TYPE_IPV6
:
1596 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1597 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
1598 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
1600 vty_out(vty
, ", src %s", buf
);
1607 /* Label information */
1608 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
1609 vty_out(vty
, ", label %s",
1610 mpls_label2str(nexthop
->nh_label
->num_labels
,
1611 nexthop
->nh_label
->label
, buf
,
1615 if (uptime
< ONE_DAY_SECOND
)
1616 vty_out(vty
, ", %02d:%02d:%02d", tm
->tm_hour
,
1617 tm
->tm_min
, tm
->tm_sec
);
1618 else if (uptime
< ONE_WEEK_SECOND
)
1619 vty_out(vty
, ", %dd%02dh%02dm", tm
->tm_yday
,
1620 tm
->tm_hour
, tm
->tm_min
);
1622 vty_out(vty
, ", %02dw%dd%02dh", tm
->tm_yday
/ 7,
1623 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7),
1629 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1630 struct route_table
*table
, afi_t afi
,
1631 bool use_fib
, route_tag_t tag
,
1632 const struct prefix
*longer_prefix_p
,
1633 bool supernets_only
, int type
,
1634 unsigned short ospf_instance_id
,
1637 struct route_node
*rn
;
1638 struct route_entry
*re
;
1641 json_object
*json
= NULL
;
1642 json_object
*json_prefix
= NULL
;
1647 json
= json_object_new_object();
1649 /* Show all routes. */
1650 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
1651 dest
= rib_dest_from_rnode(rn
);
1653 RNODE_FOREACH_RE (rn
, re
) {
1654 if (use_fib
&& re
!= dest
->selected_fib
)
1657 if (tag
&& re
->tag
!= tag
)
1661 && !prefix_match(longer_prefix_p
, &rn
->p
))
1664 /* This can only be true when the afi is IPv4 */
1665 if (supernets_only
) {
1666 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1668 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1671 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1674 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1678 if (type
&& re
->type
!= type
)
1681 if (ospf_instance_id
1682 && (re
->type
!= ZEBRA_ROUTE_OSPF
1683 || re
->instance
!= ospf_instance_id
))
1688 json_prefix
= json_object_new_array();
1693 SHOW_ROUTE_V4_HEADER
);
1696 SHOW_ROUTE_V6_HEADER
);
1698 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1699 vty_out(vty
, "\nVRF %s:\n",
1706 vty_show_ip_route(vty
, rn
, re
, json_prefix
);
1710 prefix2str(&rn
->p
, buf
, sizeof buf
);
1711 json_object_object_add(json
, buf
, json_prefix
);
1717 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1718 json
, JSON_C_TO_STRING_PRETTY
));
1719 json_object_free(json
);
1723 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1724 safi_t safi
, bool use_fib
, uint8_t use_json
,
1726 const struct prefix
*longer_prefix_p
,
1727 bool supernets_only
, int type
,
1728 unsigned short ospf_instance_id
)
1730 struct route_table
*table
;
1731 struct zebra_vrf
*zvrf
= NULL
;
1733 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1735 vty_out(vty
, "{}\n");
1737 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1741 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1743 vty_out(vty
, "{}\n");
1745 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1749 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1752 vty_out(vty
, "{}\n");
1756 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1757 longer_prefix_p
, supernets_only
, type
,
1758 ospf_instance_id
, use_json
);
1763 DEFPY (show_route_table
,
1764 show_route_table_cmd
,
1765 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1769 "IP routing table\n"
1770 "Table to display\n"
1771 "The table number to display, if available\n"
1774 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1775 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1776 struct route_table
*t
;
1778 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1780 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1786 DEFPY (show_route_table_vrf
,
1787 show_route_table_vrf_cmd
,
1788 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
1792 "IP routing table\n"
1793 "Table to display\n"
1794 "The table number to display, if available\n"
1798 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1799 struct zebra_vrf
*zvrf
;
1800 struct route_table
*t
;
1801 vrf_id_t vrf_id
= VRF_DEFAULT
;
1804 VRF_GET_ID(vrf_id
, vrf_name
);
1805 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
1807 t
= zebra_ns_find_table(zvrf
->zns
, table
, afi
);
1809 do_show_route_helper(vty
, zvrf
, t
, afi
, false, 0, false, false,
1817 "show ip nht [vrf NAME]",
1820 "IP nexthop tracking table\n"
1824 vrf_id_t vrf_id
= VRF_DEFAULT
;
1827 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1829 zebra_print_rnh_table(vrf_id
, AF_INET
, vty
, RNH_NEXTHOP_TYPE
);
1834 DEFUN (show_ip_nht_vrf_all
,
1835 show_ip_nht_vrf_all_cmd
,
1836 "show ip nht vrf all",
1839 "IP nexthop tracking table\n"
1840 VRF_ALL_CMD_HELP_STR
)
1843 struct zebra_vrf
*zvrf
;
1845 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1846 if ((zvrf
= vrf
->info
) != NULL
) {
1847 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1848 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET
, vty
,
1855 DEFUN (show_ipv6_nht
,
1857 "show ipv6 nht [vrf NAME]",
1860 "IPv6 nexthop tracking table\n"
1864 vrf_id_t vrf_id
= VRF_DEFAULT
;
1867 VRF_GET_ID(vrf_id
, argv
[idx_vrf
]->arg
);
1869 zebra_print_rnh_table(vrf_id
, AF_INET6
, vty
, RNH_NEXTHOP_TYPE
);
1874 DEFUN (show_ipv6_nht_vrf_all
,
1875 show_ipv6_nht_vrf_all_cmd
,
1876 "show ipv6 nht vrf all",
1879 "IPv6 nexthop tracking table\n"
1880 VRF_ALL_CMD_HELP_STR
)
1883 struct zebra_vrf
*zvrf
;
1885 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1886 if ((zvrf
= vrf
->info
) != NULL
) {
1887 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1888 zebra_print_rnh_table(zvrf_id(zvrf
), AF_INET6
, vty
,
1895 DEFUN (ip_nht_default_route
,
1896 ip_nht_default_route_cmd
,
1897 "ip nht resolve-via-default",
1899 "Filter Next Hop tracking route resolution\n"
1900 "Resolve via default route\n")
1902 if (zebra_rnh_ip_default_route
)
1905 zebra_rnh_ip_default_route
= 1;
1906 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1910 DEFUN (no_ip_nht_default_route
,
1911 no_ip_nht_default_route_cmd
,
1912 "no ip nht resolve-via-default",
1915 "Filter Next Hop tracking route resolution\n"
1916 "Resolve via default route\n")
1918 if (!zebra_rnh_ip_default_route
)
1921 zebra_rnh_ip_default_route
= 0;
1922 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1926 DEFUN (ipv6_nht_default_route
,
1927 ipv6_nht_default_route_cmd
,
1928 "ipv6 nht resolve-via-default",
1930 "Filter Next Hop tracking route resolution\n"
1931 "Resolve via default route\n")
1933 if (zebra_rnh_ipv6_default_route
)
1936 zebra_rnh_ipv6_default_route
= 1;
1937 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1941 DEFUN (no_ipv6_nht_default_route
,
1942 no_ipv6_nht_default_route_cmd
,
1943 "no ipv6 nht resolve-via-default",
1946 "Filter Next Hop tracking route resolution\n"
1947 "Resolve via default route\n")
1949 if (!zebra_rnh_ipv6_default_route
)
1952 zebra_rnh_ipv6_default_route
= 0;
1953 zebra_evaluate_rnh(VRF_DEFAULT
, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1961 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1964 |A.B.C.D/M$prefix longer-prefixes\
1965 |supernets-only$supernets_only\
1968 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1969 |ospf$type_str (1-65535)$ospf_instance_id\
1971 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1974 |X:X::X:X/M$prefix longer-prefixes\
1976 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1981 "IP forwarding table\n"
1982 "IP routing table\n"
1983 VRF_FULL_CMD_HELP_STR
1984 "Show only routes with tag\n"
1986 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1987 "Show route matching the specified Network/Mask pair only\n"
1988 "Show supernet entries only\n"
1989 FRR_IP_REDIST_HELP_STR_ZEBRA
1990 "Open Shortest Path First (OSPFv2)\n"
1993 "IP forwarding table\n"
1994 "IP routing table\n"
1995 VRF_FULL_CMD_HELP_STR
1996 "Show only routes with tag\n"
1999 "Show route matching the specified Network/Mask pair only\n"
2000 FRR_IP6_REDIST_HELP_STR_ZEBRA
2003 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2008 type
= proto_redistnum(afi
, type_str
);
2010 vty_out(vty
, "Unknown route type\n");
2016 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2017 struct zebra_vrf
*zvrf
;
2018 struct route_table
*table
;
2020 if ((zvrf
= vrf
->info
) == NULL
2021 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2025 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
, !!fib
,
2026 !!json
, tag
, prefix_str
? prefix
: NULL
,
2027 !!supernets_only
, type
, ospf_instance_id
);
2030 vrf_id_t vrf_id
= VRF_DEFAULT
;
2033 VRF_GET_ID(vrf_id
, vrf_name
);
2034 vrf
= vrf_lookup_by_id(vrf_id
);
2035 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
, !!fib
,
2036 !!json
, tag
, prefix_str
? prefix
: NULL
,
2037 !!supernets_only
, type
, ospf_instance_id
);
2043 DEFPY (show_route_detail
,
2044 show_route_detail_cmd
,
2047 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2052 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2060 "IP routing table\n"
2061 VRF_FULL_CMD_HELP_STR
2062 "Network in the IP routing table to display\n"
2063 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2065 "IP routing table\n"
2066 VRF_FULL_CMD_HELP_STR
2070 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2071 struct route_table
*table
;
2073 struct route_node
*rn
;
2076 prefix_str
= address_str
;
2077 if (str2prefix(prefix_str
, &p
) < 0) {
2078 vty_out(vty
, "%% Malformed address\n");
2084 struct zebra_vrf
*zvrf
;
2086 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2087 if ((zvrf
= vrf
->info
) == NULL
2088 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2091 rn
= route_node_match(table
, &p
);
2094 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2095 route_unlock_node(rn
);
2099 vty_show_ip_route_detail(vty
, rn
, 0);
2101 route_unlock_node(rn
);
2104 vrf_id_t vrf_id
= VRF_DEFAULT
;
2107 VRF_GET_ID(vrf_id
, vrf_name
);
2109 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2113 rn
= route_node_match(table
, &p
);
2115 vty_out(vty
, "%% Network not in table\n");
2118 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2119 vty_out(vty
, "%% Network not in table\n");
2120 route_unlock_node(rn
);
2124 vty_show_ip_route_detail(vty
, rn
, 0);
2126 route_unlock_node(rn
);
2132 DEFPY (show_route_summary
,
2133 show_route_summary_cmd
,
2136 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2137 summary [prefix$prefix]\
2138 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2139 summary [prefix$prefix]\
2143 "IP routing table\n"
2144 VRF_FULL_CMD_HELP_STR
2145 "Summary of all routes\n"
2148 "IP routing table\n"
2149 VRF_FULL_CMD_HELP_STR
2150 "Summary of all routes\n"
2153 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2154 struct route_table
*table
;
2158 struct zebra_vrf
*zvrf
;
2160 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2161 if ((zvrf
= vrf
->info
) == NULL
2162 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2166 vty_show_ip_route_summary_prefix(vty
, table
);
2168 vty_show_ip_route_summary(vty
, table
);
2171 vrf_id_t vrf_id
= VRF_DEFAULT
;
2174 VRF_GET_ID(vrf_id
, vrf_name
);
2176 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2181 vty_show_ip_route_summary_prefix(vty
, table
);
2183 vty_show_ip_route_summary(vty
, table
);
2189 static void vty_show_ip_route_summary(struct vty
*vty
,
2190 struct route_table
*table
)
2192 struct route_node
*rn
;
2193 struct route_entry
*re
;
2194 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2195 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2196 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2197 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2201 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2202 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2203 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2204 RNODE_FOREACH_RE (rn
, re
) {
2205 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2206 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2208 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2210 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2212 rib_cnt
[re
->type
]++;
2214 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
)) {
2215 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2218 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2220 fib_cnt
[re
->type
]++;
2224 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2225 "FIB", zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2227 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2228 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2229 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2230 if (i
== ZEBRA_ROUTE_BGP
) {
2231 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2232 rib_cnt
[ZEBRA_ROUTE_BGP
],
2233 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2234 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2235 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2236 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2238 vty_out(vty
, "%-20s %-20d %-20d \n",
2239 zebra_route_string(i
), rib_cnt
[i
],
2244 vty_out(vty
, "------\n");
2245 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2246 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2251 * Implementation of the ip route summary prefix command.
2253 * This command prints the primary prefixes that have been installed by various
2254 * protocols on the box.
2257 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2258 struct route_table
*table
)
2260 struct route_node
*rn
;
2261 struct route_entry
*re
;
2262 struct nexthop
*nexthop
;
2263 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2264 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2265 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2266 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2270 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2271 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2272 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2273 RNODE_FOREACH_RE (rn
, re
) {
2276 * In case of ECMP, count only once.
2279 for (nexthop
= re
->ng
.nexthop
; (!cnt
&& nexthop
);
2280 nexthop
= nexthop
->next
) {
2282 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2283 rib_cnt
[re
->type
]++;
2284 if (CHECK_FLAG(nexthop
->flags
,
2285 NEXTHOP_FLAG_FIB
)) {
2286 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2287 fib_cnt
[re
->type
]++;
2289 if (re
->type
== ZEBRA_ROUTE_BGP
2290 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2291 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2292 if (CHECK_FLAG(nexthop
->flags
,
2294 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2299 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2300 "Prefix Routes", "FIB",
2301 zvrf_name(((rib_table_info_t
*)table
->info
)->zvrf
));
2303 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2304 if (rib_cnt
[i
] > 0) {
2305 if (i
== ZEBRA_ROUTE_BGP
) {
2306 vty_out(vty
, "%-20s %-20d %-20d \n", "ebgp",
2307 rib_cnt
[ZEBRA_ROUTE_BGP
]
2308 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2309 fib_cnt
[ZEBRA_ROUTE_BGP
]
2310 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2311 vty_out(vty
, "%-20s %-20d %-20d \n", "ibgp",
2312 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2313 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2315 vty_out(vty
, "%-20s %-20d %-20d \n",
2316 zebra_route_string(i
), rib_cnt
[i
],
2321 vty_out(vty
, "------\n");
2322 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2323 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2327 /* Write static route configuration. */
2328 int static_config(struct vty
*vty
, struct zebra_vrf
*zvrf
, afi_t afi
,
2329 safi_t safi
, const char *cmd
)
2331 struct static_hold_route
*shr
;
2332 struct listnode
*node
;
2334 struct route_node
*rn
;
2335 struct static_route
*si
;
2336 struct route_table
*stable
;
2337 char buf
[SRCDEST2STR_BUFFER
];
2340 if ((stable
= zvrf
->stable
[afi
][safi
]) == NULL
)
2343 sprintf(spacing
, "%s%s", (zvrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
2347 * Static routes for vrfs not fully inited
2349 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
2350 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
2353 if (strcmp(zvrf
->vrf
->name
, shr
->vrf_name
) != 0)
2356 char dest_str
[PREFIX_STRLEN
];
2358 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
2360 vty_out(vty
, "%s ", spacing
);
2362 vty_out(vty
, "%s ", dest_str
);
2364 vty_out(vty
, "from %s ", shr
->src_str
);
2366 vty_out(vty
, "%s ", shr
->gate_str
);
2368 vty_out(vty
, "%s ", shr
->ifname
);
2370 vty_out(vty
, "%s ", shr
->flag_str
);
2372 vty_out(vty
, "tag %s ", shr
->tag_str
);
2373 if (shr
->distance_str
)
2374 vty_out(vty
, "%s ", shr
->distance_str
);
2376 vty_out(vty
, "label %s ", shr
->label_str
);
2378 vty_out(vty
, "table %s ", shr
->table_str
);
2379 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
2380 vty_out(vty
, "nexthop-vrf %s", shr
->nhvrf_name
);
2384 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
2385 for (si
= rn
->info
; si
; si
= si
->next
) {
2386 vty_out(vty
, "%s %s", spacing
,
2387 srcdest_rnode2str(rn
, buf
, sizeof buf
));
2390 case STATIC_IPV4_GATEWAY
:
2391 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
2393 case STATIC_IPV6_GATEWAY
:
2395 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2399 vty_out(vty
, " %s", si
->ifname
);
2401 case STATIC_BLACKHOLE
:
2402 switch (si
->bh_type
) {
2403 case STATIC_BLACKHOLE_DROP
:
2404 vty_out(vty
, " blackhole");
2406 case STATIC_BLACKHOLE_NULL
:
2407 vty_out(vty
, " Null0");
2409 case STATIC_BLACKHOLE_REJECT
:
2410 vty_out(vty
, " reject");
2414 case STATIC_IPV4_GATEWAY_IFNAME
:
2415 vty_out(vty
, " %s %s",
2416 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
2420 case STATIC_IPV6_GATEWAY_IFNAME
:
2421 vty_out(vty
, " %s %s",
2422 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
2429 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
2431 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
2432 vty_out(vty
, " %d", si
->distance
);
2434 /* Label information */
2435 if (si
->snh_label
.num_labels
)
2436 vty_out(vty
, " label %s",
2437 mpls_label2str(si
->snh_label
.num_labels
,
2438 si
->snh_label
.label
, buf
,
2441 if (si
->nh_vrf_id
!= si
->vrf_id
) {
2442 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
2445 /* table ID from VRF overrides configured
2447 if (si
->table_id
&& zvrf
->table_id
== RT_TABLE_MAIN
)
2448 vty_out(vty
, " table %u", si
->table_id
);
2457 DEFPY(ipv6_route_blackhole
,
2458 ipv6_route_blackhole_cmd
,
2459 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2460 <Null0|reject|blackhole>$flag \
2462 tag (1-4294967295) \
2466 |table (1-4294967295) \
2470 "Establish static routes\n"
2471 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2472 "IPv6 source-dest route\n"
2473 "IPv6 source prefix\n"
2475 "Emit an ICMP unreachable when matched\n"
2476 "Silently discard pkts when matched\n"
2477 "Set tag for this route\n"
2479 "Distance value for this prefix\n"
2482 "Table to configure\n"
2483 "The table number to configure\n")
2485 if (table_str
&& !vrf_is_backend_netns()) {
2487 "%% table param only available when running on netns-based vrfs\n");
2488 return CMD_WARNING_CONFIG_FAILED
;
2491 return zebra_static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
2492 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
2493 distance_str
, vrf
, label
, table_str
);
2496 DEFPY(ipv6_route_blackhole_vrf
,
2497 ipv6_route_blackhole_vrf_cmd
,
2498 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2499 <Null0|reject|blackhole>$flag \
2501 tag (1-4294967295) \
2504 |table (1-4294967295) \
2508 "Establish static routes\n"
2509 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2510 "IPv6 source-dest route\n"
2511 "IPv6 source prefix\n"
2513 "Emit an ICMP unreachable when matched\n"
2514 "Silently discard pkts when matched\n"
2515 "Set tag for this route\n"
2517 "Distance value for this prefix\n"
2519 "Table to configure\n"
2520 "The table number to configure\n")
2522 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2523 struct zebra_vrf
*zvrf
= vrf
->info
;
2525 if (table_str
&& !vrf_is_backend_netns()) {
2527 "%% table param only available when running on netns-based vrfs\n");
2528 return CMD_WARNING_CONFIG_FAILED
;
2531 * Coverity is complaining that prefix could
2532 * be dereferenced, but we know that prefix will
2533 * valid. Add an assert to make it happy
2536 return zebra_static_route_leak(
2537 vty
, zvrf
, zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2538 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
2542 DEFPY(ipv6_route_address_interface
,
2543 ipv6_route_address_interface_cmd
,
2544 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2548 tag (1-4294967295) \
2552 |table (1-4294967295) \
2557 "Establish static routes\n"
2558 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2559 "IPv6 source-dest route\n"
2560 "IPv6 source prefix\n"
2561 "IPv6 gateway address\n"
2562 "IPv6 gateway interface name\n"
2563 "Set tag for this route\n"
2565 "Distance value for this prefix\n"
2568 "Table to configure\n"
2569 "The table number to configure\n"
2572 struct zebra_vrf
*zvrf
;
2573 struct zebra_vrf
*nh_zvrf
;
2575 if (table_str
&& !vrf_is_backend_netns()) {
2577 "%% table param only available when running on netns-based vrfs\n");
2578 return CMD_WARNING_CONFIG_FAILED
;
2581 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2583 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2584 return CMD_WARNING_CONFIG_FAILED
;
2588 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2593 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2594 return CMD_WARNING_CONFIG_FAILED
;
2597 return zebra_static_route_leak(
2598 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2599 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2603 DEFPY(ipv6_route_address_interface_vrf
,
2604 ipv6_route_address_interface_vrf_cmd
,
2605 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2609 tag (1-4294967295) \
2612 |table (1-4294967295) \
2617 "Establish static routes\n"
2618 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2619 "IPv6 source-dest route\n"
2620 "IPv6 source prefix\n"
2621 "IPv6 gateway address\n"
2622 "IPv6 gateway interface name\n"
2623 "Set tag for this route\n"
2625 "Distance value for this prefix\n"
2627 "Table to configure\n"
2628 "The table number to configure\n"
2631 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2632 struct zebra_vrf
*zvrf
= vrf
->info
;
2633 struct zebra_vrf
*nh_zvrf
;
2635 if (table_str
&& !vrf_is_backend_netns()) {
2637 "%% table param only available when running on netns-based vrfs\n");
2638 return CMD_WARNING_CONFIG_FAILED
;
2642 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2647 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2648 return CMD_WARNING_CONFIG_FAILED
;
2651 return zebra_static_route_leak(
2652 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2653 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2659 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2660 <X:X::X:X$gate|INTERFACE$ifname> \
2662 tag (1-4294967295) \
2666 |table (1-4294967295) \
2671 "Establish static routes\n"
2672 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2673 "IPv6 source-dest route\n"
2674 "IPv6 source prefix\n"
2675 "IPv6 gateway address\n"
2676 "IPv6 gateway interface name\n"
2677 "Set tag for this route\n"
2679 "Distance value for this prefix\n"
2682 "Table to configure\n"
2683 "The table number to configure\n"
2686 struct zebra_vrf
*zvrf
;
2687 struct zebra_vrf
*nh_zvrf
;
2689 if (table_str
&& !vrf_is_backend_netns()) {
2691 "%% table param only available when running on netns-based vrfs\n");
2692 return CMD_WARNING_CONFIG_FAILED
;
2695 zvrf
= zebra_vty_get_unknown_vrf(vty
, vrf
);
2697 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
2698 return CMD_WARNING_CONFIG_FAILED
;
2702 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2707 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2708 return CMD_WARNING_CONFIG_FAILED
;
2711 return zebra_static_route_leak(
2712 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2713 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2717 DEFPY(ipv6_route_vrf
,
2719 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2720 <X:X::X:X$gate|INTERFACE$ifname> \
2722 tag (1-4294967295) \
2725 |table (1-4294967295) \
2730 "Establish static routes\n"
2731 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2732 "IPv6 source-dest route\n"
2733 "IPv6 source prefix\n"
2734 "IPv6 gateway address\n"
2735 "IPv6 gateway interface name\n"
2736 "Set tag for this route\n"
2738 "Distance value for this prefix\n"
2740 "Table to configure\n"
2741 "The table number to configure\n"
2744 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
2745 struct zebra_vrf
*zvrf
= vrf
->info
;
2746 struct zebra_vrf
*nh_zvrf
;
2748 if (table_str
&& !vrf_is_backend_netns()) {
2750 "%% table param only available when running on netns-based vrfs\n");
2751 return CMD_WARNING_CONFIG_FAILED
;
2755 nh_zvrf
= zebra_vty_get_unknown_vrf(vty
, nexthop_vrf
);
2760 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
2761 return CMD_WARNING_CONFIG_FAILED
;
2764 return zebra_static_route_leak(
2765 vty
, zvrf
, nh_zvrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
2766 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
2771 * Show IPv6 mroute command.Used to dump
2772 * the Multicast routing table.
2774 DEFUN (show_ipv6_mroute
,
2775 show_ipv6_mroute_cmd
,
2776 "show ipv6 mroute [vrf NAME]",
2779 "IPv6 Multicast routing table\n"
2782 struct route_table
*table
;
2783 struct route_node
*rn
;
2784 struct route_entry
*re
;
2786 vrf_id_t vrf_id
= VRF_DEFAULT
;
2789 VRF_GET_ID(vrf_id
, argv
[4]->arg
);
2791 table
= zebra_vrf_table(AFI_IP6
, SAFI_MULTICAST
, vrf_id
);
2795 /* Show all IPv6 route. */
2796 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2797 RNODE_FOREACH_RE (rn
, re
) {
2799 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2802 vty_show_ip_route(vty
, rn
, re
, NULL
);
2807 DEFUN (show_ipv6_mroute_vrf_all
,
2808 show_ipv6_mroute_vrf_all_cmd
,
2809 "show ipv6 mroute vrf all",
2812 "IPv6 Multicast routing table\n"
2813 VRF_ALL_CMD_HELP_STR
)
2815 struct route_table
*table
;
2816 struct route_node
*rn
;
2817 struct route_entry
*re
;
2819 struct zebra_vrf
*zvrf
;
2822 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2823 if ((zvrf
= vrf
->info
) == NULL
2824 || (table
= zvrf
->table
[AFI_IP6
][SAFI_MULTICAST
]) == NULL
)
2827 /* Show all IPv6 route. */
2828 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2829 RNODE_FOREACH_RE (rn
, re
) {
2831 vty_out(vty
, SHOW_ROUTE_V6_HEADER
);
2834 vty_show_ip_route(vty
, rn
, re
, NULL
);
2840 DEFUN (allow_external_route_update
,
2841 allow_external_route_update_cmd
,
2842 "allow-external-route-update",
2843 "Allow FRR routes to be overwritten by external processes\n")
2850 DEFUN (no_allow_external_route_update
,
2851 no_allow_external_route_update_cmd
,
2852 "no allow-external-route-update",
2854 "Allow FRR routes to be overwritten by external processes\n")
2869 struct zebra_vrf
*zvrf
;
2871 if (vrf_is_backend_netns())
2872 vty_out(vty
, "netns-based vrfs\n");
2874 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2875 if (!(zvrf
= vrf
->info
))
2877 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2880 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2881 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2882 vty_out(vty
, "inactive");
2883 else if (zvrf_ns_name(zvrf
))
2884 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2885 zvrf_ns_name(zvrf
));
2887 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2889 if (vrf_is_user_cfged(vrf
))
2890 vty_out(vty
, " (configured)");
2897 DEFUN (default_vrf_vni_mapping
,
2898 default_vrf_vni_mapping_cmd
,
2899 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2900 "VNI corresponding to the DEFAULT VRF\n"
2902 "Prefix routes only \n")
2905 char err
[ERR_STR_SZ
];
2906 struct zebra_vrf
*zvrf
= NULL
;
2907 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2910 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2917 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2920 vty_out(vty
, "%s\n", err
);
2927 DEFUN (no_default_vrf_vni_mapping
,
2928 no_default_vrf_vni_mapping_cmd
,
2929 "no vni " CMD_VNI_RANGE
,
2931 "VNI corresponding to DEFAULT VRF\n"
2935 char err
[ERR_STR_SZ
];
2936 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2937 struct zebra_vrf
*zvrf
= NULL
;
2939 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2943 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
, 0, 0);
2945 vty_out(vty
, "%s\n", err
);
2952 DEFUN (vrf_vni_mapping
,
2953 vrf_vni_mapping_cmd
,
2954 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2955 "VNI corresponding to tenant VRF\n"
2957 "prefix-routes-only\n")
2962 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
2963 vni_t vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2964 char err
[ERR_STR_SZ
];
2972 /* Mark as having FRR configuration */
2973 vrf_set_user_cfged(vrf
);
2974 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
, ERR_STR_SZ
,
2977 vty_out(vty
, "%s\n", err
);
2984 DEFUN (no_vrf_vni_mapping
,
2985 no_vrf_vni_mapping_cmd
,
2986 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2988 "VNI corresponding to tenant VRF\n"
2990 "prefix-routes-only\n")
2994 char err
[ERR_STR_SZ
];
2995 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2997 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
3005 ret
= zebra_vxlan_process_vrf_vni_cmd(zvrf
, vni
, err
,
3006 ERR_STR_SZ
, filter
, 0);
3008 vty_out(vty
, "%s\n", err
);
3012 /* If no other FRR config for this VRF, mark accordingly. */
3013 if (!zebra_vrf_has_config(zvrf
))
3014 vrf_reset_user_cfged(vrf
);
3020 DEFUN (show_vrf_vni
,
3022 "show vrf vni [json]",
3029 struct zebra_vrf
*zvrf
;
3030 json_object
*json
= NULL
;
3031 json_object
*json_vrfs
= NULL
;
3032 uint8_t uj
= use_json(argc
, argv
);
3035 json
= json_object_new_object();
3036 json_vrfs
= json_object_new_array();
3040 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3041 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3043 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3048 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3052 json_object_object_add(json
, "vrfs", json_vrfs
);
3053 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3054 json
, JSON_C_TO_STRING_PRETTY
));
3055 json_object_free(json
);
3061 DEFUN (show_evpn_global
,
3062 show_evpn_global_cmd
,
3068 uint8_t uj
= use_json(argc
, argv
);
3070 zebra_vxlan_print_evpn(vty
, uj
);
3074 DEFUN (show_evpn_vni
,
3076 "show evpn vni [json]",
3079 "VxLAN information\n"
3082 struct zebra_vrf
*zvrf
;
3083 uint8_t uj
= use_json(argc
, argv
);
3085 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3086 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3090 DEFUN (show_evpn_vni_vni
,
3091 show_evpn_vni_vni_cmd
,
3092 "show evpn vni " CMD_VNI_RANGE
"[json]",
3095 "VxLAN Network Identifier\n"
3099 struct zebra_vrf
*zvrf
;
3101 uint8_t uj
= use_json(argc
, argv
);
3103 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3104 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3105 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
);
3109 DEFUN (show_evpn_rmac_vni_mac
,
3110 show_evpn_rmac_vni_mac_cmd
,
3111 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3118 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3123 uint8_t uj
= use_json(argc
, argv
);
3125 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3126 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3127 vty_out(vty
, "%% Malformed MAC address\n");
3130 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3134 DEFUN (show_evpn_rmac_vni
,
3135 show_evpn_rmac_vni_cmd
,
3136 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3145 uint8_t uj
= use_json(argc
, argv
);
3147 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3148 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3153 DEFUN (show_evpn_rmac_vni_all
,
3154 show_evpn_rmac_vni_all_cmd
,
3155 "show evpn rmac vni all [json]",
3163 uint8_t uj
= use_json(argc
, argv
);
3165 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3170 DEFUN (show_evpn_nh_vni_ip
,
3171 show_evpn_nh_vni_ip_cmd
,
3172 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3179 "Host address (ipv4 or ipv6)\n"
3184 uint8_t uj
= use_json(argc
, argv
);
3186 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3187 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3189 vty_out(vty
, "%% Malformed Neighbor address\n");
3192 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3197 DEFUN (show_evpn_nh_vni
,
3198 show_evpn_nh_vni_cmd
,
3199 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3208 uint8_t uj
= use_json(argc
, argv
);
3210 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3211 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3216 DEFUN (show_evpn_nh_vni_all
,
3217 show_evpn_nh_vni_all_cmd
,
3218 "show evpn next-hops vni all [json]",
3226 uint8_t uj
= use_json(argc
, argv
);
3228 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3233 DEFUN (show_evpn_mac_vni
,
3234 show_evpn_mac_vni_cmd
,
3235 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3239 "VxLAN Network Identifier\n"
3243 struct zebra_vrf
*zvrf
;
3245 uint8_t uj
= use_json(argc
, argv
);
3247 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3248 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3249 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3253 DEFUN (show_evpn_mac_vni_all
,
3254 show_evpn_mac_vni_all_cmd
,
3255 "show evpn mac vni all [json]",
3259 "VxLAN Network Identifier\n"
3263 struct zebra_vrf
*zvrf
;
3264 uint8_t uj
= use_json(argc
, argv
);
3266 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3267 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, uj
);
3271 DEFUN (show_evpn_mac_vni_all_vtep
,
3272 show_evpn_mac_vni_all_vtep_cmd
,
3273 "show evpn mac vni all vtep A.B.C.D [json]",
3277 "VxLAN Network Identifier\n"
3280 "Remote VTEP IP address\n"
3283 struct zebra_vrf
*zvrf
;
3284 struct in_addr vtep_ip
;
3285 uint8_t uj
= use_json(argc
, argv
);
3287 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3289 vty_out(vty
, "%% Malformed VTEP IP address\n");
3292 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3293 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3299 DEFUN (show_evpn_mac_vni_mac
,
3300 show_evpn_mac_vni_mac_cmd
,
3301 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD",
3305 "VxLAN Network Identifier\n"
3308 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
3310 struct zebra_vrf
*zvrf
;
3314 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3315 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3316 vty_out(vty
, "%% Malformed MAC address");
3319 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3320 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
);
3324 DEFUN (show_evpn_mac_vni_vtep
,
3325 show_evpn_mac_vni_vtep_cmd
,
3326 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3330 "VxLAN Network Identifier\n"
3333 "Remote VTEP IP address\n"
3336 struct zebra_vrf
*zvrf
;
3338 struct in_addr vtep_ip
;
3339 uint8_t uj
= use_json(argc
, argv
);
3341 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3342 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3344 vty_out(vty
, "%% Malformed VTEP IP address\n");
3348 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3349 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3353 DEFUN (show_evpn_neigh_vni
,
3354 show_evpn_neigh_vni_cmd
,
3355 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3358 "ARP and ND cache\n"
3359 "VxLAN Network Identifier\n"
3363 struct zebra_vrf
*zvrf
;
3365 uint8_t uj
= use_json(argc
, argv
);
3367 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3368 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3369 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3373 DEFUN (show_evpn_neigh_vni_all
,
3374 show_evpn_neigh_vni_all_cmd
,
3375 "show evpn arp-cache vni all [json]",
3378 "ARP and ND cache\n"
3379 "VxLAN Network Identifier\n"
3383 struct zebra_vrf
*zvrf
;
3384 uint8_t uj
= use_json(argc
, argv
);
3386 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3387 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, uj
);
3391 DEFUN (show_evpn_neigh_vni_neigh
,
3392 show_evpn_neigh_vni_neigh_cmd
,
3393 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3396 "ARP and ND cache\n"
3397 "VxLAN Network Identifier\n"
3400 "Neighbor address (IPv4 or IPv6 address)\n"
3403 struct zebra_vrf
*zvrf
;
3406 uint8_t uj
= use_json(argc
, argv
);
3408 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3409 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3411 vty_out(vty
, "%% Malformed Neighbor address\n");
3414 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3415 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3419 DEFUN (show_evpn_neigh_vni_vtep
,
3420 show_evpn_neigh_vni_vtep_cmd
,
3421 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3424 "ARP and ND cache\n"
3425 "VxLAN Network Identifier\n"
3428 "Remote VTEP IP address\n"
3431 struct zebra_vrf
*zvrf
;
3433 struct in_addr vtep_ip
;
3434 uint8_t uj
= use_json(argc
, argv
);
3436 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3437 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3439 vty_out(vty
, "%% Malformed VTEP IP address\n");
3443 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3444 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3448 /* policy routing contexts */
3449 DEFUN (show_pbr_ipset
,
3451 "show pbr ipset [WORD]",
3453 "Policy-Based Routing\n"
3454 "IPset Context information\n"
3455 "IPset Name information\n")
3459 found
= argv_find(argv
, argc
, "WORD", &idx
);
3461 zebra_pbr_show_ipset_list(vty
, NULL
);
3463 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3467 /* policy routing contexts */
3468 DEFUN (show_pbr_iptable
,
3469 show_pbr_iptable_cmd
,
3472 "Policy-Based Routing\n"
3473 "IPtable Context information\n")
3475 zebra_pbr_show_iptable(vty
);
3479 /* Static ip route configuration write function. */
3480 static int zebra_ip_config(struct vty
*vty
)
3484 write
+= zebra_import_table_config(vty
);
3489 DEFUN (ip_zebra_import_table_distance
,
3490 ip_zebra_import_table_distance_cmd
,
3491 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3493 "import routes from non-main kernel table\n"
3494 "kernel routing table id\n"
3495 "Distance for imported routes\n"
3496 "Default distance value\n"
3497 "route-map for filtering\n"
3500 uint32_t table_id
= 0;
3502 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3503 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3505 strmatch(argv
[argc
- 2]->text
, "route-map")
3506 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3510 if (argc
== 7 || (argc
== 5 && !rmap
))
3511 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3513 if (!is_zebra_valid_kernel_table(table_id
)) {
3515 "Invalid routing table ID, %d. Must be in range 1-252\n",
3518 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3522 if (is_zebra_main_routing_table(table_id
)) {
3524 "Invalid routing table ID, %d. Must be non-default table\n",
3527 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3531 ret
= zebra_import_table(AFI_IP
, table_id
, distance
, rmap
, 1);
3533 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3538 DEFUN_HIDDEN (zebra_packet_process
,
3539 zebra_packet_process_cmd
,
3540 "zebra zapi-packets (1-10000)",
3543 "Number of packets to process before relinquishing thread\n")
3545 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3547 atomic_store_explicit(&zebrad
.packets_to_process
, packets
,
3548 memory_order_relaxed
);
3553 DEFUN_HIDDEN (no_zebra_packet_process
,
3554 no_zebra_packet_process_cmd
,
3555 "no zebra zapi-packets [(1-10000)]",
3559 "Number of packets to process before relinquishing thread\n")
3561 atomic_store_explicit(&zebrad
.packets_to_process
,
3562 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3563 memory_order_relaxed
);
3568 DEFUN_HIDDEN (zebra_workqueue_timer
,
3569 zebra_workqueue_timer_cmd
,
3570 "zebra work-queue (0-10000)",
3573 "Time in milliseconds\n")
3575 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3576 zebrad
.ribq
->spec
.hold
= timer
;
3581 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3582 no_zebra_workqueue_timer_cmd
,
3583 "no zebra work-queue [(0-10000)]",
3587 "Time in milliseconds\n")
3589 zebrad
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3594 DEFUN (no_ip_zebra_import_table
,
3595 no_ip_zebra_import_table_cmd
,
3596 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3599 "import routes from non-main kernel table\n"
3600 "kernel routing table id\n"
3601 "Distance for imported routes\n"
3602 "Default distance value\n"
3603 "route-map for filtering\n"
3606 uint32_t table_id
= 0;
3607 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3609 if (!is_zebra_valid_kernel_table(table_id
)) {
3611 "Invalid routing table ID. Must be in range 1-252\n");
3615 if (is_zebra_main_routing_table(table_id
)) {
3617 "Invalid routing table ID, %d. Must be non-default table\n",
3622 if (!is_zebra_import_table_enabled(AFI_IP
, table_id
))
3625 return (zebra_import_table(AFI_IP
, table_id
, 0, NULL
, 0));
3628 static int config_write_protocol(struct vty
*vty
)
3631 vty_out(vty
, "allow-external-route-update\n");
3633 if (zebra_rnh_ip_default_route
)
3634 vty_out(vty
, "ip nht resolve-via-default\n");
3636 if (zebra_rnh_ipv6_default_route
)
3637 vty_out(vty
, "ipv6 nht resolve-via-default\n");
3639 if (zebrad
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3640 vty_out(vty
, "zebra work-queue %u\n", zebrad
.ribq
->spec
.hold
);
3642 if (zebrad
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3643 vty_out(vty
, "zebra zapi-packets %u\n",
3644 zebrad
.packets_to_process
);
3646 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3648 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3649 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3650 ipv4_multicast_mode
== MCAST_URIB_ONLY
3652 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3654 : ipv4_multicast_mode
3655 == MCAST_MIX_MRIB_FIRST
3657 : ipv4_multicast_mode
3658 == MCAST_MIX_DISTANCE
3662 zebra_routemap_config_write_protocol(vty
);
3668 /* Display default rtm_table for all clients. */
3673 "default routing table to use for all clients\n")
3675 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3679 DEFUN (config_table
,
3682 "Configure target kernel routing table\n"
3685 zebrad
.rtm_table_default
= strtol(argv
[1]->arg
, (char **)0, 10);
3689 DEFUN (no_config_table
,
3690 no_config_table_cmd
,
3691 "no table [TABLENO]",
3693 "Configure target kernel routing table\n"
3696 zebrad
.rtm_table_default
= 0;
3710 " Route Route Neighbor LSP LSP\n");
3712 "VRF Installs Removals Updates Installs Removals\n");
3714 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3715 struct zebra_vrf
*zvrf
= vrf
->info
;
3717 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
3718 " %10" PRIu64
" %10" PRIu64
"\n",
3719 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
3720 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
3721 zvrf
->lsp_removals
);
3727 DEFUN (ip_forwarding
,
3731 "Turn on IP forwarding\n")
3737 ret
= ipforward_on();
3740 vty_out(vty
, "Can't turn on IP forwarding\n");
3741 return CMD_WARNING_CONFIG_FAILED
;
3747 DEFUN (no_ip_forwarding
,
3748 no_ip_forwarding_cmd
,
3752 "Turn off IP forwarding\n")
3758 ret
= ipforward_off();
3761 vty_out(vty
, "Can't turn off IP forwarding\n");
3762 return CMD_WARNING_CONFIG_FAILED
;
3768 /* Only display ip forwarding is enabled or not. */
3769 DEFUN (show_ip_forwarding
,
3770 show_ip_forwarding_cmd
,
3771 "show ip forwarding",
3774 "IP forwarding status\n")
3781 vty_out(vty
, "IP forwarding is off\n");
3783 vty_out(vty
, "IP forwarding is on\n");
3787 /* Only display ipv6 forwarding is enabled or not. */
3788 DEFUN (show_ipv6_forwarding
,
3789 show_ipv6_forwarding_cmd
,
3790 "show ipv6 forwarding",
3792 "IPv6 information\n"
3793 "Forwarding status\n")
3797 ret
= ipforward_ipv6();
3801 vty_out(vty
, "ipv6 forwarding is unknown\n");
3804 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3807 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
3810 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
3816 DEFUN (ipv6_forwarding
,
3817 ipv6_forwarding_cmd
,
3820 "Turn on IPv6 forwarding\n")
3824 ret
= ipforward_ipv6();
3826 ret
= ipforward_ipv6_on();
3829 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
3830 return CMD_WARNING_CONFIG_FAILED
;
3836 DEFUN (no_ipv6_forwarding
,
3837 no_ipv6_forwarding_cmd
,
3838 "no ipv6 forwarding",
3841 "Turn off IPv6 forwarding\n")
3845 ret
= ipforward_ipv6();
3847 ret
= ipforward_ipv6_off();
3850 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
3851 return CMD_WARNING_CONFIG_FAILED
;
3857 /* Table configuration write function. */
3858 static int config_write_table(struct vty
*vty
)
3860 if (zebrad
.rtm_table_default
)
3861 vty_out(vty
, "table %d\n", zebrad
.rtm_table_default
);
3865 /* IPForwarding configuration write function. */
3866 static int config_write_forwarding(struct vty
*vty
)
3868 /* FIXME: Find better place for that. */
3869 router_id_write(vty
);
3872 vty_out(vty
, "no ip forwarding\n");
3873 if (!ipforward_ipv6())
3874 vty_out(vty
, "no ipv6 forwarding\n");
3875 vty_out(vty
, "!\n");
3879 /* IP node for static routes. */
3880 static struct cmd_node ip_node
= {IP_NODE
, "", 1};
3881 static struct cmd_node protocol_node
= {PROTOCOL_NODE
, "", 1};
3882 /* table node for routing tables. */
3883 static struct cmd_node table_node
= {TABLE_NODE
,
3884 "", /* This node has no interface. */
3886 static struct cmd_node forwarding_node
= {FORWARDING_NODE
,
3887 "", /* This node has no interface. */
3891 void zebra_vty_init(void)
3893 /* Install configuration write function. */
3894 install_node(&table_node
, config_write_table
);
3895 install_node(&forwarding_node
, config_write_forwarding
);
3897 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
3898 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
3899 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
3900 install_element(ENABLE_NODE
, &show_zebra_cmd
);
3903 install_element(VIEW_NODE
, &show_table_cmd
);
3904 install_element(CONFIG_NODE
, &config_table_cmd
);
3905 install_element(CONFIG_NODE
, &no_config_table_cmd
);
3906 #endif /* HAVE_NETLINK */
3908 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
3909 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
3910 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
3913 zebra_route_map_init();
3915 install_node(&ip_node
, zebra_ip_config
);
3916 install_node(&protocol_node
, config_write_protocol
);
3918 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
3919 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
3920 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
3921 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
3922 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
3923 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
3924 install_element(CONFIG_NODE
,
3925 &ip_route_address_interface_cmd
);
3926 install_element(CONFIG_NODE
, &ip_route_cmd
);
3927 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
3928 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
3929 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
3931 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
3932 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
3933 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
3934 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
3935 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
3936 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
3938 install_element(VIEW_NODE
, &show_vrf_cmd
);
3939 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
3940 install_element(VIEW_NODE
, &show_route_cmd
);
3941 install_element(VIEW_NODE
, &show_route_table_cmd
);
3942 if (vrf_is_backend_netns())
3943 install_element(VIEW_NODE
, &show_route_table_vrf_cmd
);
3944 install_element(VIEW_NODE
, &show_route_detail_cmd
);
3945 install_element(VIEW_NODE
, &show_route_summary_cmd
);
3946 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
3947 install_element(VIEW_NODE
, &show_ip_nht_vrf_all_cmd
);
3948 install_element(VIEW_NODE
, &show_ipv6_nht_cmd
);
3949 install_element(VIEW_NODE
, &show_ipv6_nht_vrf_all_cmd
);
3951 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
3952 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
3954 install_element(CONFIG_NODE
,
3955 &ipv6_route_blackhole_cmd
);
3956 install_element(CONFIG_NODE
,
3957 &ipv6_route_address_interface_cmd
);
3958 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
3959 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
3960 install_element(VRF_NODE
,
3961 &ipv6_route_address_interface_vrf_cmd
);
3962 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
3963 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
3964 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
3965 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
3966 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
3967 install_element(VIEW_NODE
, &show_ipv6_mroute_cmd
);
3969 /* Commands for VRF */
3970 install_element(VIEW_NODE
, &show_ipv6_mroute_vrf_all_cmd
);
3972 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
3973 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
3974 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
3975 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
3976 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
3977 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
3978 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
3979 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
3980 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
3981 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
3982 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
3983 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
3984 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
3985 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
3986 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
3987 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
3988 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
3989 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
3991 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
3992 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
3994 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
3995 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
3996 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
3997 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
3999 static_list
= list_new();
4000 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
4001 static_list
->del
= (void (*)(void *))static_list_delete
;