]> git.proxmox.com Git - qemu.git/commitdiff
net: disable receiving if client returns zero
authorMark McLoughlin <markmc@redhat.com>
Tue, 27 Oct 2009 18:16:36 +0000 (18:16 +0000)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 9 Nov 2009 14:43:02 +0000 (08:43 -0600)
If a receiver returns zero, that means its queue is full and it will
notify us when room is available using qemu_flush_queued_packets().

Take note of that and disable that receiver until it flushes its queue.

This is a first step towards allowing can_receive() handlers to return
true even if no buffer space is available.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
net.c
net.h

diff --git a/net.c b/net.c
index 37662c6f57fcfea5b46f80a45781727df6bd0d66..9ea66e36fa8cf18ff8115005324f6c1cf324883d 100644 (file)
--- a/net.c
+++ b/net.c
@@ -438,11 +438,13 @@ int qemu_can_send_packet(VLANClientState *sender)
     VLANClientState *vc;
 
     if (sender->peer) {
-        if (!sender->peer->can_receive ||
-            sender->peer->can_receive(sender->peer)) {
-            return 1;
-        } else {
+        if (sender->peer->receive_disabled) {
             return 0;
+        } else if (sender->peer->can_receive &&
+                   !sender->peer->can_receive(sender->peer)) {
+            return 0;
+        } else {
+            return 1;
         }
     }
 
@@ -470,15 +472,27 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender,
                                    void *opaque)
 {
     VLANClientState *vc = opaque;
+    ssize_t ret;
 
     if (vc->link_down) {
         return size;
     }
 
-    if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw)
-        return vc->receive_raw(vc, data, size);
-    else
-        return vc->receive(vc, data, size);
+    if (vc->receive_disabled) {
+        return 0;
+    }
+
+    if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) {
+        ret = vc->receive_raw(vc, data, size);
+    } else {
+        ret = vc->receive(vc, data, size);
+    }
+
+    if (ret == 0) {
+        vc->receive_disabled = 1;
+    };
+
+    return ret;
 }
 
 static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
@@ -489,7 +503,7 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
 {
     VLANState *vlan = opaque;
     VLANClientState *vc;
-    int ret = -1;
+    ssize_t ret = -1;
 
     QTAILQ_FOREACH(vc, &vlan->clients, next) {
         ssize_t len;
@@ -503,12 +517,23 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
             continue;
         }
 
-        if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw)
+        if (vc->receive_disabled) {
+            ret = 0;
+            continue;
+        }
+
+        if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) {
             len = vc->receive_raw(vc, buf, size);
-        else
+        } else {
             len = vc->receive(vc, buf, size);
+        }
+
+        if (len == 0) {
+            vc->receive_disabled = 1;
+        }
 
         ret = (ret >= 0) ? ret : len;
+
     }
 
     return ret;
@@ -535,6 +560,8 @@ void qemu_flush_queued_packets(VLANClientState *vc)
 {
     NetQueue *queue;
 
+    vc->receive_disabled = 0;
+
     if (vc->vlan) {
         queue = vc->vlan->send_queue;
     } else {
diff --git a/net.h b/net.h
index 338d84ad673f87b1f6b7799022fddb9a0f5cbf2f..4ffce9109b26a0ec13162d324d912e04f44783ce 100644 (file)
--- a/net.h
+++ b/net.h
@@ -61,6 +61,7 @@ struct VLANClientState {
     char *model;
     char *name;
     char info_str[256];
+    unsigned receive_disabled : 1;
 };
 
 struct VLANState {