diff options
author | Mark McLoughlin <markmc@redhat.com> | 2009-10-27 18:16:36 +0000 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-11-09 08:43:02 -0600 |
commit | 893379efd0e1b84ceb0c42a713293f3dbd27b1bd (patch) | |
tree | bc0bce61704492223a353a80e63101e868fc05c0 | |
parent | be1636b3ab36b3decdd0eb35b3b09a998060104f (diff) |
net: disable receiving if client returns zero
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>
-rw-r--r-- | net.c | 49 | ||||
-rw-r--r-- | net.h | 1 |
2 files changed, 39 insertions, 11 deletions
@@ -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 { @@ -61,6 +61,7 @@ struct VLANClientState { char *model; char *name; char info_str[256]; + unsigned receive_disabled : 1; }; struct VLANState { |