virtio-net: implement async packet sending
Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
783527a9ef
commit
6243375f9b
@ -32,6 +32,10 @@ typedef struct VirtIONet
|
||||
VLANClientState *vc;
|
||||
QEMUTimer *tx_timer;
|
||||
int tx_timer_active;
|
||||
struct {
|
||||
VirtQueueElement elem;
|
||||
ssize_t len;
|
||||
} async_tx;
|
||||
int mergeable_rx_bufs;
|
||||
uint8_t promisc;
|
||||
uint8_t allmulti;
|
||||
@ -483,6 +487,21 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_
|
||||
return size;
|
||||
}
|
||||
|
||||
static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq);
|
||||
|
||||
static void virtio_net_tx_complete(VLANClientState *vc, ssize_t len)
|
||||
{
|
||||
VirtIONet *n = vc->opaque;
|
||||
|
||||
virtqueue_push(n->tx_vq, &n->async_tx.elem, n->async_tx.len);
|
||||
virtio_notify(&n->vdev, n->tx_vq);
|
||||
|
||||
n->async_tx.elem.out_num = n->async_tx.len = 0;
|
||||
|
||||
virtio_queue_set_notification(n->tx_vq, 1);
|
||||
virtio_net_flush_tx(n, n->tx_vq);
|
||||
}
|
||||
|
||||
/* TX */
|
||||
static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
|
||||
{
|
||||
@ -492,8 +511,13 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
|
||||
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 len = 0;
|
||||
ssize_t ret, len = 0;
|
||||
unsigned int out_num = elem.out_num;
|
||||
struct iovec *out_sg = &elem.out_sg[0];
|
||||
unsigned hdr_len;
|
||||
@ -520,7 +544,16 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
|
||||
len += hdr_len;
|
||||
}
|
||||
|
||||
len += qemu_sendv_packet(n->vc, out_sg, out_num);
|
||||
ret = qemu_sendv_packet_async(n->vc, 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);
|
||||
@ -663,6 +696,8 @@ static void virtio_net_cleanup(VLANClientState *vc)
|
||||
{
|
||||
VirtIONet *n = vc->opaque;
|
||||
|
||||
qemu_purge_queued_packets(vc);
|
||||
|
||||
unregister_savevm("virtio-net", n);
|
||||
|
||||
qemu_free(n->mac_table.macs);
|
||||
|
Loading…
Reference in New Issue
Block a user