Commit 6243375f9bba12d8871ac611ca8ce947c3e16c67
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); |