From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46747) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHA5c-0006GI-Pi for qemu-devel@nongnu.org; Mon, 20 Jul 2015 08:22:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZHA5Y-0000ni-Kt for qemu-devel@nongnu.org; Mon, 20 Jul 2015 08:22:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42188) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHA5Y-0000m6-Fw for qemu-devel@nongnu.org; Mon, 20 Jul 2015 08:22:32 -0400 Date: Mon, 20 Jul 2015 15:12:23 +0300 From: "Michael S. Tsirkin" Message-ID: <1437394279-24416-6-git-send-email-mst@redhat.com> References: <1437394279-24416-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1437394279-24416-1-git-send-email-mst@redhat.com> Subject: [Qemu-devel] [PULL 5/6] virtio-net: Flush incoming queues when DRIVER_OK is being set List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Fam Zheng From: Fam Zheng This patch fixes network hang after "stop" then "cont", while network packets keep arriving. Tested both manually (tap, host pinging guest) and with Jason's qtest series (plus his "[PATCH 2.4] socket: pass correct size in net_socket_send()" fix). As virtio_net_set_status is called when guest driver is setting status byte and when vm state is changing, it is a good opportunity to flush queued packets. This is necessary because during vm stop the backend (e.g. tap) would stop rx processing after .can_receive returns false, until the queue is explicitly flushed or purged. The other interesting condition in .can_receive, virtio_queue_ready(), is handled by virtio_net_handle_rx() when guest kicks; the 3rd condition is invalid queue index which doesn't need flushing. Signed-off-by: Fam Zheng Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9f7e91d..e1d9cbf 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -162,6 +162,8 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) virtio_net_vhost_status(n, status); for (i = 0; i < n->max_queues; i++) { + NetClientState *ncs = qemu_get_subqueue(n->nic, i); + bool queue_started; q = &n->vqs[i]; if ((!n->multiqueue && i != 0) || i >= n->curr_queues) { @@ -169,12 +171,18 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) } else { queue_status = status; } + queue_started = + virtio_net_started(n, queue_status) && !n->vhost_started; + + if (queue_started) { + qemu_flush_queued_packets(ncs); + } if (!q->tx_waiting) { continue; } - if (virtio_net_started(n, queue_status) && !n->vhost_started) { + if (queue_started) { if (q->tx_timer) { timer_mod(q->tx_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); -- MST