Commit e19eb22486f258a421108ac22b8380a4e2f16b97

Authored by Mark McLoughlin
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
... ... @@ -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)
... ...