virtio-net: Fix hash reporting when the queue changes

virtio_net_process_rss() fills the values used for hash reporting, but
the values used to be thrown away with a recursive function call if
the queue changes after RSS. Avoid the function call to keep the values.

Fixes: a4c960eedc ("virtio-net: Do not write hashes to peer buffer")
Buglink: https://issues.redhat.com/browse/RHEL-59572
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Akihiko Odaki 2024-11-22 14:03:10 +09:00 committed by Jason Wang
parent 162bdb8113
commit 1981fa9d7d

View file

@ -1898,10 +1898,10 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
} }
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
size_t size, bool no_rss) size_t size)
{ {
VirtIONet *n = qemu_get_nic_opaque(nc); VirtIONet *n = qemu_get_nic_opaque(nc);
VirtIONetQueue *q = virtio_net_get_subqueue(nc); VirtIONetQueue *q;
VirtIODevice *vdev = VIRTIO_DEVICE(n); VirtIODevice *vdev = VIRTIO_DEVICE(n);
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE]; VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
size_t lens[VIRTQUEUE_MAX_SIZE]; size_t lens[VIRTQUEUE_MAX_SIZE];
@ -1911,12 +1911,10 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
size_t offset, i, guest_offset, j; size_t offset, i, guest_offset, j;
ssize_t err; ssize_t err;
if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) { if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr); int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
if (index >= 0) { if (index >= 0) {
NetClientState *nc2 = nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
return virtio_net_receive_rcu(nc2, buf, size, true);
} }
} }
@ -1924,6 +1922,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
return -1; return -1;
} }
q = virtio_net_get_subqueue(nc);
/* hdr_len refers to the header we supply to the guest */ /* hdr_len refers to the header we supply to the guest */
if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) { if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
return 0; return 0;
@ -2049,7 +2049,7 @@ static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
{ {
RCU_READ_LOCK_GUARD(); RCU_READ_LOCK_GUARD();
return virtio_net_receive_rcu(nc, buf, size, false); return virtio_net_receive_rcu(nc, buf, size);
} }
/* /*