[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-stable] [PATCH 046/113] virtio_net: flush uncompleted TX on reset
From: |
Michael Roth |
Subject: |
[Qemu-stable] [PATCH 046/113] virtio_net: flush uncompleted TX on reset |
Date: |
Mon, 18 Jun 2018 20:42:12 -0500 |
From: Greg Kurz <address@hidden>
If the backend could not transmit a packet right away for some reason,
the packet is queued for asynchronous sending. The corresponding vq
element is tracked in the async_tx.elem field of the VirtIONetQueue,
for later freeing when the transmission is complete.
If a reset happens before completion, virtio_net_tx_complete() will push
async_tx.elem back to the guest anyway, and we end up with the inuse flag
of the vq being equal to -1. The next call to virtqueue_pop() is then
likely to fail with "Virtqueue size exceeded".
This can be reproduced easily by starting a guest with an hubport backend
that is not connected to a functional network, eg,
-device virtio-net-pci,netdev=hub0 -netdev hubport,id=hub0,hubid=0
and no other -netdev hubport,hubid=0 on the command line.
The appropriate fix is to ensure that such an asynchronous transmission
cannot survive a device reset. So for all queues, we first try to send
the packet again, and eventually we purge it if the backend still could
not deliver it.
CC: address@hidden
Reported-by: R. Nageswara Sastry <address@hidden>
Buglink: https://github.com/open-power-host-os/qemu/issues/37
Signed-off-by: Greg Kurz <address@hidden>
Tested-by: R. Nageswara Sastry <address@hidden>
Signed-off-by: Jason Wang <address@hidden>
(cherry picked from commit 94b52958b77a2a040564cf7ed716d3a9545d94e5)
Signed-off-by: Michael Roth <address@hidden>
---
hw/net/virtio-net.c | 11 +++++++++++
include/net/net.h | 1 +
net/net.c | 1 -
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 38674b08aa..6bdef38ceb 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -422,6 +422,7 @@ static RxFilterInfo
*virtio_net_query_rxfilter(NetClientState *nc)
static void virtio_net_reset(VirtIODevice *vdev)
{
VirtIONet *n = VIRTIO_NET(vdev);
+ int i;
/* Reset back to compatibility mode */
n->promisc = 1;
@@ -445,6 +446,16 @@ static void virtio_net_reset(VirtIODevice *vdev)
memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
memset(n->vlans, 0, MAX_VLAN >> 3);
+
+ /* Flush any async TX */
+ for (i = 0; i < n->max_queues; i++) {
+ NetClientState *nc = qemu_get_subqueue(n->nic, i);
+
+ if (nc->peer) {
+ qemu_flush_or_purge_queued_packets(nc->peer, true);
+ assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
+ }
+ }
}
static void peer_test_vnet_hdr(VirtIONet *n)
diff --git a/include/net/net.h b/include/net/net.h
index 1c55a93588..ab87d426e1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -156,6 +156,7 @@ ssize_t qemu_send_packet_async(NetClientState *nc, const
uint8_t *buf,
int size, NetPacketSent *sent_cb);
void qemu_purge_queued_packets(NetClientState *nc);
void qemu_flush_queued_packets(NetClientState *nc);
+void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge);
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]);
bool qemu_has_ufo(NetClientState *nc);
bool qemu_has_vnet_hdr(NetClientState *nc);
diff --git a/net/net.c b/net/net.c
index 39ef546708..0719358d03 100644
--- a/net/net.c
+++ b/net/net.c
@@ -612,7 +612,6 @@ void qemu_purge_queued_packets(NetClientState *nc)
qemu_net_queue_purge(nc->peer->incoming_queue, nc);
}
-static
void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
{
nc->receive_disabled = 0;
--
2.11.0
- [Qemu-stable] [PATCH 037/113] multiboot: Remove unused variables from multiboot.c, (continued)
- [Qemu-stable] [PATCH 037/113] multiboot: Remove unused variables from multiboot.c, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 039/113] multiboot: fprintf(stderr...) -> error_report(), Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 038/113] multiboot: Use header names when displaying fields, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 040/113] multiboot: Reject kernels exceeding the address space, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 003/113] virtio-balloon: unref the memory region before continuing, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 041/113] multiboot: Check validity of mh_header_addr, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 043/113] tests/multiboot: Add tests for the a.out kludge, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 044/113] tests/multiboot: Add .gitignore, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 042/113] tests/multiboot: Test exit code for every qemu run, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 045/113] arm/translate-a64: treat DISAS_UPDATE as variant of DISAS_EXIT, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 046/113] virtio_net: flush uncompleted TX on reset,
Michael Roth <=
- [Qemu-stable] [PATCH 047/113] qemu-pr-helper: Actually allow users to specify pidfile, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 049/113] iotests: Test preallocated truncate of 2G image, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 048/113] block/file-posix: Fix fully preallocated truncate, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 050/113] tcg: Mark muluh_i64 and mulsh_i64 as 64-bit ops, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 004/113] memfd: fix configure test, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 051/113] target/i386: Fix andn instruction, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 052/113] exec: fix memory leak in find_max_supported_pagesize(), Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 053/113] gluster: Fix blockdev-add with server.N.type=unix, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 054/113] cpus.c: ensure running CPU recalculates icount deadlines on timer expiry, Michael Roth, 2018/06/18
- [Qemu-stable] [PATCH 056/113] hw/block/pflash_cfi: fix off-by-one error, Michael Roth, 2018/06/18