Skip to content

Commit

Permalink
tap: vhost busy polling support
Browse files Browse the repository at this point in the history
This patch add the capability of basic vhost net busy polling which is
supported by recent kernel. User could configure the maximum number of
us that could be spent on busy polling through a new property of tap
"poll-us".

Cc: Greg Kurz <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Jason Wang <[email protected]>
  • Loading branch information
jasowang committed Jul 7, 2016
1 parent 91d3550 commit 69e87b3
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 6 deletions.
2 changes: 1 addition & 1 deletion hw/net/vhost_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion hw/scsi/vhost-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
8 changes: 8 additions & 0 deletions hw/virtio/vhost-backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down
40 changes: 39 additions & 1 deletion hw/virtio/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions include/hw/virtio/vhost-backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion include/hw/virtio/vhost.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/net/vhost_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 6 additions & 1 deletion net/tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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");
}
}

Expand Down
1 change: 1 addition & 0 deletions net/vhost-user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion qapi-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -2608,7 +2611,8 @@
'*vhostfd': 'str',
'*vhostfds': 'str',
'*vhostforce': 'bool',
'*queues': 'uint32'} }
'*queues': 'uint32',
'*poll-us': 'uint32'} }

##
# @NetdevSocketOptions
Expand Down
3 changes: 3 additions & 0 deletions qemu-options.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down

0 comments on commit 69e87b3

Please sign in to comment.