diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 4bc111422a..4b09a930ef 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -367,12 +367,19 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) qemu_notify_event(); } -static int do_virtio_net_can_receive(VirtIONet *n, int bufsize) +static int virtio_net_can_receive(VLANClientState *vc) { + VirtIONet *n = vc->opaque; + if (!virtio_queue_ready(n->rx_vq) || !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) return 0; + return 1; +} + +static int virtio_net_has_buffers(VirtIONet *n, int bufsize) +{ if (virtio_queue_empty(n->rx_vq) || (n->mergeable_rx_bufs && !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) { @@ -384,13 +391,6 @@ static int do_virtio_net_can_receive(VirtIONet *n, int bufsize) return 1; } -static int virtio_net_can_receive(VLANClientState *vc) -{ - VirtIONet *n = vc->opaque; - - return do_virtio_net_can_receive(n, VIRTIO_NET_MAX_BUFSIZE); -} - /* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so * it never finds out that the packets don't have valid checksums. This * causes dhclient to get upset. Fedora's carried a patch for ages to @@ -517,7 +517,10 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_ struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; size_t hdr_len, offset, i; - if (!do_virtio_net_can_receive(n, size)) + if (!virtio_net_can_receive(n->vc)) + return -1; + + if (!virtio_net_has_buffers(n, size)) return 0; if (!receive_filter(n, buf, size))