Net patches

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJUCJQsAAoJEJykq7OBq3PIFs4H/jHdJ65oXUeS8REtDwsRaU/q
 Ftny6suH0j8XYh/zFSppNFHprX/i2AB7oJpHS8MzVjglxQ06OT/BQWSb2NA99URD
 PARU0/Ijn2ZgReCiMS3qBGotYLJV/pJsZRtmi6xc/v9Zz/LlziBo1J/ZsZeMkhiP
 RL/Q5ySixyWGx32989YcTmn98aCc4nvG70pE3dz3I3PPYQtUn38uqTltYPORaOgy
 txhIOxeyvwgL+jwYvoJq5UgDpOw/QNtLRzN0+YydRUs5ad7roSlRX4PvlBgXxfWc
 NPxt/wM+OPEyN029KLV8IjVNvxxM/QRNFqksabnmJIS/SgBaiSRPHZuHR5po8C4=
 =cCXt
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2014-09-04 17:39:07 +01:00
commit 8cf8c92e77
4 changed files with 64 additions and 3 deletions

View file

@ -125,10 +125,23 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
return;
}
if (!n->vhost_started) {
int r;
int r, i;
if (!vhost_net_query(get_vhost_net(nc->peer), vdev)) {
return;
}
/* Any packets outstanding? Purge them to avoid touching rings
* when vhost is running.
*/
for (i = 0; i < queues; i++) {
NetClientState *qnc = qemu_get_subqueue(n->nic, i);
/* Purge both directions: TX and RX. */
qemu_net_queue_purge(qnc->peer->incoming_queue, qnc);
qemu_net_queue_purge(qnc->incoming_queue, qnc->peer);
}
n->vhost_started = 1;
r = vhost_net_start(vdev, n->nic->ncs, queues);
if (r < 0) {

View file

@ -1108,7 +1108,10 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
vdev->vm_running = running;
if (running) {
vdev->vm_running = running;
}
if (backend_run) {
virtio_set_status(vdev, vdev->status);
@ -1121,6 +1124,10 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
if (!backend_run) {
virtio_set_status(vdev, vdev->status);
}
if (!running) {
vdev->vm_running = running;
}
}
void virtio_init(VirtIODevice *vdev, const char *name,

View file

@ -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)

View file

@ -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);
}
}