-----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:
commit
5563168c53
@ -172,7 +172,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = vhost_dev_init(&net->dev, options->opaque,
|
r = vhost_dev_init(&net->dev, options->opaque,
|
||||||
options->backend_type);
|
options->backend_type, options->busyloop_timeout);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
|||||||
s->dev.backend_features = 0;
|
s->dev.backend_features = 0;
|
||||||
|
|
||||||
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
|
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
|
||||||
VHOST_BACKEND_TYPE_KERNEL);
|
VHOST_BACKEND_TYPE_KERNEL, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
|
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
|
||||||
strerror(-ret));
|
strerror(-ret));
|
||||||
|
@ -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);
|
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,
|
static int vhost_kernel_set_features(struct vhost_dev *dev,
|
||||||
uint64_t features)
|
uint64_t features)
|
||||||
{
|
{
|
||||||
@ -185,6 +191,8 @@ static const VhostOps kernel_ops = {
|
|||||||
.vhost_get_vring_base = vhost_kernel_get_vring_base,
|
.vhost_get_vring_base = vhost_kernel_get_vring_base,
|
||||||
.vhost_set_vring_kick = vhost_kernel_set_vring_kick,
|
.vhost_set_vring_kick = vhost_kernel_set_vring_kick,
|
||||||
.vhost_set_vring_call = vhost_kernel_set_vring_call,
|
.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_set_features = vhost_kernel_set_features,
|
||||||
.vhost_get_features = vhost_kernel_get_features,
|
.vhost_get_features = vhost_kernel_get_features,
|
||||||
.vhost_set_owner = vhost_kernel_set_owner,
|
.vhost_set_owner = vhost_kernel_set_owner,
|
||||||
|
@ -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,
|
static int vhost_virtqueue_init(struct vhost_dev *dev,
|
||||||
struct vhost_virtqueue *vq, int n)
|
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,
|
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
||||||
VhostBackendType backend_type)
|
VhostBackendType backend_type, uint32_t busyloop_timeout)
|
||||||
{
|
{
|
||||||
uint64_t features;
|
uint64_t features;
|
||||||
int i, r;
|
int i, r;
|
||||||
@ -1031,6 +1053,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||||||
goto fail_vq;
|
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->features = features;
|
||||||
|
|
||||||
hdev->memory_listener = (MemoryListener) {
|
hdev->memory_listener = (MemoryListener) {
|
||||||
@ -1073,6 +1106,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||||||
hdev->memory_changed = false;
|
hdev->memory_changed = false;
|
||||||
memory_listener_register(&hdev->memory_listener, &address_space_memory);
|
memory_listener_register(&hdev->memory_listener, &address_space_memory);
|
||||||
return 0;
|
return 0;
|
||||||
|
fail_busyloop:
|
||||||
|
while (--i >= 0) {
|
||||||
|
vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
|
||||||
|
}
|
||||||
|
i = hdev->nvqs;
|
||||||
fail_vq:
|
fail_vq:
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
vhost_virtqueue_cleanup(hdev->vqs + i);
|
vhost_virtqueue_cleanup(hdev->vqs + i);
|
||||||
|
@ -57,6 +57,8 @@ typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev,
|
|||||||
struct vhost_vring_file *file);
|
struct vhost_vring_file *file);
|
||||||
typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev,
|
typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev,
|
||||||
struct vhost_vring_file *file);
|
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,
|
typedef int (*vhost_set_features_op)(struct vhost_dev *dev,
|
||||||
uint64_t features);
|
uint64_t features);
|
||||||
typedef int (*vhost_get_features_op)(struct vhost_dev *dev,
|
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_get_vring_base_op vhost_get_vring_base;
|
||||||
vhost_set_vring_kick_op vhost_set_vring_kick;
|
vhost_set_vring_kick_op vhost_set_vring_kick;
|
||||||
vhost_set_vring_call_op vhost_set_vring_call;
|
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_set_features_op vhost_set_features;
|
||||||
vhost_get_features_op vhost_get_features;
|
vhost_get_features_op vhost_get_features;
|
||||||
vhost_set_owner_op vhost_set_owner;
|
vhost_set_owner_op vhost_set_owner;
|
||||||
|
@ -64,7 +64,8 @@ struct vhost_dev {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
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);
|
void vhost_dev_cleanup(struct vhost_dev *hdev);
|
||||||
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
|
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||||
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
|
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||||
|
@ -10,6 +10,7 @@ typedef struct vhost_net VHostNetState;
|
|||||||
typedef struct VhostNetOptions {
|
typedef struct VhostNetOptions {
|
||||||
VhostBackendType backend_type;
|
VhostBackendType backend_type;
|
||||||
NetClientState *net_backend;
|
NetClientState *net_backend;
|
||||||
|
uint32_t busyloop_timeout;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
} VhostNetOptions;
|
} VhostNetOptions;
|
||||||
|
|
||||||
|
@ -663,6 +663,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
|||||||
|
|
||||||
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
|
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
|
||||||
options.net_backend = &s->nc;
|
options.net_backend = &s->nc;
|
||||||
|
if (tap->has_poll_us) {
|
||||||
|
options.busyloop_timeout = tap->poll_us;
|
||||||
|
} else {
|
||||||
|
options.busyloop_timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (vhostfdname) {
|
if (vhostfdname) {
|
||||||
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
|
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
|
||||||
@ -687,7 +692,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (vhostfdname) {
|
} else if (vhostfdname) {
|
||||||
error_setg(errp, "vhostfd= is not valid without vhost");
|
error_setg(errp, "vhostfd(s)= is not valid without vhost");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
|
|||||||
|
|
||||||
options.net_backend = ncs[i];
|
options.net_backend = ncs[i];
|
||||||
options.opaque = s->chr;
|
options.opaque = s->chr;
|
||||||
|
options.busyloop_timeout = 0;
|
||||||
s->vhost_net = vhost_net_init(&options);
|
s->vhost_net = vhost_net_init(&options);
|
||||||
if (!s->vhost_net) {
|
if (!s->vhost_net) {
|
||||||
error_report("failed to init vhost_net for queue %d", i);
|
error_report("failed to init vhost_net for queue %d", i);
|
||||||
|
@ -2592,6 +2592,9 @@
|
|||||||
#
|
#
|
||||||
# @queues: #optional number of queues to be created for multiqueue capable tap
|
# @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
|
# Since 1.2
|
||||||
##
|
##
|
||||||
{ 'struct': 'NetdevTapOptions',
|
{ 'struct': 'NetdevTapOptions',
|
||||||
@ -2608,7 +2611,8 @@
|
|||||||
'*vhostfd': 'str',
|
'*vhostfd': 'str',
|
||||||
'*vhostfds': 'str',
|
'*vhostfds': 'str',
|
||||||
'*vhostforce': 'bool',
|
'*vhostforce': 'bool',
|
||||||
'*queues': 'uint32'} }
|
'*queues': 'uint32',
|
||||||
|
'*poll-us': 'uint32'} }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @NetdevSocketOptions
|
# @NetdevSocketOptions
|
||||||
|
@ -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"
|
"-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"
|
" [,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off]\n"
|
||||||
" [,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\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"
|
" configure a host TAP network backend with ID 'str'\n"
|
||||||
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
|
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
|
||||||
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_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 '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 '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 '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"
|
"-netdev bridge,id=str[,br=bridge][,helper=helper]\n"
|
||||||
" configure a host TAP network backend with ID 'str' that is\n"
|
" configure a host TAP network backend with ID 'str' that is\n"
|
||||||
" connected to a bridge (default=" DEFAULT_BRIDGE_INTERFACE ")\n"
|
" connected to a bridge (default=" DEFAULT_BRIDGE_INTERFACE ")\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user