From 893379efd0e1b84ceb0c42a713293f3dbd27b1bd Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Tue, 27 Oct 2009 18:16:36 +0000 Subject: [PATCH] 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 Signed-off-by: Anthony Liguori --- net.c | 49 ++++++++++++++++++++++++++++++++++++++----------- net.h | 1 + 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/net.c b/net.c index 37662c6f57..9ea66e36fa 100644 --- 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 338d84ad67..4ffce9109b 100644 --- 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 {