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); |