diff options
Diffstat (limited to 'hw/net/vhost_net.c')
-rw-r--r-- | hw/net/vhost_net.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 386ec2eaa2..0d888f29a6 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -231,9 +231,11 @@ fail: return NULL; } -static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index) +static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index, + int last_index) { net->dev.vq_index = vq_index; + net->dev.last_index = last_index; } static int vhost_net_start_one(struct vhost_net *net, @@ -315,25 +317,37 @@ static void vhost_net_stop_one(struct vhost_net *net, } int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, - int total_queues) + int data_queue_pairs, int cvq) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); + int total_notifiers = data_queue_pairs * 2 + cvq; + VirtIONet *n = VIRTIO_NET(dev); + int nvhosts = data_queue_pairs + cvq; struct vhost_net *net; - int r, e, i; + int r, e, i, last_index = data_queue_pairs * 2; NetClientState *peer; + if (!cvq) { + last_index -= 1; + } + if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; } - for (i = 0; i < total_queues; i++) { + for (i = 0; i < nvhosts; i++) { + + if (i < data_queue_pairs) { + peer = qemu_get_peer(ncs, i); + } else { /* Control Virtqueue */ + peer = qemu_get_peer(ncs, n->max_queue_pairs); + } - peer = qemu_get_peer(ncs, i); net = get_vhost_net(peer); - vhost_net_set_vq_index(net, i * 2); + vhost_net_set_vq_index(net, i * 2, last_index); /* Suppress the masking guest notifiers on vhost user * because vhost user doesn't interrupt masking/unmasking @@ -344,14 +358,18 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, } } - r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); + r = k->set_guest_notifiers(qbus->parent, total_notifiers, true); if (r < 0) { error_report("Error binding guest notifier: %d", -r); goto err; } - for (i = 0; i < total_queues; i++) { - peer = qemu_get_peer(ncs, i); + for (i = 0; i < nvhosts; i++) { + if (i < data_queue_pairs) { + peer = qemu_get_peer(ncs, i); + } else { + peer = qemu_get_peer(ncs, n->max_queue_pairs); + } r = vhost_net_start_one(get_vhost_net(peer), dev); if (r < 0) { @@ -375,7 +393,7 @@ err_start: peer = qemu_get_peer(ncs , i); vhost_net_stop_one(get_vhost_net(peer), dev); } - e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); + e = k->set_guest_notifiers(qbus->parent, total_notifiers, false); if (e < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); fflush(stderr); @@ -385,18 +403,27 @@ err: } void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, - int total_queues) + int data_queue_pairs, int cvq) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); + VirtIONet *n = VIRTIO_NET(dev); + NetClientState *peer; + int total_notifiers = data_queue_pairs * 2 + cvq; + int nvhosts = data_queue_pairs + cvq; int i, r; - for (i = 0; i < total_queues; i++) { - vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); + for (i = 0; i < nvhosts; i++) { + if (i < data_queue_pairs) { + peer = qemu_get_peer(ncs, i); + } else { + peer = qemu_get_peer(ncs, n->max_queue_pairs); + } + vhost_net_stop_one(get_vhost_net(peer), dev); } - r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); + r = k->set_guest_notifiers(qbus->parent, total_notifiers, false); if (r < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); fflush(stderr); |