-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQEcBAABAgAGBQJXffbYAAoJEO8Ells5jWIRZnAH/2bleryOC4i6Pwz7cNpX07MQ
 YmJ97K6RueVcYjj7pSi4l8nzv18K0k43x04ST6WIpHbRf07RIJIBOVn/f8xUnNo/
 EonhPgYWZXZX7h9EWnjUWccKU8ReQO06lUi2H7XX6f6Ba3maG2A4HCvhraE+noIr
 pkM4Qj6niD+i6hZsznmhuLWUE+ynt2JdmBIxxG+e12t/Hq5vW7IYPj6Y1IQia9r9
 vkz2wWmmiVTty6g5d/pu8yyWt+b2ob8cQ0OoRrqr1uNF/h4uWcUlgUZEe/DJER3M
 u+s5xVKLM4FK+w0grBKMCDzmRsjixV42tcS0H8LABpdRce8PINOmpsO3QI+Ul5g=
 =YU37
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging

# gpg: Signature made Thu 07 Jul 2016 07:29:44 BST
# gpg:                using RSA key 0xEF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F  3562 EF04 965B 398D 6211

* remotes/jasowang/tags/net-pull-request:
  tap: vhost busy polling support

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-07-07 10:29:05 +01:00
commit 5563168c53
11 changed files with 70 additions and 6 deletions

View file

@ -172,7 +172,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
}
r = vhost_dev_init(&net->dev, options->opaque,
options->backend_type);
options->backend_type, options->busyloop_timeout);
if (r < 0) {
goto fail;
}

View file

@ -248,7 +248,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
s->dev.backend_features = 0;
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
VHOST_BACKEND_TYPE_KERNEL);
VHOST_BACKEND_TYPE_KERNEL, 0);
if (ret < 0) {
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
strerror(-ret));

View file

@ -138,6 +138,12 @@ static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
}
static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev,
struct vhost_vring_state *s)
{
return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s);
}
static int vhost_kernel_set_features(struct vhost_dev *dev,
uint64_t features)
{
@ -185,6 +191,8 @@ static const VhostOps kernel_ops = {
.vhost_get_vring_base = vhost_kernel_get_vring_base,
.vhost_set_vring_kick = vhost_kernel_set_vring_kick,
.vhost_set_vring_call = vhost_kernel_set_vring_call,
.vhost_set_vring_busyloop_timeout =
vhost_kernel_set_vring_busyloop_timeout,
.vhost_set_features = vhost_kernel_set_features,
.vhost_get_features = vhost_kernel_get_features,
.vhost_set_owner = vhost_kernel_set_owner,

View file

@ -960,6 +960,28 @@ static void vhost_eventfd_del(MemoryListener *listener,
{
}
static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev,
int n, uint32_t timeout)
{
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, n);
struct vhost_vring_state state = {
.index = vhost_vq_index,
.num = timeout,
};
int r;
if (!dev->vhost_ops->vhost_set_vring_busyloop_timeout) {
return -EINVAL;
}
r = dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &state);
if (r) {
return r;
}
return 0;
}
static int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n)
{
@ -990,7 +1012,7 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
VhostBackendType backend_type)
VhostBackendType backend_type, uint32_t busyloop_timeout)
{
uint64_t features;
int i, r;
@ -1031,6 +1053,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
goto fail_vq;
}
}
if (busyloop_timeout) {
for (i = 0; i < hdev->nvqs; ++i) {
r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
busyloop_timeout);
if (r < 0) {
goto fail_busyloop;
}
}
}
hdev->features = features;
hdev->memory_listener = (MemoryListener) {
@ -1073,6 +1106,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hdev->memory_changed = false;
memory_listener_register(&hdev->memory_listener, &address_space_memory);
return 0;
fail_busyloop:
while (--i >= 0) {
vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
}
i = hdev->nvqs;
fail_vq:
while (--i >= 0) {
vhost_virtqueue_cleanup(hdev->vqs + i);

View file

@ -57,6 +57,8 @@ typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev,
struct vhost_vring_file *file);
typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev,
struct vhost_vring_file *file);
typedef int (*vhost_set_vring_busyloop_timeout_op)(struct vhost_dev *dev,
struct vhost_vring_state *r);
typedef int (*vhost_set_features_op)(struct vhost_dev *dev,
uint64_t features);
typedef int (*vhost_get_features_op)(struct vhost_dev *dev,
@ -91,6 +93,7 @@ typedef struct VhostOps {
vhost_get_vring_base_op vhost_get_vring_base;
vhost_set_vring_kick_op vhost_set_vring_kick;
vhost_set_vring_call_op vhost_set_vring_call;
vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_timeout;
vhost_set_features_op vhost_set_features;
vhost_get_features_op vhost_get_features;
vhost_set_owner_op vhost_set_owner;

View file

@ -64,7 +64,8 @@ struct vhost_dev {
};
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
VhostBackendType backend_type);
VhostBackendType backend_type,
uint32_t busyloop_timeout);
void vhost_dev_cleanup(struct vhost_dev *hdev);
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);

View file

@ -10,6 +10,7 @@ typedef struct vhost_net VHostNetState;
typedef struct VhostNetOptions {
VhostBackendType backend_type;
NetClientState *net_backend;
uint32_t busyloop_timeout;
void *opaque;
} VhostNetOptions;

View file

@ -663,6 +663,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
options.net_backend = &s->nc;
if (tap->has_poll_us) {
options.busyloop_timeout = tap->poll_us;
} else {
options.busyloop_timeout = 0;
}
if (vhostfdname) {
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
@ -687,7 +692,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
return;
}
} else if (vhostfdname) {
error_setg(errp, "vhostfd= is not valid without vhost");
error_setg(errp, "vhostfd(s)= is not valid without vhost");
}
}

View file

@ -91,6 +91,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
options.net_backend = ncs[i];
options.opaque = s->chr;
options.busyloop_timeout = 0;
s->vhost_net = vhost_net_init(&options);
if (!s->vhost_net) {
error_report("failed to init vhost_net for queue %d", i);

View file

@ -2592,6 +2592,9 @@
#
# @queues: #optional number of queues to be created for multiqueue capable tap
#
# @poll-us: #optional maximum number of microseconds that could
# be spent on busy polling for tap (since 2.7)
#
# Since 1.2
##
{ 'struct': 'NetdevTapOptions',
@ -2608,7 +2611,8 @@
'*vhostfd': 'str',
'*vhostfds': 'str',
'*vhostforce': 'bool',
'*queues': 'uint32'} }
'*queues': 'uint32',
'*poll-us': 'uint32'} }
##
# @NetdevSocketOptions

View file

@ -1581,6 +1581,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
"-netdev tap,id=str[,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile]\n"
" [,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off]\n"
" [,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
" [,poll-us=n]\n"
" configure a host TAP network backend with ID 'str'\n"
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@ -1600,6 +1601,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" use 'vhostfd=h' to connect to an already opened vhost net device\n"
" use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n"
" use 'queues=n' to specify the number of queues to be created for multiqueue TAP\n"
" use 'poll-us=n' to speciy the maximum number of microseconds that could be\n"
" spent on busy polling for vhost net\n"
"-netdev bridge,id=str[,br=bridge][,helper=helper]\n"
" configure a host TAP network backend with ID 'str' that is\n"
" connected to a bridge (default=" DEFAULT_BRIDGE_INTERFACE ")\n"