aboutsummaryrefslogtreecommitdiff
path: root/net/core/ethtool.c
diff options
context:
space:
mode:
authorJakub Kicinski2018-10-01 14:51:36 +0200
committerDaniel Borkmann2018-10-05 09:31:01 +0200
commit1661d346628115c364e2b7d5b15a64ca3bd0dbd4 (patch)
tree858d4d16a1a04bcb862f0e0a92150f88d5b44f13 /net/core/ethtool.c
parentb8c8a2e2e3758be93959587e6b19aadbb0ce7275 (diff)
ethtool: don't allow disabling queues with umem installed
We already check the RSS indirection table does not use queues which would be disabled by channel reconfiguration. Make sure user does not try to disable queues which have a UMEM and zero-copy AF_XDP socket installed. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r--net/core/ethtool.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 9a648fb09594..5a788adeba0b 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -27,6 +27,7 @@
#include <linux/rtnetlink.h>
#include <linux/sched/signal.h>
#include <linux/net.h>
+#include <net/xdp_sock.h>
/*
* Some useful ethtool_ops methods that're device independent.
@@ -1656,7 +1657,9 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
void __user *useraddr)
{
struct ethtool_channels channels, curr = { .cmd = ETHTOOL_GCHANNELS };
+ u16 from_channel, to_channel;
u32 max_rx_in_use = 0;
+ unsigned int i;
if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels)
return -EOPNOTSUPP;
@@ -1680,6 +1683,14 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
(channels.combined_count + channels.rx_count) <= max_rx_in_use)
return -EINVAL;
+ /* Disabling channels, query zero-copy AF_XDP sockets */
+ 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 (xdp_get_umem_from_qid(dev, i))
+ return -EINVAL;
+
return dev->ethtool_ops->set_channels(dev, &channels);
}