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