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

virtio_net: clamp rss_max_key_size to NETDEV_RSS_KEY_LEN

rss_max_key_size in the virtio spec is the maximum key size supported by
the device, not a mandatory size the driver must use. Also the value 40
is a spec minimum, not a spec maximum.

The current code rejects RSS and can fail probe when the device reports a
larger rss_max_key_size than the driver buffer limit. Instead, clamp the
effective key length to min(device rss_max_key_size, NETDEV_RSS_KEY_LEN)
and keep RSS enabled.

This keeps probe working on devices that advertise larger maximum key sizes
while respecting the netdev RSS key buffer size limit.

Fixes: 3f7d9c1964fc ("virtio_net: Add hash_key_length check")
Cc: stable@vger.kernel.org
Signed-off-by: Srujana Challa <schalla@marvell.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Link: https://patch.msgid.link/20260326142344.1171317-1-schalla@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Srujana Challa and committed by
Jakub Kicinski
b4e5f04c d64cb81d

+9 -11
+9 -11
drivers/net/virtio_net.c
··· 381 381 struct xdp_buff **xsk_buffs; 382 382 }; 383 383 384 - #define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 385 - 386 384 /* Control VQ buffers: protected by the rtnl lock */ 387 385 struct control_buf { 388 386 struct virtio_net_ctrl_hdr hdr; ··· 484 486 485 487 /* Must be last as it ends in a flexible-array member. */ 486 488 TRAILING_OVERLAP(struct virtio_net_rss_config_trailer, rss_trailer, hash_key_data, 487 - u8 rss_hash_key_data[VIRTIO_NET_RSS_MAX_KEY_SIZE]; 489 + u8 rss_hash_key_data[NETDEV_RSS_KEY_LEN]; 488 490 ); 489 491 }; 490 492 static_assert(offsetof(struct virtnet_info, rss_trailer.hash_key_data) == ··· 6706 6708 struct virtnet_info *vi; 6707 6709 u16 max_queue_pairs; 6708 6710 int mtu = 0; 6711 + u16 key_sz; 6709 6712 6710 6713 /* Find if host supports multiqueue/rss virtio_net device */ 6711 6714 max_queue_pairs = 1; ··· 6841 6842 } 6842 6843 6843 6844 if (vi->has_rss || vi->has_rss_hash_report) { 6844 - vi->rss_key_size = 6845 - virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size)); 6846 - if (vi->rss_key_size > VIRTIO_NET_RSS_MAX_KEY_SIZE) { 6847 - dev_err(&vdev->dev, "rss_max_key_size=%u exceeds the limit %u.\n", 6848 - vi->rss_key_size, VIRTIO_NET_RSS_MAX_KEY_SIZE); 6849 - err = -EINVAL; 6850 - goto free; 6851 - } 6845 + key_sz = virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size)); 6846 + 6847 + vi->rss_key_size = min_t(u16, key_sz, NETDEV_RSS_KEY_LEN); 6848 + if (key_sz > vi->rss_key_size) 6849 + dev_warn(&vdev->dev, 6850 + "rss_max_key_size=%u exceeds driver limit %u, clamping\n", 6851 + key_sz, vi->rss_key_size); 6852 6852 6853 6853 vi->rss_hash_types_supported = 6854 6854 virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types));