peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame qemu-fix-dropped-packets-with-non-virtio-nics.patch

Mark McLoughlin b65c30
From 2e7c7b6cb25603e2fa40990da86d03a57b2616bd Mon Sep 17 00:00:00 2001
Mark McLoughlin b29fd2
From: Mark McLoughlin <markmc@redhat.com>
Mark McLoughlin b29fd2
Date: Thu, 29 Oct 2009 11:34:17 +0000
Mark McLoughlin b29fd2
Subject: [PATCH] net: disable draining tap queue in one go
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
If qemu_send_packet_async() returns zero, it means the packet has been
Mark McLoughlin b29fd2
queued and the sent callback will be invoked once it has been flushed.
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
This is only possible where the NIC's receive() handler returns zero
Mark McLoughlin b29fd2
and promises to notify the networking core that room is available in its
Mark McLoughlin b29fd2
queue again.
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
In the case where the receive handler does not have this capability
Mark McLoughlin b29fd2
(and its queue fills up) it returns -1 and the networking core does not
Mark McLoughlin b29fd2
queue up the packet. This condition is indicated by a -1 return from
Mark McLoughlin b29fd2
qemu_send_packet_async().
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
Currently, tap handles this condition simply by dropping the packet. It
Mark McLoughlin b29fd2
should do its best to avoid getting into this situation by checking such
Mark McLoughlin b29fd2
NIC's have room for a packet before copying the packet from the tap
Mark McLoughlin b29fd2
interface.
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
tap_send() used to achieve this by only reading a single packet before
Mark McLoughlin b29fd2
returning to the mainloop. That way, tap_can_send() is called before
Mark McLoughlin b29fd2
reading each packet.
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
tap_send() was changed to completely drain the tap interface queue
Mark McLoughlin b29fd2
without taking into account the situation where the NIC returns an
Mark McLoughlin b29fd2
error and the packet is not queued. Let's start fixing this by
Mark McLoughlin b29fd2
reverting to the previous behaviour of reading one packet at a time.
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
Reported-by: Scott Tsai <scottt.tw@gmail.com>
Mark McLoughlin b29fd2
Tested-by: Sven Rudolph <Sven_Rudolph@drewag.de>
Mark McLoughlin b29fd2
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
Fedora-patch: qemu-fix-dropped-packets-with-non-virtio-nics.patch
Mark McLoughlin b29fd2
---
Mark McLoughlin b29fd2
 net.c |   29 +++++++++++++----------------
Mark McLoughlin b29fd2
 1 files changed, 13 insertions(+), 16 deletions(-)
Mark McLoughlin b29fd2
Mark McLoughlin b29fd2
diff --git a/net.c b/net.c
Mark McLoughlin b65c30
index 3572c48..522e33c 100644
Mark McLoughlin b29fd2
--- a/net.c
Mark McLoughlin b29fd2
+++ b/net.c
Mark McLoughlin b29fd2
@@ -1453,27 +1453,24 @@ static void tap_send(void *opaque)
Mark McLoughlin b29fd2
 {
Mark McLoughlin b29fd2
     TAPState *s = opaque;
Mark McLoughlin b29fd2
     int size;
Mark McLoughlin b29fd2
+    uint8_t *buf = s->buf;
Mark McLoughlin b29fd2
 
Mark McLoughlin b29fd2
-    do {
Mark McLoughlin b29fd2
-        uint8_t *buf = s->buf;
Mark McLoughlin b29fd2
-
Mark McLoughlin b29fd2
-        size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
Mark McLoughlin b29fd2
-        if (size <= 0) {
Mark McLoughlin b29fd2
-            break;
Mark McLoughlin b29fd2
-        }
Mark McLoughlin b29fd2
+    size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
Mark McLoughlin b29fd2
+    if (size <= 0) {
Mark McLoughlin b65c30
+        return;
Mark McLoughlin b29fd2
+    }
Mark McLoughlin b29fd2
 
Mark McLoughlin b29fd2
 #ifdef IFF_VNET_HDR
Mark McLoughlin b29fd2
-        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
Mark McLoughlin b29fd2
-            buf += sizeof(struct virtio_net_hdr);
Mark McLoughlin b29fd2
-            size -= sizeof(struct virtio_net_hdr);
Mark McLoughlin b29fd2
-        }
Mark McLoughlin b29fd2
+    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
Mark McLoughlin b29fd2
+        buf += sizeof(struct virtio_net_hdr);
Mark McLoughlin b29fd2
+        size -= sizeof(struct virtio_net_hdr);
Mark McLoughlin b29fd2
+    }
Mark McLoughlin b29fd2
 #endif
Mark McLoughlin b29fd2
 
Mark McLoughlin b29fd2
-        size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
Mark McLoughlin b29fd2
-        if (size == 0) {
Mark McLoughlin b29fd2
-            tap_read_poll(s, 0);
Mark McLoughlin b29fd2
-        }
Mark McLoughlin b29fd2
-    } while (size > 0);
Mark McLoughlin b29fd2
+    size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
Mark McLoughlin b29fd2
+    if (size == 0) {
Mark McLoughlin b29fd2
+        tap_read_poll(s, 0);
Mark McLoughlin b29fd2
+    }
Mark McLoughlin b29fd2
 }
Mark McLoughlin b29fd2
 
Mark McLoughlin b29fd2
 #ifdef TUNSETSNDBUF
Mark McLoughlin b29fd2
-- 
Mark McLoughlin b29fd2
1.6.2.5
Mark McLoughlin b29fd2