From e19eb22486f258a421108ac22b8380a4e2f16b97 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 29 Apr 2009 13:30:24 +0100 Subject: [PATCH] net: make use of async packet sending API in tap client If a packet is queued by qemu_send_packet(), remove I/O handler for the tap fd until we get notification that the packet has been sent. A not insignificant side effect of this is we can now drain the tap send queue in one go without fear of packets being dropped. Signed-off-by: Mark McLoughlin --- net.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index e7f5138343..4cf27be99c 100644 --- a/net.c +++ b/net.c @@ -1079,15 +1079,31 @@ static ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) } #endif +static void tap_send(void *opaque); + +static void tap_send_completed(VLANClientState *vc) +{ + TAPState *s = vc->opaque; + + qemu_set_fd_handler2(s->fd, tap_can_send, tap_send, NULL, s); +} + static void tap_send(void *opaque) { TAPState *s = opaque; int size; - size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); - if (size > 0) { - qemu_send_packet(s->vc, s->buf, size); - } + do { + size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); + if (size <= 0) { + break; + } + + size = qemu_send_packet_async(s->vc, s->buf, size, tap_send_completed); + if (size == 0) { + qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); + } + } while (size > 0); } static void tap_cleanup(VLANClientState *vc)