[PATCH net-next v10 04/14] net, ethtool: Disallow leased real rxqs to be resized
From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2026-03-27 12:11:17
Also in:
bpf
Subsystem:
networking [ethtool], networking [general], the rest · Maintainers:
Andrew Lunn, Jakub Kicinski, "David S. Miller", Eric Dumazet, Paolo Abeni, Linus Torvalds
Similar to AF_XDP, do not allow queues in a physical netdev to be resized by ethtool -L when they are leased. Cover channel resize paths (both netlink and ioctl) to reject resizing when the queues would be affected. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Co-developed-by: David Wei <redacted> Signed-off-by: David Wei <redacted> --- net/ethtool/channels.c | 17 ++++++++++++----- net/ethtool/ioctl.c | 16 +++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/net/ethtool/channels.c b/net/ethtool/channels.c
index 45232cf1c144..63ed5ebf19a8 100644
--- a/net/ethtool/channels.c
+++ b/net/ethtool/channels.c@@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only -#include <net/xdp_sock_drv.h> +#include <net/netdev_queues.h> #include "common.h" #include "netlink.h"
@@ -169,14 +169,21 @@ ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info) if (ret) return ret; - /* Disabling channels, query zero-copy AF_XDP sockets */ + /* ensure channels are not busy at the moment */ from_channel = channels.combined_count + min(channels.rx_count, channels.tx_count); - for (i = from_channel; i < old_total; i++) - if (xsk_get_pool_from_qid(dev, i)) { - GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing zerocopy AF_XDP sockets"); + for (i = from_channel; i < old_total; i++) { + bool losing_rx = i >= channels.combined_count + + channels.rx_count; + + if (netdev_queue_busy(dev, i, + losing_rx ? NETDEV_QUEUE_TYPE_RX : + NETDEV_QUEUE_TYPE_TX, NULL)) { + GENL_SET_ERR_MSG(info, + "requested channel counts are too low due to busy queues (AF_XDP or queue leasing)"); return -EINVAL; } + } ret = dev->ethtool_ops->set_channels(dev, &channels); return ret < 0 ? ret : 1;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 3c713a91ad0d..f7288bc6cae4 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c@@ -27,12 +27,12 @@ #include <linux/net.h> #include <linux/pm_runtime.h> #include <linux/utsname.h> +#include <linux/ethtool_netlink.h> #include <net/devlink.h> #include <net/ipv6.h> -#include <net/xdp_sock_drv.h> #include <net/flow_offload.h> #include <net/netdev_lock.h> -#include <linux/ethtool_netlink.h> +#include <net/netdev_queues.h> #include "common.h"
@@ -2284,13 +2284,19 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev, if (ret) return ret; - /* Disabling channels, query zero-copy AF_XDP sockets */ + /* Disabling channels, query busy queues (AF_XDP, queue leasing) */ from_channel = channels.combined_count + min(channels.rx_count, channels.tx_count); to_channel = curr.combined_count + max(curr.rx_count, curr.tx_count); - for (i = from_channel; i < to_channel; i++) - if (xsk_get_pool_from_qid(dev, i)) + for (i = from_channel; i < to_channel; i++) { + bool losing_rx = i >= channels.combined_count + + channels.rx_count; + + if (netdev_queue_busy(dev, i, + losing_rx ? NETDEV_QUEUE_TYPE_RX : + NETDEV_QUEUE_TYPE_TX, NULL)) return -EINVAL; + } ret = dev->ethtool_ops->set_channels(dev, &channels); if (!ret)
--
2.43.0