[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/5] net: disable receiving if client returns zero
From: |
Mark McLoughlin |
Subject: |
[Qemu-devel] [PATCH 2/5] net: disable receiving if client returns zero |
Date: |
Tue, 27 Oct 2009 18:16:36 +0000 |
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 <address@hidden>
---
net.c | 49 ++++++++++++++++++++++++++++++++++++++-----------
net.h | 1 +
2 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/net.c b/net.c
index 661bbc1..9dea615 100644
--- a/net.c
+++ b/net.c
@@ -423,11 +423,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;
}
}
@@ -455,15 +457,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,
@@ -474,7 +488,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;
@@ -488,12 +502,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;
@@ -520,6 +545,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 8074c66..c1fe515 100644
--- a/net.h
+++ b/net.h
@@ -44,6 +44,7 @@ struct VLANClientState {
char *model;
char *name;
char info_str[256];
+ unsigned receive_disabled : 1;
};
struct VLANState {
--
1.6.2.5