This moves the semantics from net_hub_port_can_receive to receive functions, by returning 0 if all receiving ports return 0. Also, remember to flush the source port's queue in that case.
Signed-off-by: Fam Zheng <f...@redhat.com> --- net/hub.c | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/net/hub.c b/net/hub.c index 3047f12..5697fad 100644 --- a/net/hub.c +++ b/net/hub.c @@ -31,6 +31,7 @@ typedef struct NetHubPort { QLIST_ENTRY(NetHubPort) next; NetHub *hub; int id; + bool needs_flush; } NetHubPort; struct NetHub { @@ -42,35 +43,58 @@ struct NetHub { static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs); +static void net_hub_port_send_cb(NetClientState *nc, ssize_t ret) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + NetHub *hub = port->hub; + + QLIST_FOREACH(port, &hub->ports, next) { + if (port->needs_flush) { + port->needs_flush = false; + qemu_flush_queued_packets(&port->nc); + } + } +} + static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port, const uint8_t *buf, size_t len) { NetHubPort *port; + ssize_t ret = -1; QLIST_FOREACH(port, &hub->ports, next) { + ssize_t r; if (port == source_port) { continue; } - qemu_send_packet(&port->nc, buf, len); + r = qemu_send_packet_async(&port->nc, buf, len, + net_hub_port_send_cb); + ret = MAX(r, ret); } - return len; + source_port->needs_flush = ret == 0; + + return ret; } static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port, const struct iovec *iov, int iovcnt) { NetHubPort *port; - ssize_t len = iov_size(iov, iovcnt); + ssize_t ret = -1; QLIST_FOREACH(port, &hub->ports, next) { + ssize_t r; if (port == source_port) { continue; } - qemu_sendv_packet(&port->nc, iov, iovcnt); + r = qemu_sendv_packet_async(&port->nc, iov, + iovcnt, net_hub_port_send_cb); + ret = MAX(r, ret); } - return len; + source_port->needs_flush = ret == 0; + return ret; } static NetHub *net_hub_new(int id) @@ -87,25 +111,6 @@ static NetHub *net_hub_new(int id) return hub; } -static int net_hub_port_can_receive(NetClientState *nc) -{ - NetHubPort *port; - NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc); - NetHub *hub = src_port->hub; - - QLIST_FOREACH(port, &hub->ports, next) { - if (port == src_port) { - continue; - } - - if (qemu_can_send_packet(&port->nc)) { - return 1; - } - } - - return 0; -} - static ssize_t net_hub_port_receive(NetClientState *nc, const uint8_t *buf, size_t len) { @@ -132,7 +137,6 @@ static void net_hub_port_cleanup(NetClientState *nc) static NetClientInfo net_hub_port_info = { .type = NET_CLIENT_OPTIONS_KIND_HUBPORT, .size = sizeof(NetHubPort), - .can_receive = net_hub_port_can_receive, .receive = net_hub_port_receive, .receive_iov = net_hub_port_receive_iov, .cleanup = net_hub_port_cleanup, -- 2.4.3