qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery
Date: Fri, 08 May 2009 12:34:17 +0200
User-agent: StGIT/0.14.2

Fix a race in qemu_send_packet when delivering deferred packets and
add proper deferring also to qemu_sendv_packet.

Signed-off-by: Jan Kiszka <address@hidden>
---

 net.c |   57 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/net.c b/net.c
index b93b3a6..671138f 100644
--- a/net.c
+++ b/net.c
@@ -438,8 +438,8 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t 
*buf, int size)
         vlan->delivering = 1;
         qemu_deliver_packet(vc, buf, size);
         while ((packet = vlan->send_queue) != NULL) {
-            qemu_deliver_packet(packet->sender, packet->data, packet->size);
             vlan->send_queue = packet->next;
+            qemu_deliver_packet(packet->sender, packet->data, packet->size);
             qemu_free(packet);
         }
         vlan->delivering = 0;
@@ -476,30 +476,57 @@ static ssize_t calc_iov_length(const struct iovec *iov, 
int iovcnt)
     return offset;
 }
 
-ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov,
+ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov,
                           int iovcnt)
 {
-    VLANState *vlan = vc1->vlan;
+    VLANState *vlan = sender->vlan;
     VLANClientState *vc;
+    VLANPacket *packet;
     ssize_t max_len = 0;
+    int i;
 
-    if (vc1->link_down)
+    if (sender->link_down)
         return calc_iov_length(iov, iovcnt);
 
-    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
-        ssize_t len = 0;
+    if (vlan->delivering) {
+        max_len = calc_iov_length(iov, iovcnt);
 
-        if (vc == vc1)
-            continue;
+        packet = qemu_malloc(sizeof(VLANPacket) + max_len);
+        packet->next = vlan->send_queue;
+        packet->sender = sender;
+        packet->size = 0;
+        for (i = 0; i < iovcnt; i++) {
+            size_t len = iov[i].iov_len;
+
+            memcpy(packet->data + packet->size, iov[i].iov_base, len);
+            packet->size += len;
+        }
+        vlan->send_queue = packet;
+    } else {
+        vlan->delivering = 1;
+
+        for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            ssize_t len = 0;
 
-        if (vc->link_down)
-            len = calc_iov_length(iov, iovcnt);
-        else if (vc->fd_readv)
-            len = vc->fd_readv(vc->opaque, iov, iovcnt);
-        else if (vc->fd_read)
-            len = vc_sendv_compat(vc, iov, iovcnt);
+            if (vc == sender) {
+                continue;
+            }
+            if (vc->link_down) {
+                len = calc_iov_length(iov, iovcnt);
+            } else if (vc->fd_readv) {
+                len = vc->fd_readv(vc->opaque, iov, iovcnt);
+            } else if (vc->fd_read) {
+                len = vc_sendv_compat(vc, iov, iovcnt);
+            }
+            max_len = MAX(max_len, len);
+        }
 
-        max_len = MAX(max_len, len);
+        while ((packet = vlan->send_queue) != NULL) {
+            vlan->send_queue = packet->next;
+            qemu_deliver_packet(packet->sender, packet->data, packet->size);
+            qemu_free(packet);
+        }
+        vlan->delivering = 0;
     }
 
     return max_len;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]