]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net, ethtool: Disallow leased real rxqs to be resized
authorDaniel Borkmann <daniel@iogearbox.net>
Thu, 15 Jan 2026 08:25:51 +0000 (09:25 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 20 Jan 2026 10:58:49 +0000 (11:58 +0100)
Similar to AF_XDP, do not allow queues in a physical netdev to be
resized by ethtool -L when they are leased.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Co-developed-by: David Wei <dw@davidwei.uk>
Signed-off-by: David Wei <dw@davidwei.uk>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260115082603.219152-5-daniel@iogearbox.net
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/ethtool/channels.c
net/ethtool/ioctl.c

index ca4f80282448b680543e1b579adb1de6d67ade11..797d2a08c5153470ec5b9bc51ade9d2c1468ae43 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
-#include <net/xdp_sock_drv.h>
+#include <net/netdev_queues.h>
 
 #include "netlink.h"
 #include "common.h"
@@ -169,14 +169,16 @@ 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++) {
+               if (netdev_queue_busy(dev, i, 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;
index 9431e305b2333f4e99464f59ff3d591c4a658d2a..02a3454234d6b7c67d129b7a90ba4d6ecb0471cb 100644 (file)
 #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"
 
 /* State held across locks and calls for commands which have devlink fallback */
@@ -2282,12 +2283,12 @@ 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))
+               if (netdev_queue_busy(dev, i, NULL))
                        return -EINVAL;
 
        ret = dev->ethtool_ops->set_channels(dev, &channels);