Commit 6243375f9bba12d8871ac611ca8ce947c3e16c67

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent 783527a9

virtio-net: implement async packet sending

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 1 changed file with 37 additions and 2 deletions
hw/virtio-net.c
@@ -32,6 +32,10 @@ typedef struct VirtIONet @@ -32,6 +32,10 @@ typedef struct VirtIONet
32 VLANClientState *vc; 32 VLANClientState *vc;
33 QEMUTimer *tx_timer; 33 QEMUTimer *tx_timer;
34 int tx_timer_active; 34 int tx_timer_active;
  35 + struct {
  36 + VirtQueueElement elem;
  37 + ssize_t len;
  38 + } async_tx;
35 int mergeable_rx_bufs; 39 int mergeable_rx_bufs;
36 uint8_t promisc; 40 uint8_t promisc;
37 uint8_t allmulti; 41 uint8_t allmulti;
@@ -483,6 +487,21 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_ @@ -483,6 +487,21 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_
483 return size; 487 return size;
484 } 488 }
485 489
  490 +static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq);
  491 +
  492 +static void virtio_net_tx_complete(VLANClientState *vc, ssize_t len)
  493 +{
  494 + VirtIONet *n = vc->opaque;
  495 +
  496 + virtqueue_push(n->tx_vq, &n->async_tx.elem, n->async_tx.len);
  497 + virtio_notify(&n->vdev, n->tx_vq);
  498 +
  499 + n->async_tx.elem.out_num = n->async_tx.len = 0;
  500 +
  501 + virtio_queue_set_notification(n->tx_vq, 1);
  502 + virtio_net_flush_tx(n, n->tx_vq);
  503 +}
  504 +
486 /* TX */ 505 /* TX */
487 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) 506 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
488 { 507 {
@@ -492,8 +511,13 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) @@ -492,8 +511,13 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
492 if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) 511 if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
493 return; 512 return;
494 513
  514 + if (n->async_tx.elem.out_num) {
  515 + virtio_queue_set_notification(n->tx_vq, 0);
  516 + return;
  517 + }
  518 +
495 while (virtqueue_pop(vq, &elem)) { 519 while (virtqueue_pop(vq, &elem)) {
496 - ssize_t len = 0; 520 + ssize_t ret, len = 0;
497 unsigned int out_num = elem.out_num; 521 unsigned int out_num = elem.out_num;
498 struct iovec *out_sg = &elem.out_sg[0]; 522 struct iovec *out_sg = &elem.out_sg[0];
499 unsigned hdr_len; 523 unsigned hdr_len;
@@ -520,7 +544,16 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) @@ -520,7 +544,16 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
520 len += hdr_len; 544 len += hdr_len;
521 } 545 }
522 546
523 - len += qemu_sendv_packet(n->vc, out_sg, out_num); 547 + ret = qemu_sendv_packet_async(n->vc, out_sg, out_num,
  548 + virtio_net_tx_complete);
  549 + if (ret == 0) {
  550 + virtio_queue_set_notification(n->tx_vq, 0);
  551 + n->async_tx.elem = elem;
  552 + n->async_tx.len = len;
  553 + return;
  554 + }
  555 +
  556 + len += ret;
524 557
525 virtqueue_push(vq, &elem, len); 558 virtqueue_push(vq, &elem, len);
526 virtio_notify(&n->vdev, vq); 559 virtio_notify(&n->vdev, vq);
@@ -663,6 +696,8 @@ static void virtio_net_cleanup(VLANClientState *vc) @@ -663,6 +696,8 @@ static void virtio_net_cleanup(VLANClientState *vc)
663 { 696 {
664 VirtIONet *n = vc->opaque; 697 VirtIONet *n = vc->opaque;
665 698
  699 + qemu_purge_queued_packets(vc);
  700 +
666 unregister_savevm("virtio-net", n); 701 unregister_savevm("virtio-net", n);
667 702
668 qemu_free(n->mac_table.macs); 703 qemu_free(n->mac_table.macs);