net: fix qemu_flush_queued_packets() in presence of a hub
When frontend and backend are connected through a hub as below (showing only one direction), and the frontend (or in general, all output ports of the hub) cannot accept more traffic, the backend queues packets in queue-A. When the frontend (or in general, one output port) becomes ready again, quemu tries to flush packets from queue-B, which is unfortunately empty. e1000.0 <--[queue B]-- hub0port0(hub)hub0port1 <--[queue A]-- tap.0 To fix this i propose to introduce a new function net_hub_flush() which is called when trying to flush a queue connected to a hub. Signed-off-by: Luigi Rizzo <rizzo@iet.unipi.it> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
ee24aaf356
commit
199ee608f0
14
net/hub.c
14
net/hub.c
@ -338,3 +338,17 @@ void net_hub_check_clients(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool net_hub_flush(NetClientState *nc)
|
||||||
|
{
|
||||||
|
NetHubPort *port;
|
||||||
|
NetHubPort *source_port = DO_UPCAST(NetHubPort, nc, nc);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
QLIST_FOREACH(port, &source_port->hub->ports, next) {
|
||||||
|
if (port != source_port) {
|
||||||
|
ret += qemu_net_queue_flush(port->nc.send_queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret ? true : false;
|
||||||
|
}
|
||||||
|
@ -21,5 +21,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name);
|
|||||||
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
|
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
|
||||||
void net_hub_info(Monitor *mon);
|
void net_hub_info(Monitor *mon);
|
||||||
void net_hub_check_clients(void);
|
void net_hub_check_clients(void);
|
||||||
|
bool net_hub_flush(NetClientState *nc);
|
||||||
|
|
||||||
#endif /* NET_HUB_H */
|
#endif /* NET_HUB_H */
|
||||||
|
@ -441,6 +441,12 @@ void qemu_flush_queued_packets(NetClientState *nc)
|
|||||||
{
|
{
|
||||||
nc->receive_disabled = 0;
|
nc->receive_disabled = 0;
|
||||||
|
|
||||||
|
if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
|
||||||
|
if (net_hub_flush(nc->peer)) {
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (qemu_net_queue_flush(nc->send_queue)) {
|
if (qemu_net_queue_flush(nc->send_queue)) {
|
||||||
/* We emptied the queue successfully, signal to the IO thread to repoll
|
/* We emptied the queue successfully, signal to the IO thread to repoll
|
||||||
* the file descriptor (for tap, for example).
|
* the file descriptor (for tap, for example).
|
||||||
|
Loading…
Reference in New Issue
Block a user