Commit 8cf8c92e authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 01eb3139 086abc1c
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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) {
+8 −1
Original line number Diff line number Diff line
@@ -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);

    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,
+39 −1
Original line number Diff line number Diff line
@@ -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)
+3 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }