Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jakub Kicinski and committed by
Daniel Borkmann
1661d346 b8c8a2e2

+20 -2
+7
include/net/xdp_sock.h
··· 86 86 struct xdp_umem_fq_reuse *xsk_reuseq_swap(struct xdp_umem *umem, 87 87 struct xdp_umem_fq_reuse *newq); 88 88 void xsk_reuseq_free(struct xdp_umem_fq_reuse *rq); 89 + struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev, u16 queue_id); 89 90 90 91 static inline char *xdp_umem_get_data(struct xdp_umem *umem, u64 addr) 91 92 { ··· 182 181 } 183 182 static inline void xsk_reuseq_free(struct xdp_umem_fq_reuse *rq) 184 183 { 184 + } 185 + 186 + static inline struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev, 187 + u16 queue_id) 188 + { 189 + return NULL; 185 190 } 186 191 187 192 static inline char *xdp_umem_get_data(struct xdp_umem *umem, u64 addr)
+11
net/core/ethtool.c
··· 27 27 #include <linux/rtnetlink.h> 28 28 #include <linux/sched/signal.h> 29 29 #include <linux/net.h> 30 + #include <net/xdp_sock.h> 30 31 31 32 /* 32 33 * Some useful ethtool_ops methods that're device independent. ··· 1657 1656 void __user *useraddr) 1658 1657 { 1659 1658 struct ethtool_channels channels, curr = { .cmd = ETHTOOL_GCHANNELS }; 1659 + u16 from_channel, to_channel; 1660 1660 u32 max_rx_in_use = 0; 1661 + unsigned int i; 1661 1662 1662 1663 if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels) 1663 1664 return -EOPNOTSUPP; ··· 1682 1679 !ethtool_get_max_rxfh_channel(dev, &max_rx_in_use) && 1683 1680 (channels.combined_count + channels.rx_count) <= max_rx_in_use) 1684 1681 return -EINVAL; 1682 + 1683 + /* Disabling channels, query zero-copy AF_XDP sockets */ 1684 + from_channel = channels.combined_count + 1685 + min(channels.rx_count, channels.tx_count); 1686 + to_channel = curr.combined_count + max(curr.rx_count, curr.tx_count); 1687 + for (i = from_channel; i < to_channel; i++) 1688 + if (xdp_get_umem_from_qid(dev, i)) 1689 + return -EINVAL; 1685 1690 1686 1691 return dev->ethtool_ops->set_channels(dev, &channels); 1687 1692 }
+2 -2
net/xdp/xdp_umem.c
··· 55 55 dev->_tx[queue_id].umem = umem; 56 56 } 57 57 58 - static struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev, 59 - u16 queue_id) 58 + struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev, 59 + u16 queue_id) 60 60 { 61 61 if (queue_id < dev->real_num_rx_queues) 62 62 return dev->_rx[queue_id].umem;