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.kicin...@netronome.com>
Reviewed-by: Quentin Monnet <quentin.mon...@netronome.com>
---
 include/linux/netdevice.h | 8 ++++++++
 net/core/ethtool.c        | 7 +++++++
 2 files changed, 15 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a5a34f0fb485..c0df40deec54 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3566,7 +3566,15 @@ int dev_change_xdp_fd(struct net_device *dev, struct 
netlink_ext_ack *extack,
                      int fd, u32 flags);
 u32 __dev_xdp_query(struct net_device *dev, bpf_op_t xdp_op,
                    enum bpf_netdev_command cmd);
+
+#if defined(CONFIG_XDP_SOCKETS)
 int xdp_umem_query(struct net_device *dev, u16 queue_id);
+#else
+static inline int xdp_umem_query(struct net_device *dev, u16 queue_id)
+{
+       return 0;
+}
+#endif
 
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4d5093577fe6..a8e693de5b11 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1745,6 +1745,7 @@ static noinline_for_stack int ethtool_set_channels(struct 
net_device *dev,
 {
        struct ethtool_channels channels, curr = { .cmd = ETHTOOL_GCHANNELS };
        u32 max_rx_in_use = 0;
+       unsigned int i;
 
        if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels)
                return -EOPNOTSUPP;
@@ -1768,6 +1769,12 @@ 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 */
+       for (i = channels.combined_count + channels.rx_count;
+            i < curr.combined_count + curr.rx_count; i++)
+               if (xdp_umem_query(dev, i) > 0)
+                       return -EINVAL;
+
        return dev->ethtool_ops->set_channels(dev, &channels);
 }
 
-- 
2.17.1

Reply via email to