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 | 32 | VLANClientState *vc; |
33 | 33 | QEMUTimer *tx_timer; |
34 | 34 | int tx_timer_active; |
35 | + struct { | |
36 | + VirtQueueElement elem; | |
37 | + ssize_t len; | |
38 | + } async_tx; | |
35 | 39 | int mergeable_rx_bufs; |
36 | 40 | uint8_t promisc; |
37 | 41 | uint8_t allmulti; |
... | ... | @@ -483,6 +487,21 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_ |
483 | 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 | 505 | /* TX */ |
487 | 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 | 511 | if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) |
493 | 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 | 519 | while (virtqueue_pop(vq, &elem)) { |
496 | - ssize_t len = 0; | |
520 | + ssize_t ret, len = 0; | |
497 | 521 | unsigned int out_num = elem.out_num; |
498 | 522 | struct iovec *out_sg = &elem.out_sg[0]; |
499 | 523 | unsigned hdr_len; |
... | ... | @@ -520,7 +544,16 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) |
520 | 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 | 558 | virtqueue_push(vq, &elem, len); |
526 | 559 | virtio_notify(&n->vdev, vq); |
... | ... | @@ -663,6 +696,8 @@ static void virtio_net_cleanup(VLANClientState *vc) |
663 | 696 | { |
664 | 697 | VirtIONet *n = vc->opaque; |
665 | 698 | |
699 | + qemu_purge_queued_packets(vc); | |
700 | + | |
666 | 701 | unregister_savevm("virtio-net", n); |
667 | 702 | |
668 | 703 | qemu_free(n->mac_table.macs); | ... | ... |