diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 2abcd6ef2aeb..705536595b5d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -75,6 +75,10 @@ static vlanid_t filter_vlan = 0; +/* We capture whether the current kernel supports nexthop ids; by + * default, we'll use them if possible. There's also a configuration + * available to _disable_ use of kernel nexthops. + */ static bool supports_nh; struct gw_family_t { @@ -86,6 +90,12 @@ struct gw_family_t { static const char ipv4_ll_buf[16] = "169.254.0.1"; static struct in_addr ipv4_ll; +/* Helper to control use of kernel-level nexthop ids */ +static bool kernel_nexthops_supported(void) +{ + return (supports_nh && zebra_nhg_kernel_nexthops_enabled()); +} + /* * The ipv4_ll data structure is used for all 5549 * additions to the kernel. Let's figure out the @@ -1628,7 +1638,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) RTA_PAYLOAD(rta)); } - if (supports_nh) { + if (kernel_nexthops_supported()) { /* Kernel supports nexthop objects */ addattr32(&req.n, sizeof(req), RTA_NH_ID, dplane_ctx_get_nhe_id(ctx)); @@ -1943,7 +1953,7 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) size_t req_size = sizeof(req); /* Nothing to do if the kernel doesn't support nexthop objects */ - if (!supports_nh) + if (!kernel_nexthops_supported()) return 0; label_buf[0] = '\0'; @@ -2504,8 +2514,10 @@ int netlink_nexthop_read(struct zebra_ns *zns) * this kernel must support them. */ supports_nh = true; - else if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Nexthop objects not supported on this kernel"); + + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) + zlog_debug("Nexthop objects %ssupported on this kernel", + supports_nh ? "" : "not "); return ret; } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index cbeb73aed420..62c478cf8583 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -49,6 +49,9 @@ DEFINE_MTYPE_STATIC(ZEBRA, NHG_CTX, "Nexthop Group Context"); /* id counter to keep in sync with kernel */ uint32_t id_counter; +/* */ +static bool g_nexthops_enabled = true; + static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi); static void depends_add(struct nhg_connected_tree_head *head, @@ -2004,3 +2007,18 @@ void zebra_nhg_sweep_table(struct hash *hash) { hash_iterate(hash, zebra_nhg_sweep_entry, NULL); } + +/* Global control to disable use of kernel nexthops, if available. We can't + * force the kernel to support nexthop ids, of course, but we can disable + * zebra's use of them, for testing e.g. By default, if the kernel supports + * nexthop ids, zebra uses them. + */ +void zebra_nhg_enable_kernel_nexthops(bool set) +{ + g_nexthops_enabled = set; +} + +bool zebra_nhg_kernel_nexthops_enabled(void) +{ + return g_nexthops_enabled; +} diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index c2e173e0947d..4d001944b7f2 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -153,6 +153,13 @@ struct nhg_ctx { enum nhg_ctx_status status; }; +/* Global control to disable use of kernel nexthops, if available. We can't + * force the kernel to support nexthop ids, of course, but we can disable + * zebra's use of them, for testing e.g. By default, if the kernel supports + * nexthop ids, zebra uses them. + */ +void zebra_nhg_enable_kernel_nexthops(bool set); +bool zebra_nhg_kernel_nexthops_enabled(void); /** * NHE abstracted tree functions. @@ -227,4 +234,5 @@ extern void zebra_nhg_sweep_table(struct hash *hash); /* Nexthop resolution processing */ struct route_entry; /* Forward ref to avoid circular includes */ extern int nexthop_active_update(struct route_node *rn, struct route_entry *re); -#endif + +#endif /* __ZEBRA_NHG_H__ */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 78001da170a1..866b38b47e48 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1410,6 +1410,19 @@ DEFPY (show_nexthop_group, return CMD_SUCCESS; } +DEFPY_HIDDEN(nexthop_group_use_enable, + nexthop_group_use_enable_cmd, + "[no] zebra nexthop kernel enable", + NO_STR + ZEBRA_STR + "Nexthop configuration \n" + "Configure use of kernel nexthops\n" + "Enable kernel nexthops\n") +{ + zebra_nhg_enable_kernel_nexthops(!no); + return CMD_SUCCESS; +} + DEFUN (no_ip_nht_default_route, no_ip_nht_default_route_cmd, "no ip nht resolve-via-default", @@ -3121,6 +3134,10 @@ static int config_write_protocol(struct vty *vty) /* Include dataplane info */ dplane_config_write_helper(vty); + /* Include nexthop-group config */ + if (!zebra_nhg_kernel_nexthops_enabled()) + vty_out(vty, "no zebra nexthop kernel enable\n"); + return 1; } @@ -3492,6 +3509,7 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd); install_element(CONFIG_NODE, &zebra_packet_process_cmd); install_element(CONFIG_NODE, &no_zebra_packet_process_cmd); + install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd); install_element(VIEW_NODE, &show_nexthop_group_cmd); install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);