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;
|
VLANClientState *vc;
|
||||||
QEMUTimer *tx_timer;
|
QEMUTimer *tx_timer;
|
||||||
int tx_timer_active;
|
int tx_timer_active;
|
||||||
|
struct {
|
||||||
|
VirtQueueElement elem;
|
||||||
|
ssize_t len;
|
||||||
|
} async_tx;
|
||||||
int mergeable_rx_bufs;
|
int mergeable_rx_bufs;
|
||||||
uint8_t promisc;
|
uint8_t promisc;
|
||||||
uint8_t allmulti;
|
uint8_t allmulti;
|
||||||
|
@ -483,6 +487,21 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_
|
||||||
return 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 */
|
/* TX */
|
||||||
static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
|
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))
|
if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (n->async_tx.elem.out_num) {
|
||||||
|
virtio_queue_set_notification(n->tx_vq, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (virtqueue_pop(vq, &elem)) {
|
while (virtqueue_pop(vq, &elem)) {
|
||||||
ssize_t len = 0;
|
ssize_t ret, len = 0;
|
||||||
unsigned int out_num = elem.out_num;
|
unsigned int out_num = elem.out_num;
|
||||||
struct iovec *out_sg = &elem.out_sg[0];
|
struct iovec *out_sg = &elem.out_sg[0];
|
||||||
unsigned hdr_len;
|
unsigned hdr_len;
|
||||||
|
@ -520,7 +544,16 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
|
||||||
len += hdr_len;
|
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);
|
virtqueue_push(vq, &elem, len);
|
||||||
virtio_notify(&n->vdev, vq);
|
virtio_notify(&n->vdev, vq);
|
||||||
|
@ -663,6 +696,8 @@ static void virtio_net_cleanup(VLANClientState *vc)
|
||||||
{
|
{
|
||||||
VirtIONet *n = vc->opaque;
|
VirtIONet *n = vc->opaque;
|
||||||
|
|
||||||
|
qemu_purge_queued_packets(vc);
|
||||||
|
|
||||||
unregister_savevm("virtio-net", n);
|
unregister_savevm("virtio-net", n);
|
||||||
|
|
||||||
qemu_free(n->mac_table.macs);
|
qemu_free(n->mac_table.macs);
|
||||||
|
|
Loading…
Reference in a new issue