static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)

{

    VirtQueueElement elem;



    if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))

        return;



    if (n->async_tx.elem.out_num) {

        virtio_queue_set_notification(n->tx_vq, 0);

        return;

    }



    while (virtqueue_pop(vq, &elem)) {

        ssize_t ret, len = 0;

        unsigned int out_num = elem.out_num;

        struct iovec *out_sg = &elem.out_sg[0];

        unsigned hdr_len;



        /* hdr_len refers to the header received from the guest */

        hdr_len = n->mergeable_rx_bufs ?

            sizeof(struct virtio_net_hdr_mrg_rxbuf) :

            sizeof(struct virtio_net_hdr);



        if (out_num < 1 || out_sg->iov_len != hdr_len) {

            fprintf(stderr, "virtio-net header not in first element\n");

            exit(1);

        }



        /* ignore the header if GSO is not supported */

        if (!n->has_vnet_hdr) {

            out_num--;

            out_sg++;

            len += hdr_len;

        } else if (n->mergeable_rx_bufs) {

            /* tapfd expects a struct virtio_net_hdr */

            hdr_len -= sizeof(struct virtio_net_hdr);

            out_sg->iov_len -= hdr_len;

            len += hdr_len;

        }



        ret = qemu_sendv_packet_async(&n->nic->nc, out_sg, out_num,

                                      virtio_net_tx_complete);

        if (ret == 0) {

            virtio_queue_set_notification(n->tx_vq, 0);

            n->async_tx.elem = elem;

            n->async_tx.len  = len;

            return;

        }



        len += ret;



        virtqueue_push(vq, &elem, len);

        virtio_notify(&n->vdev, vq);

    }

}

static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)

{

    VirtQueueElement elem;



    if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))

        return;



    if (n->async_tx.elem.out_num) {

        virtio_queue_set_notification(n->tx_vq, 0);

        return;

    }



    while (virtqueue_pop(vq, &elem)) {

        ssize_t ret, len = 0;

        unsigned int out_num = elem.out_num;

        struct iovec *out_sg = &elem.out_sg[0];

        unsigned hdr_len;



        

        hdr_len = n->mergeable_rx_bufs ?

            sizeof(struct virtio_net_hdr_mrg_rxbuf) :

            sizeof(struct virtio_net_hdr);



        if (out_num < 1 || out_sg->iov_len != hdr_len) {

            fprintf(stderr, "virtio-net header not in first element\n");

            exit(1);

        }



        

        if (!n->has_vnet_hdr) {

            out_num--;

            out_sg++;

            len += hdr_len;

        } else if (n->mergeable_rx_bufs) {

            

            hdr_len -= sizeof(struct virtio_net_hdr);

            out_sg->iov_len -= hdr_len;

            len += hdr_len;

        }



        ret = qemu_sendv_packet_async(&n->nic->nc, out_sg, out_num,

                                      virtio_net_tx_complete);

        if (ret == 0) {

            virtio_queue_set_notification(n->tx_vq, 0);

            n->async_tx.elem = elem;

            n->async_tx.len  = len;

            return;

        }



        len += ret;



        virtqueue_push(vq, &elem, len);

        virtio_notify(&n->vdev, vq);

    }

}

static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)     if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
static void FUNC_0(VirtIONet *VAR_0, VirtQueue *VAR_1)

{

    VirtQueueElement elem;



    if (!(VAR_0->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))

        return;



    if (VAR_0->async_tx.elem.VAR_2) {

        virtio_queue_set_notification(VAR_0->tx_vq, 0);

        return;

    }



    while (virtqueue_pop(VAR_1, &elem)) {

        ssize_t ret, len = 0;

        unsigned int VAR_2 = elem.VAR_2;

        struct iovec *VAR_3 = &elem.VAR_3[0];

        unsigned VAR_4;



        

        VAR_4 = VAR_0->mergeable_rx_bufs ?

            sizeof(struct virtio_net_hdr_mrg_rxbuf) :

            sizeof(struct virtio_net_hdr);



        if (VAR_2 < 1 || VAR_3->iov_len != VAR_4) {

            fprintf(stderr, "virtio-net header not in first element\VAR_0");

            exit(1);

        }



        

        if (!VAR_0->has_vnet_hdr) {

            VAR_2--;

            VAR_3++;

            len += VAR_4;

        } else if (VAR_0->mergeable_rx_bufs) {

            

            VAR_4 -= sizeof(struct virtio_net_hdr);

            VAR_3->iov_len -= VAR_4;

            len += VAR_4;

        }



        ret = qemu_sendv_packet_async(&VAR_0->nic->nc, VAR_3, VAR_2,

                                      virtio_net_tx_complete);

        if (ret == 0) {

            virtio_queue_set_notification(VAR_0->tx_vq, 0);

            VAR_0->async_tx.elem = elem;

            VAR_0->async_tx.len  = len;

            return;

        }



        len += ret;



        virtqueue_push(VAR_1, &elem, len);

        virtio_notify(&VAR_0->vdev, VAR_1);

    }

}

static void FUNC_0(VirtIONet *VAR_0, VirtQueue *VAR_1)
{ VirtQueueElement elem; if (!(VAR_0->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return; if (VAR_0->async_tx.elem.VAR_2) { virtio_queue_set_notification(VAR_0->tx_vq, 0); return; } while (virtqueue_pop(VAR_1, &elem)) { ssize_t ret, len = 0; unsigned int VAR_2 = elem.VAR_2; struct iovec *VAR_3 = &elem.VAR_3[0]; unsigned VAR_4; VAR_4 = VAR_0->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) :
sizeof(struct virtio_net_hdr); if (VAR_2 < 1 || VAR_3->iov_len != VAR_4) { fprintf(stderr, "virtio-net header not in first element\VAR_0"); exit(1); } if (!VAR_0->has_vnet_hdr) { VAR_2--; VAR_3++; len += VAR_4; } else if (VAR_0->mergeable_rx_bufs) { VAR_4 -= sizeof(struct virtio_net_hdr); VAR_3->iov_len -= VAR_4; len += VAR_4; } ret = qemu_sendv_packet_async(&VAR_0->nic->nc, VAR_3, VAR_2,
virtio_net_tx_complete); if (ret == 0) { virtio_queue_set_notification(VAR_0->tx_vq, 0); VAR_0->async_tx.elem = elem; VAR_0->async_tx.len  = len; return; } len += ret; virtqueue_push(VAR_1, &elem, len); virtio_notify(&VAR_0->vdev, VAR_1); } }