Commit e19eb22486f258a421108ac22b8380a4e2f16b97
1 parent
f3b6c7fc
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 <markmc@redhat.com>
Showing
1 changed file
with
20 additions
and
4 deletions
net.c
... | ... | @@ -1079,15 +1079,31 @@ static ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) |
1079 | 1079 | } |
1080 | 1080 | #endif |
1081 | 1081 | |
1082 | +static void tap_send(void *opaque); | |
1083 | + | |
1084 | +static void tap_send_completed(VLANClientState *vc) | |
1085 | +{ | |
1086 | + TAPState *s = vc->opaque; | |
1087 | + | |
1088 | + qemu_set_fd_handler2(s->fd, tap_can_send, tap_send, NULL, s); | |
1089 | +} | |
1090 | + | |
1082 | 1091 | static void tap_send(void *opaque) |
1083 | 1092 | { |
1084 | 1093 | TAPState *s = opaque; |
1085 | 1094 | int size; |
1086 | 1095 | |
1087 | - size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); | |
1088 | - if (size > 0) { | |
1089 | - qemu_send_packet(s->vc, s->buf, size); | |
1090 | - } | |
1096 | + do { | |
1097 | + size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); | |
1098 | + if (size <= 0) { | |
1099 | + break; | |
1100 | + } | |
1101 | + | |
1102 | + size = qemu_send_packet_async(s->vc, s->buf, size, tap_send_completed); | |
1103 | + if (size == 0) { | |
1104 | + qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); | |
1105 | + } | |
1106 | + } while (size > 0); | |
1091 | 1107 | } |
1092 | 1108 | |
1093 | 1109 | static void tap_cleanup(VLANClientState *vc) | ... | ... |