Lines Matching +full:0 +full:- +full:dev
2 * vhost-net support
10 * the COPYING file in the top-level directory.
12 * Contributions after 2012-01-13 are licensed under the terms of the
19 #include "net/vhost-user.h"
20 #include "net/vhost-vdpa.h"
22 #include "standard-headers/linux/vhost_types.h"
23 #include "hw/virtio/virtio-net.h"
26 #include "qemu/error-report.h"
27 #include "qemu/main-loop.h"
34 #include "standard-headers/linux/virtio_ring.h"
36 #include "hw/virtio/virtio-bus.h"
37 #include "linux-headers/linux/vhost.h"
101 const int *feature_bits = 0; in vhost_net_get_feature_bits()
103 switch (net->nc->info->type) { in vhost_net_get_feature_bits()
117 net->nc->info->type); in vhost_net_get_feature_bits()
126 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), in vhost_net_get_features()
132 return vhost_dev_get_config(&net->dev, config, config_len, NULL); in vhost_net_get_config()
137 return vhost_dev_set_config(&net->dev, data, offset, size, flags); in vhost_net_set_config()
142 net->dev.acked_features = net->dev.backend_features; in vhost_net_ack_features()
143 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features); in vhost_net_ack_features()
148 return net->dev.max_queues; in vhost_net_get_max_queues()
153 return net->dev.acked_features; in vhost_net_get_acked_features()
159 if (nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) { in vhost_net_save_acked_features()
165 static void vhost_net_disable_notifiers_nvhosts(VirtIODevice *dev, in vhost_net_disable_notifiers_nvhosts() argument
168 VirtIONet *n = VIRTIO_NET(dev); in vhost_net_disable_notifiers_nvhosts()
169 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); in vhost_net_disable_notifiers_nvhosts()
181 for (i = 0; i < nvhosts; i++) { in vhost_net_disable_notifiers_nvhosts()
185 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_disable_notifiers_nvhosts()
189 hdev = &net->dev; in vhost_net_disable_notifiers_nvhosts()
190 for (j = 0; j < hdev->nvqs; j++) { in vhost_net_disable_notifiers_nvhosts()
192 hdev->vq_index + j, in vhost_net_disable_notifiers_nvhosts()
194 if (r < 0) { in vhost_net_disable_notifiers_nvhosts()
196 i, j, -r); in vhost_net_disable_notifiers_nvhosts()
198 assert(r >= 0); in vhost_net_disable_notifiers_nvhosts()
207 for (i = 0; i < nvhosts; i++) { in vhost_net_disable_notifiers_nvhosts()
211 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_disable_notifiers_nvhosts()
215 hdev = &net->dev; in vhost_net_disable_notifiers_nvhosts()
216 for (j = 0; j < hdev->nvqs; j++) { in vhost_net_disable_notifiers_nvhosts()
218 hdev->vq_index + j); in vhost_net_disable_notifiers_nvhosts()
220 virtio_device_release_ioeventfd(dev); in vhost_net_disable_notifiers_nvhosts()
224 static int vhost_net_enable_notifiers(VirtIODevice *dev, in vhost_net_enable_notifiers() argument
227 VirtIONet *n = VIRTIO_NET(dev); in vhost_net_enable_notifiers()
228 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); in vhost_net_enable_notifiers()
239 for (i = 0; i < nvhosts; i++) { in vhost_net_enable_notifiers()
240 r = virtio_device_grab_ioeventfd(dev); in vhost_net_enable_notifiers()
241 if (r < 0) { in vhost_net_enable_notifiers()
243 for (k = 0; k < i; k++) { in vhost_net_enable_notifiers()
244 virtio_device_release_ioeventfd(dev); in vhost_net_enable_notifiers()
256 for (i = 0; i < nvhosts; i++) { in vhost_net_enable_notifiers()
260 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_enable_notifiers()
264 hdev = &net->dev; in vhost_net_enable_notifiers()
266 for (j = 0; j < hdev->nvqs; j++) { in vhost_net_enable_notifiers()
268 hdev->vq_index + j, in vhost_net_enable_notifiers()
270 if (r < 0) { in vhost_net_enable_notifiers()
272 i, j, -r); in vhost_net_enable_notifiers()
274 vhost_dev_disable_notifiers_nvqs(hdev, dev, j); in vhost_net_enable_notifiers()
282 return 0; in vhost_net_enable_notifiers()
284 vhost_net_disable_notifiers_nvhosts(dev, ncs, data_queue_pairs, i); in vhost_net_enable_notifiers()
286 * This for loop starts from i+1, not i, because the i-th ioeventfd in vhost_net_enable_notifiers()
290 virtio_device_release_ioeventfd(dev); in vhost_net_enable_notifiers()
300 static void vhost_net_disable_notifiers(VirtIODevice *dev, in vhost_net_disable_notifiers() argument
303 vhost_net_disable_notifiers_nvhosts(dev, ncs, data_queue_pairs, in vhost_net_disable_notifiers()
309 switch (backend->info->type) { in vhost_net_get_fd()
313 fprintf(stderr, "vhost-net requires tap backend\n"); in vhost_net_get_fd()
314 return -ENOSYS; in vhost_net_get_fd()
321 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL; in vhost_net_init()
323 uint64_t features = 0; in vhost_net_init()
326 if (!options->net_backend) { in vhost_net_init()
327 fprintf(stderr, "vhost-net requires net backend to be setup\n"); in vhost_net_init()
330 net->nc = options->net_backend; in vhost_net_init()
331 net->dev.nvqs = options->nvqs; in vhost_net_init()
333 net->dev.max_queues = 1; in vhost_net_init()
334 net->dev.vqs = net->vqs; in vhost_net_init()
337 r = vhost_net_get_fd(options->net_backend); in vhost_net_init()
338 if (r < 0) { in vhost_net_init()
341 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend) in vhost_net_init()
342 ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR); in vhost_net_init()
343 net->backend = r; in vhost_net_init()
344 net->dev.protocol_features = 0; in vhost_net_init()
346 net->dev.backend_features = 0; in vhost_net_init()
347 net->dev.protocol_features = 0; in vhost_net_init()
348 net->backend = -1; in vhost_net_init()
350 /* vhost-user needs vq_index to initiate a specific queue pair */ in vhost_net_init()
351 net->dev.vq_index = net->nc->queue_index * net->dev.nvqs; in vhost_net_init()
354 r = vhost_dev_init(&net->dev, options->opaque, in vhost_net_init()
355 options->backend_type, options->busyloop_timeout, in vhost_net_init()
357 if (r < 0) { in vhost_net_init()
362 if (!qemu_has_vnet_hdr_len(options->net_backend, in vhost_net_init()
364 net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF); in vhost_net_init()
366 if (~net->dev.features & net->dev.backend_features) { in vhost_net_init()
367 fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64 in vhost_net_init()
369 (uint64_t)(~net->dev.features & net->dev.backend_features)); in vhost_net_init()
376 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) { in vhost_net_init()
377 features = vhost_user_get_acked_features(net->nc); in vhost_net_init()
378 if (~net->dev.features & features) { in vhost_net_init()
379 fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64 in vhost_net_init()
381 (uint64_t)(~net->dev.features & features)); in vhost_net_init()
392 vhost_dev_cleanup(&net->dev); in vhost_net_init()
400 net->dev.vq_index = vq_index; in vhost_net_set_vq_index()
401 net->dev.vq_index_end = vq_index_end; in vhost_net_set_vq_index()
405 VirtIODevice *dev) in vhost_net_start_one() argument
410 if (net->nc->info->start) { in vhost_net_start_one()
411 r = net->nc->info->start(net->nc); in vhost_net_start_one()
412 if (r < 0) { in vhost_net_start_one()
417 r = vhost_dev_start(&net->dev, dev, false); in vhost_net_start_one()
418 if (r < 0) { in vhost_net_start_one()
422 if (net->nc->info->poll) { in vhost_net_start_one()
423 net->nc->info->poll(net->nc, false); in vhost_net_start_one()
426 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_start_one()
427 qemu_set_fd_handler(net->backend, NULL, NULL, NULL); in vhost_net_start_one()
428 file.fd = net->backend; in vhost_net_start_one()
429 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { in vhost_net_start_one()
430 if (!virtio_queue_enabled(dev, net->dev.vq_index + in vhost_net_start_one()
435 r = vhost_net_set_backend(&net->dev, &file); in vhost_net_start_one()
436 if (r < 0) { in vhost_net_start_one()
437 r = -errno; in vhost_net_start_one()
443 if (net->nc->info->load) { in vhost_net_start_one()
444 r = net->nc->info->load(net->nc); in vhost_net_start_one()
445 if (r < 0) { in vhost_net_start_one()
449 return 0; in vhost_net_start_one()
451 file.fd = -1; in vhost_net_start_one()
452 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_start_one()
453 while (file.index-- > 0) { in vhost_net_start_one()
454 if (!virtio_queue_enabled(dev, net->dev.vq_index + in vhost_net_start_one()
459 int ret = vhost_net_set_backend(&net->dev, &file); in vhost_net_start_one()
460 assert(ret >= 0); in vhost_net_start_one()
463 if (net->nc->info->poll) { in vhost_net_start_one()
464 net->nc->info->poll(net->nc, true); in vhost_net_start_one()
466 vhost_dev_stop(&net->dev, dev, false); in vhost_net_start_one()
472 VirtIODevice *dev) in vhost_net_stop_one() argument
474 struct vhost_vring_file file = { .fd = -1 }; in vhost_net_stop_one()
476 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_stop_one()
477 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { in vhost_net_stop_one()
478 int r = vhost_net_set_backend(&net->dev, &file); in vhost_net_stop_one()
479 assert(r >= 0); in vhost_net_stop_one()
482 if (net->nc->info->poll) { in vhost_net_stop_one()
483 net->nc->info->poll(net->nc, true); in vhost_net_stop_one()
485 vhost_dev_stop(&net->dev, dev, false); in vhost_net_stop_one()
486 if (net->nc->info->stop) { in vhost_net_stop_one()
487 net->nc->info->stop(net->nc); in vhost_net_stop_one()
491 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, in vhost_net_start() argument
494 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); in vhost_net_start()
498 VirtIONet *n = VIRTIO_NET(dev); in vhost_net_start()
508 if (!k->set_guest_notifiers) { in vhost_net_start()
510 return -ENOSYS; in vhost_net_start()
513 for (i = 0; i < nvhosts; i++) { in vhost_net_start()
518 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_start()
528 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) { in vhost_net_start()
529 dev->use_guest_notifier_mask = false; in vhost_net_start()
533 r = vhost_net_enable_notifiers(dev, ncs, data_queue_pairs, cvq); in vhost_net_start()
534 if (r < 0) { in vhost_net_start()
535 error_report("Error enabling host notifiers: %d", -r); in vhost_net_start()
539 r = k->set_guest_notifiers(qbus->parent, total_notifiers, true); in vhost_net_start()
540 if (r < 0) { in vhost_net_start()
541 error_report("Error binding guest notifier: %d", -r); in vhost_net_start()
545 for (i = 0; i < nvhosts; i++) { in vhost_net_start()
549 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_start()
552 if (peer->vring_enable) { in vhost_net_start()
554 r = vhost_set_vring_enable(peer, peer->vring_enable); in vhost_net_start()
556 if (r < 0) { in vhost_net_start()
561 r = vhost_net_start_one(get_vhost_net(peer), dev); in vhost_net_start()
562 if (r < 0) { in vhost_net_start()
567 return 0; in vhost_net_start()
570 while (--i >= 0) { in vhost_net_start()
572 i : n->max_queue_pairs); in vhost_net_start()
573 vhost_net_stop_one(get_vhost_net(peer), dev); in vhost_net_start()
575 e = k->set_guest_notifiers(qbus->parent, total_notifiers, false); in vhost_net_start()
576 if (e < 0) { in vhost_net_start()
581 vhost_net_disable_notifiers(dev, ncs, data_queue_pairs, cvq); in vhost_net_start()
586 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, in vhost_net_stop() argument
589 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); in vhost_net_stop()
592 VirtIONet *n = VIRTIO_NET(dev); in vhost_net_stop()
598 for (i = 0; i < nvhosts; i++) { in vhost_net_stop()
602 peer = qemu_get_peer(ncs, n->max_queue_pairs); in vhost_net_stop()
604 vhost_net_stop_one(get_vhost_net(peer), dev); in vhost_net_stop()
607 r = k->set_guest_notifiers(qbus->parent, total_notifiers, false); in vhost_net_stop()
608 if (r < 0) { in vhost_net_stop()
612 assert(r >= 0); in vhost_net_stop()
614 vhost_net_disable_notifiers(dev, ncs, data_queue_pairs, cvq); in vhost_net_stop()
619 vhost_dev_cleanup(&net->dev); in vhost_net_cleanup()
624 const VhostOps *vhost_ops = net->dev.vhost_ops; in vhost_net_notify_migration_done()
626 assert(vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); in vhost_net_notify_migration_done()
627 assert(vhost_ops->vhost_migration_done); in vhost_net_notify_migration_done()
629 return vhost_ops->vhost_migration_done(&net->dev, mac_addr); in vhost_net_notify_migration_done()
634 return vhost_virtqueue_pending(&net->dev, idx); in vhost_net_virtqueue_pending()
637 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, in vhost_net_virtqueue_mask() argument
640 vhost_virtqueue_mask(&net->dev, dev, idx, mask); in vhost_net_virtqueue_mask()
645 return vhost_config_pending(&net->dev); in vhost_net_config_pending()
648 void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) in vhost_net_config_mask() argument
650 vhost_config_mask(&net->dev, dev, mask); in vhost_net_config_mask()
654 VHostNetState *vhost_net = 0; in get_vhost_net()
657 return 0; in get_vhost_net()
660 switch (nc->info->type) { in get_vhost_net()
664 * tap_get_vhost_net() can return NULL if a tap net-device backend is in get_vhost_net()
692 const VhostOps *vhost_ops = net->dev.vhost_ops; in vhost_set_vring_enable()
695 * vhost-vdpa network devices need to enable dataplane virtqueues after in vhost_set_vring_enable()
698 * net/vhost-vdpa.c. in vhost_set_vring_enable()
700 if (nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { in vhost_set_vring_enable()
701 return 0; in vhost_set_vring_enable()
704 nc->vring_enable = enable; in vhost_set_vring_enable()
706 if (vhost_ops && vhost_ops->vhost_set_vring_enable) { in vhost_set_vring_enable()
707 return vhost_ops->vhost_set_vring_enable(&net->dev, enable); in vhost_set_vring_enable()
710 return 0; in vhost_set_vring_enable()
715 const VhostOps *vhost_ops = net->dev.vhost_ops; in vhost_net_set_mtu()
717 if (!vhost_ops->vhost_net_set_mtu) { in vhost_net_set_mtu()
718 return 0; in vhost_net_set_mtu()
721 return vhost_ops->vhost_net_set_mtu(&net->dev, mtu); in vhost_net_set_mtu()
727 VHostNetState *net = get_vhost_net(nc->peer); in vhost_net_virtqueue_reset()
728 const VhostOps *vhost_ops = net->dev.vhost_ops; in vhost_net_virtqueue_reset()
729 struct vhost_vring_file file = { .fd = -1 }; in vhost_net_virtqueue_reset()
735 idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index); in vhost_net_virtqueue_reset()
737 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_virtqueue_reset()
739 int r = vhost_net_set_backend(&net->dev, &file); in vhost_net_virtqueue_reset()
740 assert(r >= 0); in vhost_net_virtqueue_reset()
743 vhost_virtqueue_stop(&net->dev, in vhost_net_virtqueue_reset()
745 net->dev.vqs + idx, in vhost_net_virtqueue_reset()
746 net->dev.vq_index + idx); in vhost_net_virtqueue_reset()
752 VHostNetState *net = get_vhost_net(nc->peer); in vhost_net_virtqueue_restart()
753 const VhostOps *vhost_ops = net->dev.vhost_ops; in vhost_net_virtqueue_restart()
757 if (!net->dev.started) { in vhost_net_virtqueue_restart()
758 return -EBUSY; in vhost_net_virtqueue_restart()
764 idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index); in vhost_net_virtqueue_restart()
766 r = vhost_virtqueue_start(&net->dev, in vhost_net_virtqueue_restart()
768 net->dev.vqs + idx, in vhost_net_virtqueue_restart()
769 net->dev.vq_index + idx); in vhost_net_virtqueue_restart()
770 if (r < 0) { in vhost_net_virtqueue_restart()
774 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_virtqueue_restart()
776 file.fd = net->backend; in vhost_net_virtqueue_restart()
777 r = vhost_net_set_backend(&net->dev, &file); in vhost_net_virtqueue_restart()
778 if (r < 0) { in vhost_net_virtqueue_restart()
779 r = -errno; in vhost_net_virtqueue_restart()
784 return 0; in vhost_net_virtqueue_restart()
789 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { in vhost_net_virtqueue_restart()
792 int ret = vhost_net_set_backend(&net->dev, &file); in vhost_net_virtqueue_restart()
793 assert(ret >= 0); in vhost_net_virtqueue_restart()
796 vhost_dev_stop(&net->dev, vdev, false); in vhost_net_virtqueue_restart()