Message ID | 1478506829-9208-4-git-send-email-yuri.benditovich@daynix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 2016年11月07日 16:20, yuri.benditovich@daynix.com wrote: > From: Yuri Benditovich <yuri.benditovich@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.benditovich@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
On Tue, Nov 8, 2016 at 8:48 AM, Jason Wang <jasowang@redhat.com> wrote: > > > On 2016年11月07日 16:20, yuri.benditovich@daynix.com wrote: > >> From: Yuri Benditovich <yuri.benditovich@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.benditovich@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 > I will prepare v2 with support for timer configuration. But in case of vhost virtio_net_flush_tx() never called and without vhost I did not succeed to reproduce the problem.
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; }