On 2016年11月07日 16:20, yuri.benditov...@daynix.com wrote:
From: Yuri Benditovich <yuri.benditov...@daynix.com>

https://bugzilla.redhat.com/show_bug.cgi?id=1295637
Upon set_link monitor command or upon netdev deletion
virtio-net sends link down indication to the guest
and stops vhost if one is used.
Guest driver can still submit data for TX until it
recognizes link loss. If these packets not returned by
the host, the Windows guest will never be able to finish
disable/removal/shutdown.
Now each packet sent by guest after NIC indicated link
down will be completed immediately.

Signed-off-by: Yuri Benditovich <yuri.benditov...@daynix.com>
---
  hw/net/virtio-net.c | 15 +++++++++++++++
  1 file changed, 15 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 06bfe4b..6158de0 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1200,6 +1200,16 @@ static ssize_t virtio_net_receive(NetClientState *nc, 
const uint8_t *buf, size_t
      return size;
  }
+static void virtio_net_drop_tx_queue_data(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtQueueElement *elem;
+    while ((elem = virtqueue_pop(vq, sizeof(VirtQueueElement)))) {
+        virtqueue_push(vq, elem, 0);
+        virtio_notify(vdev, vq);
+        g_free(elem);
+    }
+}
+
  static int32_t virtio_net_flush_tx(VirtIONetQueue *q);
static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
@@ -1345,6 +1355,11 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, 
VirtQueue *vq)
      VirtIONet *n = VIRTIO_NET(vdev);
      VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
+ if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) {
+        virtio_net_drop_tx_queue_data(vdev, vq);
+        return;
+    }
+
      if (unlikely(q->tx_waiting)) {
          return;
      }

This doesn't work for tx timer, you may want to do the modification on virtio_net_flush_tx().

What's more, when link_down is true, qemu_send_packet_async() will return size of iov, can we do some check there?

Thanks

Reply via email to