diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-09-04 17:39:07 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-09-04 17:39:07 +0100 |
commit | 8cf8c92e7775b9c5e811c55c9b8814168c46c34b (patch) | |
tree | 09b57396fc0a5fb7bab1341b11f62851fd678fd6 /net | |
parent | 01eb313907dda97313b8fea62e5632fca64f069c (diff) | |
parent | 086abc1ccd0fa5103345adda819e6c6436949579 (diff) | |
download | qemu-8cf8c92e7775b9c5e811c55c9b8814168c46c34b.tar.gz qemu-8cf8c92e7775b9c5e811c55c9b8814168c46c34b.tar.bz2 qemu-8cf8c92e7775b9c5e811c55c9b8814168c46c34b.zip |
Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging
Net patches
# gpg: Signature made Thu 04 Sep 2014 17:32:44 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
* remotes/stefanha/tags/net-pull-request:
virtio-net: purge outstanding packets when starting vhost
net: complete all queued packets on VM stop
net: invoke callback when purging queue
virtio: don't call device on !vm_running
virtio-net: don't run bh on vm stopped
net: Forbid dealing with packets when VM is not running
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/net.c | 40 | ||||
-rw-r--r-- | net/queue.c | 3 |
2 files changed, 42 insertions, 1 deletions
@@ -41,12 +41,14 @@ #include "qapi-visit.h" #include "qapi/opts-visitor.h" #include "qapi/dealloc-visitor.h" +#include "sysemu/sysemu.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) # define CONFIG_NET_BRIDGE #endif +static VMChangeStateEntry *net_change_state_entry; static QTAILQ_HEAD(, NetClientState) net_clients; const char *host_net_devices[] = { @@ -452,6 +454,12 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len) int qemu_can_send_packet(NetClientState *sender) { + int vm_running = runstate_is_running(); + + if (!vm_running) { + return 0; + } + if (!sender->peer) { return 1; } @@ -504,7 +512,8 @@ void qemu_purge_queued_packets(NetClientState *nc) qemu_net_queue_purge(nc->peer->incoming_queue, nc); } -void qemu_flush_queued_packets(NetClientState *nc) +static +void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge) { nc->receive_disabled = 0; @@ -518,9 +527,17 @@ void qemu_flush_queued_packets(NetClientState *nc) * the file descriptor (for tap, for example). */ qemu_notify_event(); + } else if (purge) { + /* Unable to empty the queue, purge remaining packets */ + qemu_net_queue_purge(nc->incoming_queue, nc); } } +void qemu_flush_queued_packets(NetClientState *nc) +{ + qemu_flush_or_purge_queued_packets(nc, false); +} + static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, unsigned flags, const uint8_t *buf, int size, @@ -1168,6 +1185,22 @@ void qmp_set_link(const char *name, bool up, Error **errp) } } +static void net_vm_change_state_handler(void *opaque, int running, + RunState state) +{ + /* Complete all queued packets, to guarantee we don't modify + * state later when VM is not running. + */ + if (!running) { + NetClientState *nc; + NetClientState *tmp; + + QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) { + qemu_flush_or_purge_queued_packets(nc, true); + } + } +} + void net_cleanup(void) { NetClientState *nc; @@ -1183,6 +1216,8 @@ void net_cleanup(void) qemu_del_net_client(nc); } } + + qemu_del_vm_change_state_handler(net_change_state_entry); } void net_check_clients(void) @@ -1268,6 +1303,9 @@ int net_init_clients(void) #endif } + net_change_state_entry = + qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL); + QTAILQ_INIT(&net_clients); if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1) diff --git a/net/queue.c b/net/queue.c index 859d02a136..f948318718 100644 --- a/net/queue.c +++ b/net/queue.c @@ -233,6 +233,9 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) if (packet->sender == from) { QTAILQ_REMOVE(&queue->packets, packet, entry); queue->nq_count--; + if (packet->sent_cb) { + packet->sent_cb(packet->sender, 0); + } g_free(packet); } } |