mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +00:00
QAPI patches for 2016-07-19
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXjnLvAAoJEDhwtADrkYZTkd0P/iVsviq3WwxjmpbjyYDqgBYl 2hj9XL8ZtYGwFIU9WZXdu16lXlXtZom9u8XzspXIvhy5McNeWDxYarbE2kByyjac rl4873YzIspVKPPFMl2LWsHwtq7LLGzFF+f+ofjHN81ZdM6qTwZBe00gxxY8281I 6x1aQYkhOAmqJAlqqnEVk76WtdScs23mdbqmy1LzGD3ZBKvDa8IasogAKvZquNZX P16kYdq9QFqFJ30non9fWg9VQWtdryisseVhpSY/PXlrM4H+XPDK4hvegr3pjN8S yqtmKkPOuVWQyCfRz6UWBP0ncz3QN7iOiVLqb6TJgxJ8jFp3lbEEsXsCkvpSWjOU JDFOcGuiE1AVoZF8NxWQ3fdLiHt2jyCgY7iqgbNc1A3eT2H5IshIc7OF5QOU7MtP EYqk5bXiusUftuvZE5Mh0pXJ5AeOEOoXM+/dGRt3IRxPtqOWlW7/NM4YGgMD9XFg 83i5OIjdOBa1HYvetfEl3oKYsu+2zGsSqz4AH3CDIWJ8aoWJ9RNId3JJWFf+jyFR S+l7wMyFYdzDL7VqUmIy8xrVgc0IQPYT0udcjdOciEej873roEVencQ07VnK2zN0 aiAmAN/BQFO0HmmH4rBvTcLxF06+HnW0CwKii0mlAeisUFTQJEDmyg823Uc+MAGl 4pGFqDUbnzsy8xK3HCCP =MhfL -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-07-19' into staging QAPI patches for 2016-07-19 # gpg: Signature made Tue 19 Jul 2016 19:35:27 BST # gpg: using RSA key 0x3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2016-07-19: net: Use correct type for bool flag qapi: Change Netdev into a flat union block: Simplify drive-mirror block: Simplify block_set_io_throttle qapi: Implement boxed types for commands/events qapi: Plumb in 'boxed' to qapi generator lower levels qapi-event: Simplify visit of non-implicit data qapi: Drop useless gen_err_check() qapi: Add type.is_empty() helper qapi: Hide tag_name data member of variants qapi: Special case c_name() for empty type qapi: Require all branches of flat union enum to be covered net: use Netdev instead of NetClientOptions in client init qapi: change QmpInputVisitor to QSLIST qapi: change QmpOutputVisitor to QSLIST Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3b2e6798ff
189
blockdev.c
189
blockdev.c
@ -2634,49 +2634,17 @@ fail:
|
||||
}
|
||||
|
||||
/* throttling disk I/O limits */
|
||||
void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
int64_t bps_wr,
|
||||
int64_t iops,
|
||||
int64_t iops_rd,
|
||||
int64_t iops_wr,
|
||||
bool has_bps_max,
|
||||
int64_t bps_max,
|
||||
bool has_bps_rd_max,
|
||||
int64_t bps_rd_max,
|
||||
bool has_bps_wr_max,
|
||||
int64_t bps_wr_max,
|
||||
bool has_iops_max,
|
||||
int64_t iops_max,
|
||||
bool has_iops_rd_max,
|
||||
int64_t iops_rd_max,
|
||||
bool has_iops_wr_max,
|
||||
int64_t iops_wr_max,
|
||||
bool has_bps_max_length,
|
||||
int64_t bps_max_length,
|
||||
bool has_bps_rd_max_length,
|
||||
int64_t bps_rd_max_length,
|
||||
bool has_bps_wr_max_length,
|
||||
int64_t bps_wr_max_length,
|
||||
bool has_iops_max_length,
|
||||
int64_t iops_max_length,
|
||||
bool has_iops_rd_max_length,
|
||||
int64_t iops_rd_max_length,
|
||||
bool has_iops_wr_max_length,
|
||||
int64_t iops_wr_max_length,
|
||||
bool has_iops_size,
|
||||
int64_t iops_size,
|
||||
bool has_group,
|
||||
const char *group, Error **errp)
|
||||
void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
|
||||
{
|
||||
ThrottleConfig cfg;
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk;
|
||||
AioContext *aio_context;
|
||||
|
||||
blk = blk_by_name(device);
|
||||
blk = blk_by_name(arg->device);
|
||||
if (!blk) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
"Device '%s' not found", device);
|
||||
"Device '%s' not found", arg->device);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2685,59 +2653,59 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
|
||||
bs = blk_bs(blk);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Device '%s' has no medium", device);
|
||||
error_setg(errp, "Device '%s' has no medium", arg->device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
throttle_config_init(&cfg);
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
|
||||
cfg.buckets[THROTTLE_BPS_READ].avg = bps_rd;
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr;
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps;
|
||||
cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd;
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr;
|
||||
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops;
|
||||
cfg.buckets[THROTTLE_OPS_READ].avg = iops_rd;
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr;
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops;
|
||||
cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd;
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr;
|
||||
|
||||
if (has_bps_max) {
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max;
|
||||
if (arg->has_bps_max) {
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max;
|
||||
}
|
||||
if (has_bps_rd_max) {
|
||||
cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max;
|
||||
if (arg->has_bps_rd_max) {
|
||||
cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max;
|
||||
}
|
||||
if (has_bps_wr_max) {
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max;
|
||||
if (arg->has_bps_wr_max) {
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max;
|
||||
}
|
||||
if (has_iops_max) {
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max;
|
||||
if (arg->has_iops_max) {
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max;
|
||||
}
|
||||
if (has_iops_rd_max) {
|
||||
cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max;
|
||||
if (arg->has_iops_rd_max) {
|
||||
cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max;
|
||||
}
|
||||
if (has_iops_wr_max) {
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max;
|
||||
if (arg->has_iops_wr_max) {
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max;
|
||||
}
|
||||
|
||||
if (has_bps_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = bps_max_length;
|
||||
if (arg->has_bps_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length;
|
||||
}
|
||||
if (has_bps_rd_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_READ].burst_length = bps_rd_max_length;
|
||||
if (arg->has_bps_rd_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length;
|
||||
}
|
||||
if (has_bps_wr_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].burst_length = bps_wr_max_length;
|
||||
if (arg->has_bps_wr_max_length) {
|
||||
cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length;
|
||||
}
|
||||
if (has_iops_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = iops_max_length;
|
||||
if (arg->has_iops_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length;
|
||||
}
|
||||
if (has_iops_rd_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_READ].burst_length = iops_rd_max_length;
|
||||
if (arg->has_iops_rd_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length;
|
||||
}
|
||||
if (has_iops_wr_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].burst_length = iops_wr_max_length;
|
||||
if (arg->has_iops_wr_max_length) {
|
||||
cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length;
|
||||
}
|
||||
|
||||
if (has_iops_size) {
|
||||
cfg.op_size = iops_size;
|
||||
if (arg->has_iops_size) {
|
||||
cfg.op_size = arg->iops_size;
|
||||
}
|
||||
|
||||
if (!throttle_is_valid(&cfg, errp)) {
|
||||
@ -2748,9 +2716,10 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
/* Enable I/O limits if they're not enabled yet, otherwise
|
||||
* just update the throttling group. */
|
||||
if (!blk_get_public(blk)->throttle_state) {
|
||||
blk_io_limits_enable(blk, has_group ? group : device);
|
||||
} else if (has_group) {
|
||||
blk_io_limits_update_group(blk, group);
|
||||
blk_io_limits_enable(blk,
|
||||
arg->has_group ? arg->group : arg->device);
|
||||
} else if (arg->has_group) {
|
||||
blk_io_limits_update_group(blk, arg->group);
|
||||
}
|
||||
/* Set the new throttling configuration */
|
||||
blk_set_io_limits(blk, &cfg);
|
||||
@ -3497,19 +3466,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
||||
block_job_cb, bs, errp);
|
||||
}
|
||||
|
||||
void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
const char *target, bool has_format, const char *format,
|
||||
bool has_node_name, const char *node_name,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
bool has_mode, enum NewImageMode mode,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
bool has_on_source_error, BlockdevOnError on_source_error,
|
||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
||||
bool has_unmap, bool unmap,
|
||||
Error **errp)
|
||||
void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk;
|
||||
@ -3520,11 +3477,12 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
QDict *options = NULL;
|
||||
int flags;
|
||||
int64_t size;
|
||||
const char *format = arg->format;
|
||||
|
||||
blk = blk_by_name(device);
|
||||
blk = blk_by_name(arg->device);
|
||||
if (!blk) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
"Device '%s' not found", device);
|
||||
"Device '%s' not found", arg->device);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3532,24 +3490,25 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
if (!blk_is_available(blk)) {
|
||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
|
||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, arg->device);
|
||||
goto out;
|
||||
}
|
||||
bs = blk_bs(blk);
|
||||
if (!has_mode) {
|
||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
if (!arg->has_mode) {
|
||||
arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
}
|
||||
|
||||
if (!has_format) {
|
||||
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
|
||||
if (!arg->has_format) {
|
||||
format = (arg->mode == NEW_IMAGE_MODE_EXISTING
|
||||
? NULL : bs->drv->format_name);
|
||||
}
|
||||
|
||||
flags = bs->open_flags | BDRV_O_RDWR;
|
||||
source = backing_bs(bs);
|
||||
if (!source && sync == MIRROR_SYNC_MODE_TOP) {
|
||||
sync = MIRROR_SYNC_MODE_FULL;
|
||||
if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) {
|
||||
arg->sync = MIRROR_SYNC_MODE_FULL;
|
||||
}
|
||||
if (sync == MIRROR_SYNC_MODE_NONE) {
|
||||
if (arg->sync == MIRROR_SYNC_MODE_NONE) {
|
||||
source = bs;
|
||||
}
|
||||
|
||||
@ -3559,18 +3518,18 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (has_replaces) {
|
||||
if (arg->has_replaces) {
|
||||
BlockDriverState *to_replace_bs;
|
||||
AioContext *replace_aio_context;
|
||||
int64_t replace_size;
|
||||
|
||||
if (!has_node_name) {
|
||||
if (!arg->has_node_name) {
|
||||
error_setg(errp, "a node-name must be provided when replacing a"
|
||||
" named node of the graph");
|
||||
goto out;
|
||||
}
|
||||
|
||||
to_replace_bs = check_to_replace_node(bs, replaces, &local_err);
|
||||
to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err);
|
||||
|
||||
if (!to_replace_bs) {
|
||||
error_propagate(errp, local_err);
|
||||
@ -3589,26 +3548,26 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
|
||||
if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
|
||||
backing_mode = MIRROR_SOURCE_BACKING_CHAIN;
|
||||
} else {
|
||||
backing_mode = MIRROR_OPEN_BACKING_CHAIN;
|
||||
}
|
||||
|
||||
if ((sync == MIRROR_SYNC_MODE_FULL || !source)
|
||||
&& mode != NEW_IMAGE_MODE_EXISTING)
|
||||
if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)
|
||||
&& arg->mode != NEW_IMAGE_MODE_EXISTING)
|
||||
{
|
||||
/* create new image w/o backing file */
|
||||
assert(format);
|
||||
bdrv_img_create(target, format,
|
||||
bdrv_img_create(arg->target, format,
|
||||
NULL, NULL, NULL, size, flags, &local_err, false);
|
||||
} else {
|
||||
switch (mode) {
|
||||
switch (arg->mode) {
|
||||
case NEW_IMAGE_MODE_EXISTING:
|
||||
break;
|
||||
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
|
||||
/* create new image with backing file */
|
||||
bdrv_img_create(target, format,
|
||||
bdrv_img_create(arg->target, format,
|
||||
source->filename,
|
||||
source->drv->format_name,
|
||||
NULL, size, flags, &local_err, false);
|
||||
@ -3624,8 +3583,8 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
}
|
||||
|
||||
options = qdict_new();
|
||||
if (has_node_name) {
|
||||
qdict_put(options, "node-name", qstring_from_str(node_name));
|
||||
if (arg->has_node_name) {
|
||||
qdict_put(options, "node-name", qstring_from_str(arg->node_name));
|
||||
}
|
||||
if (format) {
|
||||
qdict_put(options, "driver", qstring_from_str(format));
|
||||
@ -3634,22 +3593,22 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
|
||||
/* Mirroring takes care of copy-on-write using the source's backing
|
||||
* file.
|
||||
*/
|
||||
target_bs = bdrv_open(target, NULL, options, flags | BDRV_O_NO_BACKING,
|
||||
errp);
|
||||
target_bs = bdrv_open(arg->target, NULL, options,
|
||||
flags | BDRV_O_NO_BACKING, errp);
|
||||
if (!target_bs) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_set_aio_context(target_bs, aio_context);
|
||||
|
||||
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
|
||||
has_replaces, replaces, sync, backing_mode,
|
||||
has_speed, speed,
|
||||
has_granularity, granularity,
|
||||
has_buf_size, buf_size,
|
||||
has_on_source_error, on_source_error,
|
||||
has_on_target_error, on_target_error,
|
||||
has_unmap, unmap,
|
||||
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
||||
arg->has_replaces, arg->replaces, arg->sync,
|
||||
backing_mode, arg->has_speed, arg->speed,
|
||||
arg->has_granularity, arg->granularity,
|
||||
arg->has_buf_size, arg->buf_size,
|
||||
arg->has_on_source_error, arg->on_source_error,
|
||||
arg->has_on_target_error, arg->on_target_error,
|
||||
arg->has_unmap, arg->unmap,
|
||||
&local_err);
|
||||
bdrv_unref(target_bs);
|
||||
error_propagate(errp, local_err);
|
||||
|
@ -410,7 +410,7 @@ following example objects:
|
||||
=== Commands ===
|
||||
|
||||
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
||||
'*returns': TYPE-NAME,
|
||||
'*returns': TYPE-NAME, '*boxed': true,
|
||||
'*gen': false, '*success-response': false }
|
||||
|
||||
Commands are defined by using a dictionary containing several members,
|
||||
@ -461,6 +461,20 @@ which would validate this Client JSON Protocol transaction:
|
||||
=> { "execute": "my-second-command" }
|
||||
<= { "return": [ { "value": "one" }, { } ] }
|
||||
|
||||
The generator emits a prototype for the user's function implementing
|
||||
the command. Normally, 'data' is a dictionary for an anonymous type,
|
||||
or names a struct type (possibly empty, but not a union), and its
|
||||
members are passed as separate arguments to this function. If the
|
||||
command definition includes a key 'boxed' with the boolean value true,
|
||||
then 'data' is instead the name of any non-empty complex type
|
||||
(struct, union, or alternate), and a pointer to that QAPI type is
|
||||
passed as a single argument.
|
||||
|
||||
The generator also emits a marshalling function that extracts
|
||||
arguments for the user's function out of an input QDict, calls the
|
||||
user's function, and if it succeeded, builds an output QObject from
|
||||
its return value.
|
||||
|
||||
In rare cases, QAPI cannot express a type-safe representation of a
|
||||
corresponding Client JSON Protocol command. You then have to suppress
|
||||
generation of a marshalling function by including a key 'gen' with
|
||||
@ -484,7 +498,8 @@ use of this member.
|
||||
|
||||
=== Events ===
|
||||
|
||||
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT }
|
||||
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
||||
'*boxed': true }
|
||||
|
||||
Events are defined with the keyword 'event'. It is not allowed to
|
||||
name an event 'MAX', since the generator also produces a C enumeration
|
||||
@ -505,6 +520,14 @@ Resulting in this JSON object:
|
||||
"data": { "b": "test string" },
|
||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
|
||||
The generator emits a function to send the event. Normally, 'data' is
|
||||
a dictionary for an anonymous type, or names a struct type (possibly
|
||||
empty, but not a union), and its members are passed as separate
|
||||
arguments to this function. If the event definition includes a key
|
||||
'boxed' with the boolean value true, then 'data' is instead the name of
|
||||
any non-empty complex type (struct, union, or alternate), and a
|
||||
pointer to that QAPI type is passed as a single argument.
|
||||
|
||||
|
||||
== Client JSON Protocol introspection ==
|
||||
|
||||
|
70
hmp.c
70
hmp.c
@ -1077,31 +1077,28 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
|
||||
|
||||
void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
const char *filename = qdict_get_str(qdict, "target");
|
||||
const char *format = qdict_get_try_str(qdict, "format");
|
||||
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
||||
bool full = qdict_get_try_bool(qdict, "full", false);
|
||||
enum NewImageMode mode;
|
||||
Error *err = NULL;
|
||||
DriveMirror mirror = {
|
||||
.device = (char *)qdict_get_str(qdict, "device"),
|
||||
.target = (char *)filename,
|
||||
.has_format = !!format,
|
||||
.format = (char *)format,
|
||||
.sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
||||
.has_mode = true,
|
||||
.mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
|
||||
.unmap = true,
|
||||
};
|
||||
|
||||
if (!filename) {
|
||||
error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
||||
hmp_handle_error(mon, &err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reuse) {
|
||||
mode = NEW_IMAGE_MODE_EXISTING;
|
||||
} else {
|
||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
}
|
||||
|
||||
qmp_drive_mirror(false, NULL, device, filename, !!format, format,
|
||||
false, NULL, false, NULL,
|
||||
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
||||
true, mode, false, 0, false, 0, false, 0,
|
||||
false, 0, false, 0, false, true, &err);
|
||||
qmp_drive_mirror(&mirror, &err);
|
||||
hmp_handle_error(mon, &err);
|
||||
}
|
||||
|
||||
@ -1439,42 +1436,17 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *err = NULL;
|
||||
BlockIOThrottle throttle = {
|
||||
.device = (char *) qdict_get_str(qdict, "device"),
|
||||
.bps = qdict_get_int(qdict, "bps"),
|
||||
.bps_rd = qdict_get_int(qdict, "bps_rd"),
|
||||
.bps_wr = qdict_get_int(qdict, "bps_wr"),
|
||||
.iops = qdict_get_int(qdict, "iops"),
|
||||
.iops_rd = qdict_get_int(qdict, "iops_rd"),
|
||||
.iops_wr = qdict_get_int(qdict, "iops_wr"),
|
||||
};
|
||||
|
||||
qmp_block_set_io_throttle(qdict_get_str(qdict, "device"),
|
||||
qdict_get_int(qdict, "bps"),
|
||||
qdict_get_int(qdict, "bps_rd"),
|
||||
qdict_get_int(qdict, "bps_wr"),
|
||||
qdict_get_int(qdict, "iops"),
|
||||
qdict_get_int(qdict, "iops_rd"),
|
||||
qdict_get_int(qdict, "iops_wr"),
|
||||
false, /* no burst max via HMP */
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false, /* no burst length via HMP */
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
false, /* No default I/O size */
|
||||
0,
|
||||
false,
|
||||
NULL, &err);
|
||||
qmp_block_set_io_throttle(&throttle, &err);
|
||||
hmp_handle_error(mon, &err);
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ static void eth_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_mv88w8618_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = eth_receive,
|
||||
.cleanup = eth_cleanup,
|
||||
|
@ -247,7 +247,7 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
|
||||
}
|
||||
|
||||
queues = qemu_find_net_clients_except(str, peers,
|
||||
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
if (queues == 0) {
|
||||
err = -ENOENT;
|
||||
|
@ -424,7 +424,7 @@ static const MemoryRegionOps aw_emac_mem_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_aw_emac_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = aw_emac_can_receive,
|
||||
.receive = aw_emac_receive,
|
||||
|
@ -1207,7 +1207,7 @@ static void gem_set_link(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_gem_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = gem_can_receive,
|
||||
.receive = gem_receive,
|
||||
|
@ -812,7 +812,7 @@ static void dp8393x_reset(DeviceState *dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_dp83932_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = dp8393x_can_receive,
|
||||
.receive = dp8393x_receive,
|
||||
|
@ -1563,7 +1563,7 @@ pci_e1000_uninit(PCIDevice *dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_e1000_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = e1000_can_receive,
|
||||
.receive = e1000_receive,
|
||||
|
@ -225,7 +225,7 @@ e1000e_set_link_status(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_e1000e_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = e1000e_nc_can_receive,
|
||||
.receive = e1000e_nc_receive,
|
||||
|
@ -1848,7 +1848,7 @@ static void pci_nic_uninit(PCIDevice *pci_dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_eepro100_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = nic_receive,
|
||||
};
|
||||
|
@ -578,7 +578,7 @@ static const MemoryRegionOps eth_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_etraxfs_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = eth_receive,
|
||||
.link_status_changed = eth_set_link,
|
||||
|
@ -371,7 +371,7 @@ static void etsec_set_link_status(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_etsec_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = etsec_receive,
|
||||
.link_status_changed = etsec_set_link_status,
|
||||
|
@ -1147,7 +1147,7 @@ static void imx_eth_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo imx_eth_net_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = imx_eth_can_receive,
|
||||
.receive = imx_eth_receive,
|
||||
|
@ -1313,7 +1313,7 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_lan9118_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = lan9118_receive,
|
||||
.link_status_changed = lan9118_set_link,
|
||||
|
@ -93,7 +93,7 @@ static const MemoryRegionOps lance_mem_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_lance_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = pcnet_receive,
|
||||
.link_status_changed = pcnet_set_link_status,
|
||||
|
@ -507,7 +507,7 @@ static const MemoryRegionOps mcf_fec_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_mcf_fec_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = mcf_fec_receive,
|
||||
};
|
||||
|
@ -447,7 +447,7 @@ static void milkymist_minimac2_reset(DeviceState *d)
|
||||
}
|
||||
|
||||
static NetClientInfo net_milkymist_minimac2_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = minimac2_rx,
|
||||
};
|
||||
|
@ -224,7 +224,7 @@ static const VMStateDescription vmstate_mipsnet = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_mipsnet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = mipsnet_receive,
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ typedef struct ISANE2000State {
|
||||
} ISANE2000State;
|
||||
|
||||
static NetClientInfo net_ne2000_isa_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = ne2000_receive,
|
||||
};
|
||||
|
@ -712,7 +712,7 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
|
||||
}
|
||||
|
||||
static NetClientInfo net_ne2000_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = ne2000_receive,
|
||||
};
|
||||
|
@ -473,7 +473,7 @@ static ssize_t open_eth_receive(NetClientState *nc,
|
||||
}
|
||||
|
||||
static NetClientInfo net_open_eth_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = open_eth_can_receive,
|
||||
.receive = open_eth_receive,
|
||||
|
@ -272,7 +272,7 @@ static void pci_pcnet_uninit(PCIDevice *dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_pci_pcnet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = pcnet_receive,
|
||||
.link_status_changed = pcnet_set_link_status,
|
||||
|
@ -167,7 +167,7 @@ static void fp_port_set_link_status(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo fp_port_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = fp_port_receive,
|
||||
.receive_iov = fp_port_receive_iov,
|
||||
|
@ -3393,7 +3393,7 @@ static void rtl8139_set_link_status(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_rtl8139_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = rtl8139_can_receive,
|
||||
.receive = rtl8139_receive,
|
||||
|
@ -755,7 +755,7 @@ static const MemoryRegionOps smc91c111_mem_ops = {
|
||||
};
|
||||
|
||||
static NetClientInfo net_smc91c111_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = smc91c111_can_receive_nc,
|
||||
.receive = smc91c111_receive,
|
||||
|
@ -278,7 +278,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
|
||||
}
|
||||
|
||||
static NetClientInfo net_spapr_vlan_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = spapr_vlan_can_receive,
|
||||
.receive = spapr_vlan_receive,
|
||||
|
@ -460,7 +460,7 @@ static void stellaris_enet_reset(stellaris_enet_state *s)
|
||||
}
|
||||
|
||||
static NetClientInfo net_stellaris_enet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = stellaris_enet_receive,
|
||||
};
|
||||
|
@ -88,10 +88,10 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net)
|
||||
const int *feature_bits = 0;
|
||||
|
||||
switch (net->nc->info->type) {
|
||||
case NET_CLIENT_OPTIONS_KIND_TAP:
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
feature_bits = kernel_feature_bits;
|
||||
break;
|
||||
case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
feature_bits = user_feature_bits;
|
||||
break;
|
||||
default:
|
||||
@ -128,7 +128,7 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net)
|
||||
static int vhost_net_get_fd(NetClientState *backend)
|
||||
{
|
||||
switch (backend->info->type) {
|
||||
case NET_CLIENT_OPTIONS_KIND_TAP:
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
return tap_get_fd(backend);
|
||||
default:
|
||||
fprintf(stderr, "vhost-net requires tap backend\n");
|
||||
@ -191,7 +191,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
||||
}
|
||||
|
||||
/* Set sane init value. Override when guest acks. */
|
||||
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
features = vhost_user_get_acked_features(net->nc);
|
||||
if (~net->dev.features & features) {
|
||||
fprintf(stderr, "vhost lacks feature mask %" PRIu64
|
||||
@ -238,7 +238,7 @@ static int vhost_net_start_one(struct vhost_net *net,
|
||||
net->nc->info->poll(net->nc, false);
|
||||
}
|
||||
|
||||
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
|
||||
qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
|
||||
file.fd = net->backend;
|
||||
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
@ -253,7 +253,7 @@ static int vhost_net_start_one(struct vhost_net *net,
|
||||
return 0;
|
||||
fail:
|
||||
file.fd = -1;
|
||||
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
|
||||
while (file.index-- > 0) {
|
||||
const VhostOps *vhost_ops = net->dev.vhost_ops;
|
||||
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
|
||||
@ -275,7 +275,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
|
||||
{
|
||||
struct vhost_vring_file file = { .fd = -1 };
|
||||
|
||||
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
|
||||
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
const VhostOps *vhost_ops = net->dev.vhost_ops;
|
||||
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
|
||||
@ -312,7 +312,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
||||
* because vhost user doesn't interrupt masking/unmasking
|
||||
* properly.
|
||||
*/
|
||||
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
dev->use_guest_notifier_mask = false;
|
||||
}
|
||||
}
|
||||
@ -413,10 +413,10 @@ VHostNetState *get_vhost_net(NetClientState *nc)
|
||||
}
|
||||
|
||||
switch (nc->info->type) {
|
||||
case NET_CLIENT_OPTIONS_KIND_TAP:
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
vhost_net = tap_get_vhost_net(nc);
|
||||
break;
|
||||
case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
vhost_net = vhost_user_get_vhost_net(nc);
|
||||
break;
|
||||
default:
|
||||
|
@ -468,11 +468,11 @@ static int peer_attach(VirtIONet *n, int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
|
||||
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
vhost_set_vring_enable(nc->peer, 1);
|
||||
}
|
||||
|
||||
if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -487,11 +487,11 @@ static int peer_detach(VirtIONet *n, int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
|
||||
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
vhost_set_vring_enable(nc->peer, 0);
|
||||
}
|
||||
|
||||
if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1680,7 +1680,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||
}
|
||||
|
||||
static NetClientInfo net_virtio_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = virtio_net_can_receive,
|
||||
.receive = virtio_net_receive,
|
||||
|
@ -2087,7 +2087,7 @@ static void vmxnet3_set_link_status(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_vmxnet3_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = vmxnet3_receive,
|
||||
.link_status_changed = vmxnet3_set_link_status,
|
||||
|
@ -269,7 +269,7 @@ static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static NetClientInfo net_xen_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = net_rx_packet,
|
||||
};
|
||||
|
@ -371,7 +371,7 @@ out:
|
||||
}
|
||||
|
||||
static NetClientInfo net_xgmac_enet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = eth_rx,
|
||||
};
|
||||
|
@ -935,7 +935,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
|
||||
}
|
||||
|
||||
static NetClientInfo net_xilinx_enet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = eth_rx,
|
||||
};
|
||||
|
@ -217,7 +217,7 @@ static void xilinx_ethlite_reset(DeviceState *dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_xilinx_ethlite_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = eth_can_rx,
|
||||
.receive = eth_rx,
|
||||
|
@ -1334,7 +1334,7 @@ static void usb_net_handle_destroy(USBDevice *dev)
|
||||
}
|
||||
|
||||
static NetClientInfo net_usbnet_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.type = NET_CLIENT_DRIVER_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.receive = usbnet_receive,
|
||||
.cleanup = usbnet_cleanup,
|
||||
@ -1396,7 +1396,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
|
||||
qemu_opt_set(opts, "type", "nic", &error_abort);
|
||||
qemu_opt_set(opts, "model", "usb", &error_abort);
|
||||
|
||||
idx = net_client_init(opts, 0, &local_err);
|
||||
idx = net_client_init(opts, false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return NULL;
|
||||
|
@ -66,7 +66,7 @@ typedef struct SocketReadState SocketReadState;
|
||||
typedef void (SocketReadStateFinalize)(SocketReadState *rs);
|
||||
|
||||
typedef struct NetClientInfo {
|
||||
NetClientOptionsKind type;
|
||||
NetClientDriver type;
|
||||
size_t size;
|
||||
NetReceive *receive;
|
||||
NetReceive *receive_raw;
|
||||
@ -122,7 +122,7 @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size);
|
||||
char *qemu_mac_strdup_printf(const uint8_t *macaddr);
|
||||
NetClientState *qemu_find_netdev(const char *id);
|
||||
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
|
||||
NetClientOptionsKind type, int max);
|
||||
NetClientDriver type, int max);
|
||||
NetClientState *qemu_new_net_client(NetClientInfo *info,
|
||||
NetClientState *peer,
|
||||
const char *model,
|
||||
@ -203,7 +203,7 @@ extern const char *host_net_devices[];
|
||||
extern const char *legacy_tftp_prefix;
|
||||
extern const char *legacy_bootp_filename;
|
||||
|
||||
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp);
|
||||
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp);
|
||||
int net_client_parse(QemuOptsList *opts_list, const char *str);
|
||||
int net_init_clients(void);
|
||||
void net_check_clients(void);
|
||||
|
14
monitor.c
14
monitor.c
@ -3080,8 +3080,8 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; NetClientOptionsKind_lookup[i]; i++) {
|
||||
add_completion_option(rs, str, NetClientOptionsKind_lookup[i]);
|
||||
for (i = 0; NetClientDriver_lookup[i]; i++) {
|
||||
add_completion_option(rs, str, NetClientDriver_lookup[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3281,7 +3281,7 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||
int count, i;
|
||||
count = qemu_find_net_clients_except(NULL, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NONE,
|
||||
NET_CLIENT_DRIVER_NONE,
|
||||
MAX_QUEUE_NUM);
|
||||
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||
const char *name = ncs[i]->name;
|
||||
@ -3306,7 +3306,7 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||
QemuOpts *opts;
|
||||
@ -3435,7 +3435,7 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
readline_set_completion_index(rs, len);
|
||||
if (nb_args == 2) {
|
||||
count = qemu_find_net_clients_except(NULL, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NONE,
|
||||
NET_CLIENT_DRIVER_NONE,
|
||||
MAX_QUEUE_NUM);
|
||||
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||
int id;
|
||||
@ -3452,13 +3452,13 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
return;
|
||||
} else if (nb_args == 3) {
|
||||
count = qemu_find_net_clients_except(NULL, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||
int id;
|
||||
const char *name;
|
||||
|
||||
if (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT ||
|
||||
if (ncs[i]->info->type == NET_CLIENT_DRIVER_HUBPORT ||
|
||||
net_hub_id_for_client(ncs[i], &id)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -27,39 +27,39 @@
|
||||
#include "net/net.h"
|
||||
#include "qapi-types.h"
|
||||
|
||||
int net_init_dump(const NetClientOptions *opts, const char *name,
|
||||
int net_init_dump(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
#ifdef CONFIG_SLIRP
|
||||
int net_init_slirp(const NetClientOptions *opts, const char *name,
|
||||
int net_init_slirp(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
#endif
|
||||
|
||||
int net_init_hubport(const NetClientOptions *opts, const char *name,
|
||||
int net_init_hubport(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
int net_init_socket(const NetClientOptions *opts, const char *name,
|
||||
int net_init_socket(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
int net_init_tap(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
int net_init_bridge(const NetClientOptions *opts, const char *name,
|
||||
int net_init_bridge(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
int net_init_l2tpv3(const NetClientOptions *opts, const char *name,
|
||||
int net_init_l2tpv3(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
#ifdef CONFIG_VDE
|
||||
int net_init_vde(const NetClientOptions *opts, const char *name,
|
||||
int net_init_vde(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETMAP
|
||||
int net_init_netmap(const NetClientOptions *opts, const char *name,
|
||||
int net_init_netmap(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
#endif
|
||||
|
||||
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
|
||||
int net_init_vhost_user(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
#endif /* QEMU_NET_CLIENTS_H */
|
||||
|
@ -172,14 +172,14 @@ static void dumpclient_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_dump_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_DUMP,
|
||||
.type = NET_CLIENT_DRIVER_DUMP,
|
||||
.size = sizeof(DumpNetClient),
|
||||
.receive = dumpclient_receive,
|
||||
.receive_iov = dumpclient_receive_iov,
|
||||
.cleanup = dumpclient_cleanup,
|
||||
};
|
||||
|
||||
int net_init_dump(const NetClientOptions *opts, const char *name,
|
||||
int net_init_dump(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
int len, rc;
|
||||
@ -189,8 +189,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
|
||||
NetClientState *nc;
|
||||
DumpNetClient *dnc;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_DUMP);
|
||||
dump = opts->u.dump.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
|
||||
dump = &netdev->u.dump;
|
||||
|
||||
assert(peer);
|
||||
|
||||
|
@ -201,7 +201,7 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
|
||||
}
|
||||
|
||||
queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
if (queues < 1) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
|
||||
|
24
net/hub.c
24
net/hub.c
@ -131,7 +131,7 @@ static void net_hub_port_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_hub_port_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_HUBPORT,
|
||||
.type = NET_CLIENT_DRIVER_HUBPORT,
|
||||
.size = sizeof(NetHubPort),
|
||||
.can_receive = net_hub_port_can_receive,
|
||||
.receive = net_hub_port_receive,
|
||||
@ -266,10 +266,10 @@ int net_hub_id_for_client(NetClientState *nc, int *id)
|
||||
{
|
||||
NetHubPort *port;
|
||||
|
||||
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_HUBPORT) {
|
||||
port = DO_UPCAST(NetHubPort, nc, nc);
|
||||
} else if (nc->peer != NULL && nc->peer->info->type ==
|
||||
NET_CLIENT_OPTIONS_KIND_HUBPORT) {
|
||||
NET_CLIENT_DRIVER_HUBPORT) {
|
||||
port = DO_UPCAST(NetHubPort, nc, nc->peer);
|
||||
} else {
|
||||
return -ENOENT;
|
||||
@ -281,14 +281,14 @@ int net_hub_id_for_client(NetClientState *nc, int *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init_hubport(const NetClientOptions *opts, const char *name,
|
||||
int net_init_hubport(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
const NetdevHubPortOptions *hubport;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT);
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
|
||||
assert(!peer);
|
||||
hubport = opts->u.hubport.data;
|
||||
hubport = &netdev->u.hubport;
|
||||
|
||||
net_hub_add_port(hubport->hubid, name);
|
||||
return 0;
|
||||
@ -315,14 +315,14 @@ void net_hub_check_clients(void)
|
||||
}
|
||||
|
||||
switch (peer->info->type) {
|
||||
case NET_CLIENT_OPTIONS_KIND_NIC:
|
||||
case NET_CLIENT_DRIVER_NIC:
|
||||
has_nic = 1;
|
||||
break;
|
||||
case NET_CLIENT_OPTIONS_KIND_USER:
|
||||
case NET_CLIENT_OPTIONS_KIND_TAP:
|
||||
case NET_CLIENT_OPTIONS_KIND_SOCKET:
|
||||
case NET_CLIENT_OPTIONS_KIND_VDE:
|
||||
case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
|
||||
case NET_CLIENT_DRIVER_USER:
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
case NET_CLIENT_DRIVER_SOCKET:
|
||||
case NET_CLIENT_DRIVER_VDE:
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
has_host_dev = 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -516,7 +516,7 @@ static void net_l2tpv3_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_l2tpv3_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_L2TPV3,
|
||||
.type = NET_CLIENT_DRIVER_L2TPV3,
|
||||
.size = sizeof(NetL2TPV3State),
|
||||
.receive = net_l2tpv3_receive_dgram,
|
||||
.receive_iov = net_l2tpv3_receive_dgram_iov,
|
||||
@ -524,7 +524,7 @@ static NetClientInfo net_l2tpv3_info = {
|
||||
.cleanup = net_l2tpv3_cleanup,
|
||||
};
|
||||
|
||||
int net_init_l2tpv3(const NetClientOptions *opts,
|
||||
int net_init_l2tpv3(const Netdev *netdev,
|
||||
const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
@ -545,8 +545,8 @@ int net_init_l2tpv3(const NetClientOptions *opts,
|
||||
s->queue_tail = 0;
|
||||
s->header_mismatch = false;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3);
|
||||
l2tpv3 = opts->u.l2tpv3.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_L2TPV3);
|
||||
l2tpv3 = &netdev->u.l2tpv3;
|
||||
|
||||
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
|
||||
s->ipv6 = l2tpv3->ipv6;
|
||||
|
155
net/net.c
155
net/net.c
@ -289,7 +289,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
|
||||
NICState *nic;
|
||||
int i, queues = MAX(1, conf->peers.queues);
|
||||
|
||||
assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
|
||||
assert(info->type == NET_CLIENT_DRIVER_NIC);
|
||||
assert(info->size >= sizeof(NICState));
|
||||
|
||||
nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
|
||||
@ -360,13 +360,13 @@ void qemu_del_net_client(NetClientState *nc)
|
||||
int queues, i;
|
||||
NetFilterState *nf, *next;
|
||||
|
||||
assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
|
||||
assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
|
||||
|
||||
/* If the NetClientState belongs to a multiqueue backend, we will change all
|
||||
* other NetClientStates also.
|
||||
*/
|
||||
queues = qemu_find_net_clients_except(nc->name, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
assert(queues != 0);
|
||||
|
||||
@ -375,7 +375,7 @@ void qemu_del_net_client(NetClientState *nc)
|
||||
}
|
||||
|
||||
/* If there is a peer NIC, delete and cleanup client, but do not free. */
|
||||
if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
|
||||
NICState *nic = qemu_get_nic(nc->peer);
|
||||
if (nic->peer_deleted) {
|
||||
return;
|
||||
@ -431,7 +431,7 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
|
||||
NetClientState *nc;
|
||||
|
||||
QTAILQ_FOREACH(nc, &net_clients, next) {
|
||||
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
|
||||
if (nc->queue_index == 0) {
|
||||
func(qemu_get_nic(nc), opaque);
|
||||
}
|
||||
@ -603,7 +603,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
|
||||
{
|
||||
nc->receive_disabled = 0;
|
||||
|
||||
if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
|
||||
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
|
||||
if (net_hub_flush(nc->peer)) {
|
||||
qemu_notify_event();
|
||||
}
|
||||
@ -777,7 +777,7 @@ NetClientState *qemu_find_netdev(const char *id)
|
||||
NetClientState *nc;
|
||||
|
||||
QTAILQ_FOREACH(nc, &net_clients, next) {
|
||||
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_NIC)
|
||||
continue;
|
||||
if (!strcmp(nc->name, id)) {
|
||||
return nc;
|
||||
@ -788,7 +788,7 @@ NetClientState *qemu_find_netdev(const char *id)
|
||||
}
|
||||
|
||||
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
|
||||
NetClientOptionsKind type, int max)
|
||||
NetClientDriver type, int max)
|
||||
{
|
||||
NetClientState *nc;
|
||||
int ret = 0;
|
||||
@ -862,15 +862,15 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int net_init_nic(const NetClientOptions *opts, const char *name,
|
||||
static int net_init_nic(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
int idx;
|
||||
NICInfo *nd;
|
||||
const NetLegacyNicOptions *nic;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
|
||||
nic = opts->u.nic.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_NIC);
|
||||
nic = &netdev->u.nic;
|
||||
|
||||
idx = nic_get_free_idx();
|
||||
if (idx == -1 || nb_nics >= MAX_NICS) {
|
||||
@ -930,70 +930,111 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
|
||||
}
|
||||
|
||||
|
||||
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND__MAX])(
|
||||
const NetClientOptions *opts,
|
||||
static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
|
||||
const Netdev *netdev,
|
||||
const char *name,
|
||||
NetClientState *peer, Error **errp) = {
|
||||
[NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic,
|
||||
[NET_CLIENT_DRIVER_NIC] = net_init_nic,
|
||||
#ifdef CONFIG_SLIRP
|
||||
[NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp,
|
||||
[NET_CLIENT_DRIVER_USER] = net_init_slirp,
|
||||
#endif
|
||||
[NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap,
|
||||
[NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket,
|
||||
[NET_CLIENT_DRIVER_TAP] = net_init_tap,
|
||||
[NET_CLIENT_DRIVER_SOCKET] = net_init_socket,
|
||||
#ifdef CONFIG_VDE
|
||||
[NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde,
|
||||
[NET_CLIENT_DRIVER_VDE] = net_init_vde,
|
||||
#endif
|
||||
#ifdef CONFIG_NETMAP
|
||||
[NET_CLIENT_OPTIONS_KIND_NETMAP] = net_init_netmap,
|
||||
[NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
|
||||
#endif
|
||||
[NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump,
|
||||
[NET_CLIENT_DRIVER_DUMP] = net_init_dump,
|
||||
#ifdef CONFIG_NET_BRIDGE
|
||||
[NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge,
|
||||
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
|
||||
#endif
|
||||
[NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport,
|
||||
[NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
|
||||
#ifdef CONFIG_VHOST_NET_USED
|
||||
[NET_CLIENT_OPTIONS_KIND_VHOST_USER] = net_init_vhost_user,
|
||||
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
|
||||
#endif
|
||||
#ifdef CONFIG_L2TPV3
|
||||
[NET_CLIENT_OPTIONS_KIND_L2TPV3] = net_init_l2tpv3,
|
||||
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static int net_client_init1(const void *object, int is_netdev, Error **errp)
|
||||
static int net_client_init1(const void *object, bool is_netdev, Error **errp)
|
||||
{
|
||||
const NetClientOptions *opts;
|
||||
Netdev legacy = {0};
|
||||
const Netdev *netdev;
|
||||
const char *name;
|
||||
NetClientState *peer = NULL;
|
||||
|
||||
if (is_netdev) {
|
||||
const Netdev *netdev = object;
|
||||
opts = netdev->opts;
|
||||
netdev = object;
|
||||
name = netdev->id;
|
||||
|
||||
if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP ||
|
||||
opts->type == NET_CLIENT_OPTIONS_KIND_NIC ||
|
||||
!net_client_init_fun[opts->type]) {
|
||||
if (netdev->type == NET_CLIENT_DRIVER_DUMP ||
|
||||
netdev->type == NET_CLIENT_DRIVER_NIC ||
|
||||
!net_client_init_fun[netdev->type]) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
|
||||
"a netdev backend type");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
const NetLegacy *net = object;
|
||||
opts = net->opts;
|
||||
const NetLegacyOptions *opts = net->opts;
|
||||
legacy.id = net->id;
|
||||
netdev = &legacy;
|
||||
/* missing optional values have been initialized to "all bits zero" */
|
||||
name = net->has_id ? net->id : net->name;
|
||||
|
||||
if (opts->type == NET_CLIENT_OPTIONS_KIND_NONE) {
|
||||
/* Map the old options to the new flat type */
|
||||
switch (opts->type) {
|
||||
case NET_LEGACY_OPTIONS_KIND_NONE:
|
||||
return 0; /* nothing to do */
|
||||
}
|
||||
if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
|
||||
"a net type");
|
||||
return -1;
|
||||
case NET_LEGACY_OPTIONS_KIND_NIC:
|
||||
legacy.type = NET_CLIENT_DRIVER_NIC;
|
||||
legacy.u.nic = *opts->u.nic.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_USER:
|
||||
legacy.type = NET_CLIENT_DRIVER_USER;
|
||||
legacy.u.user = *opts->u.user.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_TAP:
|
||||
legacy.type = NET_CLIENT_DRIVER_TAP;
|
||||
legacy.u.tap = *opts->u.tap.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_L2TPV3:
|
||||
legacy.type = NET_CLIENT_DRIVER_L2TPV3;
|
||||
legacy.u.l2tpv3 = *opts->u.l2tpv3.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_SOCKET:
|
||||
legacy.type = NET_CLIENT_DRIVER_SOCKET;
|
||||
legacy.u.socket = *opts->u.socket.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_VDE:
|
||||
legacy.type = NET_CLIENT_DRIVER_VDE;
|
||||
legacy.u.vde = *opts->u.vde.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_DUMP:
|
||||
legacy.type = NET_CLIENT_DRIVER_DUMP;
|
||||
legacy.u.dump = *opts->u.dump.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_BRIDGE:
|
||||
legacy.type = NET_CLIENT_DRIVER_BRIDGE;
|
||||
legacy.u.bridge = *opts->u.bridge.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_NETMAP:
|
||||
legacy.type = NET_CLIENT_DRIVER_NETMAP;
|
||||
legacy.u.netmap = *opts->u.netmap.data;
|
||||
break;
|
||||
case NET_LEGACY_OPTIONS_KIND_VHOST_USER:
|
||||
legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
|
||||
legacy.u.vhost_user = *opts->u.vhost_user.data;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!net_client_init_fun[opts->type]) {
|
||||
if (!net_client_init_fun[netdev->type]) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
|
||||
"a net backend type (maybe it is not compiled "
|
||||
"into this binary)");
|
||||
@ -1001,17 +1042,17 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
|
||||
}
|
||||
|
||||
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
|
||||
if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC ||
|
||||
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
|
||||
!opts->u.nic.data->has_netdev) {
|
||||
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (net_client_init_fun[opts->type](opts, name, peer, errp) < 0) {
|
||||
if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
|
||||
/* FIXME drop when all init functions store an Error */
|
||||
if (errp && !*errp) {
|
||||
error_setg(errp, QERR_DEVICE_INIT_FAILED,
|
||||
NetClientOptionsKind_lookup[opts->type]);
|
||||
NetClientDriver_lookup[netdev->type]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1019,7 +1060,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
|
||||
}
|
||||
|
||||
|
||||
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
|
||||
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
|
||||
{
|
||||
void *object = NULL;
|
||||
Error *err = NULL;
|
||||
@ -1112,7 +1153,7 @@ void hmp_host_net_add(Monitor *mon, const QDict *qdict)
|
||||
|
||||
qemu_opt_set(opts, "type", device, &error_abort);
|
||||
|
||||
net_client_init(opts, 0, &local_err);
|
||||
net_client_init(opts, false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
monitor_printf(mon, "adding host network device %s failed\n", device);
|
||||
@ -1131,7 +1172,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
|
||||
device, vlan_id);
|
||||
return;
|
||||
}
|
||||
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
|
||||
error_report("invalid host network device '%s'", device);
|
||||
return;
|
||||
}
|
||||
@ -1142,7 +1183,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
|
||||
|
||||
void netdev_add(QemuOpts *opts, Error **errp)
|
||||
{
|
||||
net_client_init(opts, 1, errp);
|
||||
net_client_init(opts, true, errp);
|
||||
}
|
||||
|
||||
void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp)
|
||||
@ -1222,7 +1263,7 @@ void print_net_client(Monitor *mon, NetClientState *nc)
|
||||
|
||||
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
|
||||
nc->queue_index,
|
||||
NetClientOptionsKind_lookup[nc->info->type],
|
||||
NetClientDriver_lookup[nc->info->type],
|
||||
nc->info_str);
|
||||
if (!QTAILQ_EMPTY(&nc->filters)) {
|
||||
monitor_printf(mon, "filters:\n");
|
||||
@ -1252,7 +1293,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
|
||||
}
|
||||
|
||||
/* only query rx-filter information of NIC */
|
||||
if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
|
||||
if (has_name) {
|
||||
error_setg(errp, "net client(%s) isn't a NIC", name);
|
||||
return NULL;
|
||||
@ -1298,7 +1339,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
|
||||
void hmp_info_network(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
NetClientState *nc, *peer;
|
||||
NetClientOptionsKind type;
|
||||
NetClientDriver type;
|
||||
|
||||
net_hub_info(mon);
|
||||
|
||||
@ -1311,10 +1352,10 @@ void hmp_info_network(Monitor *mon, const QDict *qdict)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (!peer || type == NET_CLIENT_DRIVER_NIC) {
|
||||
print_net_client(mon, nc);
|
||||
} /* else it's a netdev connected to a NIC, printed with the NIC */
|
||||
if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (peer && type == NET_CLIENT_DRIVER_NIC) {
|
||||
monitor_printf(mon, " \\ ");
|
||||
print_net_client(mon, peer);
|
||||
}
|
||||
@ -1328,7 +1369,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
|
||||
int queues, i;
|
||||
|
||||
queues = qemu_find_net_clients_except(name, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND__MAX,
|
||||
NET_CLIENT_DRIVER__MAX,
|
||||
MAX_QUEUE_NUM);
|
||||
|
||||
if (queues == 0) {
|
||||
@ -1355,7 +1396,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
|
||||
* multiple clients that can still communicate with each other in
|
||||
* disconnected mode. For now maintain this compatibility.
|
||||
*/
|
||||
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
|
||||
for (i = 0; i < queues; i++) {
|
||||
ncs[i]->peer->link_down = !up;
|
||||
}
|
||||
@ -1396,7 +1437,7 @@ void net_cleanup(void)
|
||||
*/
|
||||
while (!QTAILQ_EMPTY(&net_clients)) {
|
||||
nc = QTAILQ_FIRST(&net_clients);
|
||||
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
|
||||
qemu_del_nic(qemu_get_nic(nc));
|
||||
} else {
|
||||
qemu_del_net_client(nc);
|
||||
@ -1416,7 +1457,7 @@ void net_check_clients(void)
|
||||
QTAILQ_FOREACH(nc, &net_clients, next) {
|
||||
if (!nc->peer) {
|
||||
fprintf(stderr, "Warning: %s %s has no peer\n",
|
||||
nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
|
||||
nc->info->type == NET_CLIENT_DRIVER_NIC ?
|
||||
"nic" : "netdev", nc->name);
|
||||
}
|
||||
}
|
||||
@ -1440,7 +1481,7 @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
net_client_init(opts, 0, &local_err);
|
||||
net_client_init(opts, false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
@ -1454,7 +1495,7 @@ static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = net_client_init(opts, 1, &local_err);
|
||||
ret = net_client_init(opts, true, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
|
@ -400,7 +400,7 @@ static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
|
||||
/* NetClientInfo methods */
|
||||
static NetClientInfo net_netmap_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NETMAP,
|
||||
.type = NET_CLIENT_DRIVER_NETMAP,
|
||||
.size = sizeof(NetmapState),
|
||||
.receive = netmap_receive,
|
||||
.receive_iov = netmap_receive_iov,
|
||||
@ -418,10 +418,10 @@ static NetClientInfo net_netmap_info = {
|
||||
*
|
||||
* ... -net netmap,ifname="..."
|
||||
*/
|
||||
int net_init_netmap(const NetClientOptions *opts,
|
||||
int net_init_netmap(const Netdev *netdev,
|
||||
const char *name, NetClientState *peer, Error **errp)
|
||||
{
|
||||
const NetdevNetmapOptions *netmap_opts = opts->u.netmap.data;
|
||||
const NetdevNetmapOptions *netmap_opts = &netdev->u.netmap;
|
||||
struct nm_desc *nmd;
|
||||
NetClientState *nc;
|
||||
Error *err = NULL;
|
||||
|
@ -137,7 +137,7 @@ static void net_slirp_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_slirp_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_USER,
|
||||
.type = NET_CLIENT_DRIVER_USER,
|
||||
.size = sizeof(SlirpState),
|
||||
.receive = net_slirp_receive,
|
||||
.cleanup = net_slirp_cleanup,
|
||||
@ -828,7 +828,7 @@ static const char **slirp_dnssearch(const StringList *dnsname)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int net_init_slirp(const NetClientOptions *opts, const char *name,
|
||||
int net_init_slirp(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
/* FIXME error_setg(errp, ...) on failure */
|
||||
@ -839,8 +839,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
|
||||
const char **dnssearch;
|
||||
bool ipv4 = true, ipv6 = true;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER);
|
||||
user = opts->u.user.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_USER);
|
||||
user = &netdev->u.user;
|
||||
|
||||
if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
|
||||
(user->has_ipv4 && !user->ipv4)) {
|
||||
|
10
net/socket.c
10
net/socket.c
@ -311,7 +311,7 @@ static void net_socket_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_dgram_socket_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_SOCKET,
|
||||
.type = NET_CLIENT_DRIVER_SOCKET,
|
||||
.size = sizeof(NetSocketState),
|
||||
.receive = net_socket_receive_dgram,
|
||||
.cleanup = net_socket_cleanup,
|
||||
@ -395,7 +395,7 @@ static void net_socket_connect(void *opaque)
|
||||
}
|
||||
|
||||
static NetClientInfo net_socket_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_SOCKET,
|
||||
.type = NET_CLIENT_DRIVER_SOCKET,
|
||||
.size = sizeof(NetSocketState),
|
||||
.receive = net_socket_receive,
|
||||
.cleanup = net_socket_cleanup,
|
||||
@ -663,15 +663,15 @@ static int net_socket_udp_init(NetClientState *peer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init_socket(const NetClientOptions *opts, const char *name,
|
||||
int net_init_socket(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
/* FIXME error_setg(errp, ...) on failure */
|
||||
Error *err = NULL;
|
||||
const NetdevSocketOptions *sock;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET);
|
||||
sock = opts->u.socket.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
|
||||
sock = &netdev->u.socket;
|
||||
|
||||
if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
|
||||
sock->has_udp != 1) {
|
||||
|
@ -750,7 +750,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
}
|
||||
|
||||
static NetClientInfo net_tap_win32_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_TAP,
|
||||
.type = NET_CLIENT_DRIVER_TAP,
|
||||
.size = sizeof(TAPState),
|
||||
.receive = tap_receive,
|
||||
.cleanup = tap_cleanup,
|
||||
@ -788,14 +788,14 @@ static int tap_win32_init(NetClientState *peer, const char *model,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
int net_init_tap(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
/* FIXME error_setg(errp, ...) on failure */
|
||||
const NetdevTapOptions *tap;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
tap = opts->u.tap.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
|
||||
tap = &netdev->u.tap;
|
||||
|
||||
if (!tap->has_ifname) {
|
||||
error_report("tap: no interface name");
|
||||
|
28
net/tap.c
28
net/tap.c
@ -223,7 +223,7 @@ static bool tap_has_ufo(NetClientState *nc)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
|
||||
return s->has_ufo;
|
||||
}
|
||||
@ -232,7 +232,7 @@ static bool tap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
|
||||
return !!s->host_vnet_hdr_len;
|
||||
}
|
||||
@ -241,7 +241,7 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
|
||||
return !!tap_probe_vnet_hdr_len(s->fd, len);
|
||||
}
|
||||
@ -250,7 +250,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
|
||||
len == sizeof(struct virtio_net_hdr));
|
||||
|
||||
@ -262,7 +262,7 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
|
||||
|
||||
s->using_vnet_hdr = using_vnet_hdr;
|
||||
@ -336,14 +336,14 @@ static void tap_poll(NetClientState *nc, bool enable)
|
||||
int tap_get_fd(NetClientState *nc)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
return s->fd;
|
||||
}
|
||||
|
||||
/* fd support */
|
||||
|
||||
static NetClientInfo net_tap_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_TAP,
|
||||
.type = NET_CLIENT_DRIVER_TAP,
|
||||
.size = sizeof(TAPState),
|
||||
.receive = tap_receive,
|
||||
.receive_raw = tap_receive_raw,
|
||||
@ -571,7 +571,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge,
|
||||
}
|
||||
}
|
||||
|
||||
int net_init_bridge(const NetClientOptions *opts, const char *name,
|
||||
int net_init_bridge(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
const NetdevBridgeOptions *bridge;
|
||||
@ -579,8 +579,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
|
||||
TAPState *s;
|
||||
int fd, vnet_hdr;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
|
||||
bridge = opts->u.bridge.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
|
||||
bridge = &netdev->u.bridge;
|
||||
|
||||
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
|
||||
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
|
||||
@ -735,7 +735,7 @@ static int get_fds(char *str, char *fds[], int max)
|
||||
return i;
|
||||
}
|
||||
|
||||
int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
int net_init_tap(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
const NetdevTapOptions *tap;
|
||||
@ -747,8 +747,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
const char *vhostfdname;
|
||||
char ifname[128];
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
tap = opts->u.tap.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
|
||||
tap = &netdev->u.tap;
|
||||
queues = tap->has_queues ? tap->queues : 1;
|
||||
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
|
||||
|
||||
@ -921,7 +921,7 @@ free_fail:
|
||||
VHostNetState *tap_get_vhost_net(NetClientState *nc)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
|
||||
return s->vhost_net;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ static void vde_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
static NetClientInfo net_vde_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_VDE,
|
||||
.type = NET_CLIENT_DRIVER_VDE,
|
||||
.size = sizeof(VDEState),
|
||||
.receive = vde_receive,
|
||||
.cleanup = vde_cleanup,
|
||||
@ -109,14 +109,14 @@ static int net_vde_init(NetClientState *peer, const char *model,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init_vde(const NetClientOptions *opts, const char *name,
|
||||
int net_init_vde(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
/* FIXME error_setg(errp, ...) on failure */
|
||||
const NetdevVdeOptions *vde;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VDE);
|
||||
vde = opts->u.vde.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_VDE);
|
||||
vde = &netdev->u.vde;
|
||||
|
||||
/* missing optional values have been initialized to "all bits zero" */
|
||||
if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group,
|
||||
|
@ -34,14 +34,14 @@ typedef struct VhostUserChardevProps {
|
||||
VHostNetState *vhost_user_get_vhost_net(NetClientState *nc)
|
||||
{
|
||||
VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
return s->vhost_net;
|
||||
}
|
||||
|
||||
uint64_t vhost_user_get_acked_features(NetClientState *nc)
|
||||
{
|
||||
VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
return s->acked_features;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
|
||||
int i;
|
||||
|
||||
for (i = 0; i < queues; i++) {
|
||||
assert (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(ncs[i]->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
|
||||
s = DO_UPCAST(VhostUserState, nc, ncs[i]);
|
||||
if (!vhost_user_running(s)) {
|
||||
@ -82,7 +82,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
|
||||
options.backend_type = VHOST_BACKEND_TYPE_USER;
|
||||
|
||||
for (i = 0; i < queues; i++) {
|
||||
assert (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(ncs[i]->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
|
||||
s = DO_UPCAST(VhostUserState, nc, ncs[i]);
|
||||
if (vhost_user_running(s)) {
|
||||
@ -163,20 +163,20 @@ static void vhost_user_cleanup(NetClientState *nc)
|
||||
|
||||
static bool vhost_user_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vhost_user_has_ufo(NetClientState *nc)
|
||||
{
|
||||
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static NetClientInfo net_vhost_user_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_VHOST_USER,
|
||||
.type = NET_CLIENT_DRIVER_VHOST_USER,
|
||||
.size = sizeof(VhostUserState),
|
||||
.receive = vhost_user_receive,
|
||||
.cleanup = vhost_user_cleanup,
|
||||
@ -207,7 +207,7 @@ static void net_vhost_user_event(void *opaque, int event)
|
||||
int queues;
|
||||
|
||||
queues = qemu_find_net_clients_except(name, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
NET_CLIENT_DRIVER_NIC,
|
||||
MAX_QUEUE_NUM);
|
||||
assert(queues < MAX_QUEUE_NUM);
|
||||
|
||||
@ -334,15 +334,15 @@ static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
|
||||
int net_init_vhost_user(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
int queues;
|
||||
const NetdevVhostUserOptions *vhost_user_opts;
|
||||
CharDriverState *chr;
|
||||
|
||||
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
|
||||
vhost_user_opts = opts->u.vhost_user.data;
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
vhost_user_opts = &netdev->u.vhost_user;
|
||||
|
||||
chr = net_vhost_parse_chardev(vhost_user_opts, errp);
|
||||
if (!chr) {
|
||||
|
@ -2809,16 +2809,32 @@
|
||||
'*queues': 'int' } }
|
||||
|
||||
##
|
||||
# @NetClientOptions
|
||||
# @NetClientDriver
|
||||
#
|
||||
# A discriminated record of network device traits.
|
||||
# Available netdev drivers.
|
||||
#
|
||||
# Since 2.7
|
||||
##
|
||||
{ 'enum': 'NetClientDriver',
|
||||
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump',
|
||||
'bridge', 'hubport', 'netmap', 'vhost-user' ] }
|
||||
|
||||
##
|
||||
# @Netdev
|
||||
#
|
||||
# Captures the configuration of a network device.
|
||||
#
|
||||
# @id: identifier for monitor commands.
|
||||
#
|
||||
# @type: Specify the driver used for interpreting remaining arguments.
|
||||
#
|
||||
# Since 1.2
|
||||
#
|
||||
# 'l2tpv3' - since 2.1
|
||||
#
|
||||
##
|
||||
{ 'union': 'NetClientOptions',
|
||||
{ 'union': 'Netdev',
|
||||
'base': { 'id': 'str', 'type': 'NetClientDriver' },
|
||||
'discriminator': 'type',
|
||||
'data': {
|
||||
'none': 'NetdevNoneOptions',
|
||||
'nic': 'NetLegacyNicOptions',
|
||||
@ -2853,23 +2869,28 @@
|
||||
'*vlan': 'int32',
|
||||
'*id': 'str',
|
||||
'*name': 'str',
|
||||
'opts': 'NetClientOptions' } }
|
||||
'opts': 'NetLegacyOptions' } }
|
||||
|
||||
##
|
||||
# @Netdev
|
||||
# @NetLegacyOptions
|
||||
#
|
||||
# Captures the configuration of a network device.
|
||||
#
|
||||
# @id: identifier for monitor commands.
|
||||
#
|
||||
# @opts: device type specific properties
|
||||
# Like Netdev, but for use only by the legacy command line options
|
||||
#
|
||||
# Since 1.2
|
||||
##
|
||||
{ 'struct': 'Netdev',
|
||||
{ 'union': 'NetLegacyOptions',
|
||||
'data': {
|
||||
'id': 'str',
|
||||
'opts': 'NetClientOptions' } }
|
||||
'none': 'NetdevNoneOptions',
|
||||
'nic': 'NetLegacyNicOptions',
|
||||
'user': 'NetdevUserOptions',
|
||||
'tap': 'NetdevTapOptions',
|
||||
'l2tpv3': 'NetdevL2TPv3Options',
|
||||
'socket': 'NetdevSocketOptions',
|
||||
'vde': 'NetdevVdeOptions',
|
||||
'dump': 'NetdevDumpOptions',
|
||||
'bridge': 'NetdevBridgeOptions',
|
||||
'netmap': 'NetdevNetmapOptions',
|
||||
'vhost-user': 'NetdevVhostUserOptions' } }
|
||||
|
||||
##
|
||||
# @NetFilterDirection
|
||||
|
@ -1120,6 +1120,21 @@
|
||||
#
|
||||
# Start mirroring a block device's writes to a new destination.
|
||||
#
|
||||
# See DriveMirror for parameter descriptions
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
#
|
||||
# Since 1.3
|
||||
##
|
||||
{ 'command': 'drive-mirror', 'boxed': true,
|
||||
'data': 'DriveMirror' }
|
||||
|
||||
##
|
||||
# DriveMirror
|
||||
#
|
||||
# A set of parameters describing drive mirror setup.
|
||||
#
|
||||
# @job-id: #optional identifier for the newly-created block job. If
|
||||
# omitted, the device name will be used. (Since 2.7)
|
||||
#
|
||||
@ -1169,12 +1184,9 @@
|
||||
# written. Both will result in identical contents.
|
||||
# Default is true. (Since 2.4)
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
#
|
||||
# Since 1.3
|
||||
##
|
||||
{ 'command': 'drive-mirror',
|
||||
{ 'struct': 'DriveMirror',
|
||||
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
|
||||
'*format': 'str', '*node-name': 'str', '*replaces': 'str',
|
||||
'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
|
||||
@ -1330,6 +1342,21 @@
|
||||
# the device will be removed from its group and the rest of its
|
||||
# members will not be affected. The 'group' parameter is ignored.
|
||||
#
|
||||
# See BlockIOThrottle for parameter descriptions.
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'block_set_io_throttle', 'boxed': true,
|
||||
'data': 'BlockIOThrottle' }
|
||||
|
||||
##
|
||||
# BlockIOThrottle
|
||||
#
|
||||
# A set of parameters describing block throttling.
|
||||
#
|
||||
# @device: The name of the device
|
||||
#
|
||||
# @bps: total throughput limit in bytes per second
|
||||
@ -1396,12 +1423,9 @@
|
||||
#
|
||||
# @group: #optional throttle group name (Since 2.4)
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'block_set_io_throttle',
|
||||
{ 'struct': 'BlockIOThrottle',
|
||||
'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
|
||||
'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
|
||||
'*bps_max': 'int', '*bps_rd_max': 'int',
|
||||
|
@ -30,6 +30,8 @@ typedef struct StackObject
|
||||
|
||||
GHashTable *h; /* If obj is dict: unvisited keys */
|
||||
const QListEntry *entry; /* If obj is list: unvisited tail */
|
||||
|
||||
QSLIST_ENTRY(StackObject) node;
|
||||
} StackObject;
|
||||
|
||||
struct QmpInputVisitor
|
||||
@ -41,8 +43,7 @@ struct QmpInputVisitor
|
||||
|
||||
/* Stack of objects being visited (all entries will be either
|
||||
* QDict or QList). */
|
||||
StackObject stack[QIV_STACK_SIZE];
|
||||
int nb_stack;
|
||||
QSLIST_HEAD(, StackObject) stack;
|
||||
|
||||
/* True to reject parse in visit_end_struct() if unvisited keys remain. */
|
||||
bool strict;
|
||||
@ -61,13 +62,13 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
|
||||
QObject *qobj;
|
||||
QObject *ret;
|
||||
|
||||
if (!qiv->nb_stack) {
|
||||
if (QSLIST_EMPTY(&qiv->stack)) {
|
||||
/* Starting at root, name is ignored. */
|
||||
return qiv->root;
|
||||
}
|
||||
|
||||
/* We are in a container; find the next element. */
|
||||
tos = &qiv->stack[qiv->nb_stack - 1];
|
||||
tos = QSLIST_FIRST(&qiv->stack);
|
||||
qobj = tos->obj;
|
||||
assert(qobj);
|
||||
|
||||
@ -100,18 +101,11 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
|
||||
void *qapi, Error **errp)
|
||||
{
|
||||
GHashTable *h;
|
||||
StackObject *tos = &qiv->stack[qiv->nb_stack];
|
||||
StackObject *tos = g_new0(StackObject, 1);
|
||||
|
||||
assert(obj);
|
||||
if (qiv->nb_stack >= QIV_STACK_SIZE) {
|
||||
error_setg(errp, "An internal buffer overran");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tos->obj = obj;
|
||||
tos->qapi = qapi;
|
||||
assert(!tos->h);
|
||||
assert(!tos->entry);
|
||||
|
||||
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
|
||||
h = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
@ -121,7 +115,7 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
|
||||
tos->entry = qlist_first(qobject_to_qlist(obj));
|
||||
}
|
||||
|
||||
qiv->nb_stack++;
|
||||
QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
|
||||
return tos->entry;
|
||||
}
|
||||
|
||||
@ -129,10 +123,9 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
|
||||
static void qmp_input_check_struct(Visitor *v, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
|
||||
|
||||
assert(qiv->nb_stack > 0);
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
assert(tos && !tos->entry);
|
||||
if (qiv->strict) {
|
||||
GHashTable *const top_ht = tos->h;
|
||||
if (top_ht) {
|
||||
@ -147,23 +140,23 @@ static void qmp_input_check_struct(Visitor *v, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_input_stack_object_free(StackObject *tos)
|
||||
{
|
||||
if (tos->h) {
|
||||
g_hash_table_unref(tos->h);
|
||||
}
|
||||
|
||||
g_free(tos);
|
||||
}
|
||||
|
||||
static void qmp_input_pop(Visitor *v, void **obj)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
assert(qiv->nb_stack > 0);
|
||||
assert(tos->qapi == obj);
|
||||
|
||||
if (qiv->strict) {
|
||||
GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
|
||||
if (top_ht) {
|
||||
g_hash_table_unref(top_ht);
|
||||
}
|
||||
tos->h = NULL;
|
||||
}
|
||||
|
||||
qiv->nb_stack--;
|
||||
assert(tos && tos->qapi == obj);
|
||||
QSLIST_REMOVE_HEAD(&qiv->stack, node);
|
||||
qmp_input_stack_object_free(tos);
|
||||
}
|
||||
|
||||
static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
|
||||
@ -224,7 +217,7 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
|
||||
size_t size)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
StackObject *so = &qiv->stack[qiv->nb_stack - 1];
|
||||
StackObject *so = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
if (!so->entry) {
|
||||
return NULL;
|
||||
@ -376,6 +369,12 @@ static void qmp_input_optional(Visitor *v, const char *name, bool *present)
|
||||
static void qmp_input_free(Visitor *v)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
while (!QSLIST_EMPTY(&qiv->stack)) {
|
||||
StackObject *tos = QSLIST_FIRST(&qiv->stack);
|
||||
|
||||
QSLIST_REMOVE_HEAD(&qiv->stack, node);
|
||||
qmp_input_stack_object_free(tos);
|
||||
}
|
||||
|
||||
qobject_decref(qiv->root);
|
||||
g_free(qiv);
|
||||
|
@ -23,15 +23,13 @@ typedef struct QStackEntry
|
||||
{
|
||||
QObject *value;
|
||||
void *qapi; /* sanity check that caller uses same pointer */
|
||||
QTAILQ_ENTRY(QStackEntry) node;
|
||||
QSLIST_ENTRY(QStackEntry) node;
|
||||
} QStackEntry;
|
||||
|
||||
typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
|
||||
|
||||
struct QmpOutputVisitor
|
||||
{
|
||||
Visitor visitor;
|
||||
QStack stack; /* Stack of containers that haven't yet been finished */
|
||||
QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
|
||||
QObject *root; /* Root of the output visit */
|
||||
QObject **result; /* User's storage location for result */
|
||||
};
|
||||
@ -56,18 +54,18 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value,
|
||||
assert(value);
|
||||
e->value = value;
|
||||
e->qapi = qapi;
|
||||
QTAILQ_INSERT_HEAD(&qov->stack, e, node);
|
||||
QSLIST_INSERT_HEAD(&qov->stack, e, node);
|
||||
}
|
||||
|
||||
/* Pop a value off the stack of QObjects being built, and return it. */
|
||||
static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
|
||||
{
|
||||
QStackEntry *e = QTAILQ_FIRST(&qov->stack);
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *value;
|
||||
|
||||
assert(e);
|
||||
assert(e->qapi == qapi);
|
||||
QTAILQ_REMOVE(&qov->stack, e, node);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
value = e->value;
|
||||
assert(value);
|
||||
g_free(e);
|
||||
@ -80,7 +78,7 @@ static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
|
||||
static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
|
||||
QObject *value)
|
||||
{
|
||||
QStackEntry *e = QTAILQ_FIRST(&qov->stack);
|
||||
QStackEntry *e = QSLIST_FIRST(&qov->stack);
|
||||
QObject *cur = e ? e->value : NULL;
|
||||
|
||||
if (!cur) {
|
||||
@ -206,7 +204,7 @@ static void qmp_output_complete(Visitor *v, void *opaque)
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
|
||||
/* A visit must have occurred, with each start paired with end. */
|
||||
assert(qov->root && QTAILQ_EMPTY(&qov->stack));
|
||||
assert(qov->root && QSLIST_EMPTY(&qov->stack));
|
||||
assert(opaque == qov->result);
|
||||
|
||||
qobject_incref(qov->root);
|
||||
@ -217,10 +215,11 @@ static void qmp_output_complete(Visitor *v, void *opaque)
|
||||
static void qmp_output_free(Visitor *v)
|
||||
{
|
||||
QmpOutputVisitor *qov = to_qov(v);
|
||||
QStackEntry *e, *tmp;
|
||||
QStackEntry *e;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(e, &qov->stack, node, tmp) {
|
||||
QTAILQ_REMOVE(&qov->stack, e, node);
|
||||
while (!QSLIST_EMPTY(&qov->stack)) {
|
||||
e = QSLIST_FIRST(&qov->stack);
|
||||
QSLIST_REMOVE_HEAD(&qov->stack, node);
|
||||
g_free(e);
|
||||
}
|
||||
|
||||
@ -250,7 +249,6 @@ Visitor *qmp_output_visitor_new(QObject **result)
|
||||
v->visitor.complete = qmp_output_complete;
|
||||
v->visitor.free = qmp_output_free;
|
||||
|
||||
QTAILQ_INIT(&v->stack);
|
||||
*result = NULL;
|
||||
v->result = result;
|
||||
|
||||
|
@ -16,20 +16,23 @@ from qapi import *
|
||||
import re
|
||||
|
||||
|
||||
def gen_command_decl(name, arg_type, ret_type):
|
||||
def gen_command_decl(name, arg_type, boxed, ret_type):
|
||||
return mcgen('''
|
||||
%(c_type)s qmp_%(c_name)s(%(params)s);
|
||||
''',
|
||||
c_type=(ret_type and ret_type.c_type()) or 'void',
|
||||
c_name=c_name(name),
|
||||
params=gen_params(arg_type, 'Error **errp'))
|
||||
params=gen_params(arg_type, boxed, 'Error **errp'))
|
||||
|
||||
|
||||
def gen_call(name, arg_type, ret_type):
|
||||
def gen_call(name, arg_type, boxed, ret_type):
|
||||
ret = ''
|
||||
|
||||
argstr = ''
|
||||
if arg_type:
|
||||
if boxed:
|
||||
assert arg_type and not arg_type.is_empty()
|
||||
argstr = '&arg, '
|
||||
elif arg_type:
|
||||
assert not arg_type.variants
|
||||
for memb in arg_type.members:
|
||||
if memb.optional:
|
||||
@ -46,8 +49,10 @@ def gen_call(name, arg_type, ret_type):
|
||||
''',
|
||||
c_name=c_name(name), args=argstr, lhs=lhs)
|
||||
if ret_type:
|
||||
ret += gen_err_check()
|
||||
ret += mcgen('''
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
qmp_marshal_output_%(c_name)s(retval, ret, &err);
|
||||
''',
|
||||
@ -92,7 +97,7 @@ def gen_marshal_decl(name):
|
||||
proto=gen_marshal_proto(name))
|
||||
|
||||
|
||||
def gen_marshal(name, arg_type, ret_type):
|
||||
def gen_marshal(name, arg_type, boxed, ret_type):
|
||||
ret = mcgen('''
|
||||
|
||||
%(proto)s
|
||||
@ -107,7 +112,7 @@ def gen_marshal(name, arg_type, ret_type):
|
||||
''',
|
||||
c_type=ret_type.c_type())
|
||||
|
||||
if arg_type and arg_type.members:
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
Visitor *v;
|
||||
%(c_name)s arg = {0};
|
||||
@ -134,10 +139,10 @@ def gen_marshal(name, arg_type, ret_type):
|
||||
(void)args;
|
||||
''')
|
||||
|
||||
ret += gen_call(name, arg_type, ret_type)
|
||||
ret += gen_call(name, arg_type, boxed, ret_type)
|
||||
|
||||
# 'goto out' produced above for arg_type, and by gen_call() for ret_type
|
||||
if (arg_type and arg_type.members) or ret_type:
|
||||
if (arg_type and not arg_type.is_empty()) or ret_type:
|
||||
ret += mcgen('''
|
||||
|
||||
out:
|
||||
@ -145,7 +150,7 @@ out:
|
||||
ret += mcgen('''
|
||||
error_propagate(errp, err);
|
||||
''')
|
||||
if arg_type and arg_type.members:
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
visit_free(v);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
@ -210,16 +215,16 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
|
||||
self._visited_ret_types = None
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response):
|
||||
gen, success_response, boxed):
|
||||
if not gen:
|
||||
return
|
||||
self.decl += gen_command_decl(name, arg_type, ret_type)
|
||||
self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
|
||||
if ret_type and ret_type not in self._visited_ret_types:
|
||||
self._visited_ret_types.add(ret_type)
|
||||
self.defn += gen_marshal_output(ret_type)
|
||||
if middle_mode:
|
||||
self.decl += gen_marshal_decl(name)
|
||||
self.defn += gen_marshal(name, arg_type, ret_type)
|
||||
self.defn += gen_marshal(name, arg_type, boxed, ret_type)
|
||||
if not middle_mode:
|
||||
self._regy += gen_register_command(name, success_response)
|
||||
|
||||
|
@ -14,18 +14,18 @@
|
||||
from qapi import *
|
||||
|
||||
|
||||
def gen_event_send_proto(name, arg_type):
|
||||
def gen_event_send_proto(name, arg_type, boxed):
|
||||
return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
|
||||
'c_name': c_name(name.lower()),
|
||||
'param': gen_params(arg_type, 'Error **errp')}
|
||||
'param': gen_params(arg_type, boxed, 'Error **errp')}
|
||||
|
||||
|
||||
def gen_event_send_decl(name, arg_type):
|
||||
def gen_event_send_decl(name, arg_type, boxed):
|
||||
return mcgen('''
|
||||
|
||||
%(proto)s;
|
||||
''',
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
proto=gen_event_send_proto(name, arg_type, boxed))
|
||||
|
||||
|
||||
# Declare and initialize an object 'qapi' using parameters from gen_params()
|
||||
@ -49,10 +49,15 @@ def gen_param_var(typ):
|
||||
|
||||
};
|
||||
''')
|
||||
if not typ.is_implicit():
|
||||
ret += mcgen('''
|
||||
%(c_name)s *arg = ¶m;
|
||||
''',
|
||||
c_name=typ.c_name())
|
||||
return ret
|
||||
|
||||
|
||||
def gen_event_send(name, arg_type):
|
||||
def gen_event_send(name, arg_type, boxed):
|
||||
# FIXME: Our declaration of local variables (and of 'errp' in the
|
||||
# parameter list) can collide with exploded members of the event's
|
||||
# data type passed in as parameters. If this collision ever hits in
|
||||
@ -67,14 +72,17 @@ def gen_event_send(name, arg_type):
|
||||
Error *err = NULL;
|
||||
QMPEventFuncEmit emit;
|
||||
''',
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
proto=gen_event_send_proto(name, arg_type, boxed))
|
||||
|
||||
if arg_type and arg_type.members:
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
QObject *obj;
|
||||
Visitor *v;
|
||||
''')
|
||||
ret += gen_param_var(arg_type)
|
||||
if not boxed:
|
||||
ret += gen_param_var(arg_type)
|
||||
else:
|
||||
assert not boxed
|
||||
|
||||
ret += mcgen('''
|
||||
|
||||
@ -88,9 +96,17 @@ def gen_event_send(name, arg_type):
|
||||
''',
|
||||
name=name)
|
||||
|
||||
if arg_type and arg_type.members:
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
v = qmp_output_visitor_new(&obj);
|
||||
''')
|
||||
if not arg_type.is_implicit():
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_name)s(v, "%(name)s", &arg, &err);
|
||||
''',
|
||||
name=name, c_name=arg_type.c_name())
|
||||
else:
|
||||
ret += mcgen('''
|
||||
|
||||
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
||||
if (err) {
|
||||
@ -101,14 +117,16 @@ def gen_event_send(name, arg_type):
|
||||
visit_check_struct(v, &err);
|
||||
}
|
||||
visit_end_struct(v, NULL);
|
||||
''',
|
||||
name=name, c_name=arg_type.c_name())
|
||||
ret += mcgen('''
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
visit_complete(v, &obj);
|
||||
qdict_put_obj(qmp, "data", obj);
|
||||
''',
|
||||
name=name, c_name=arg_type.c_name())
|
||||
''')
|
||||
|
||||
ret += mcgen('''
|
||||
emit(%(c_enum)s, qmp, &err);
|
||||
@ -116,7 +134,7 @@ def gen_event_send(name, arg_type):
|
||||
''',
|
||||
c_enum=c_enum_const(event_enum_name, name))
|
||||
|
||||
if arg_type and arg_type.members:
|
||||
if arg_type and not arg_type.is_empty():
|
||||
ret += mcgen('''
|
||||
out:
|
||||
visit_free(v);
|
||||
@ -145,9 +163,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
|
||||
self.defn += gen_enum_lookup(event_enum_name, self._event_names)
|
||||
self._event_names = None
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
self.decl += gen_event_send_decl(name, arg_type)
|
||||
self.defn += gen_event_send(name, arg_type)
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
self.decl += gen_event_send_decl(name, arg_type, boxed)
|
||||
self.defn += gen_event_send(name, arg_type, boxed)
|
||||
self._event_names.append(name)
|
||||
|
||||
|
||||
|
@ -154,14 +154,14 @@ const char %(c_name)s[] = %(c_string)s;
|
||||
for m in variants.variants]})
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response):
|
||||
gen, success_response, boxed):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
ret_type = ret_type or self._schema.the_empty_object_type
|
||||
self._gen_json(name, 'command',
|
||||
{'arg-type': self._use_type(arg_type),
|
||||
'ret-type': self._use_type(ret_type)})
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
|
||||
|
||||
|
@ -91,7 +91,7 @@ struct %(c_name)s {
|
||||
# potential issues with attempting to malloc space for zero-length
|
||||
# structs in C, and also incompatibility with C++ (where an empty
|
||||
# struct is size 1).
|
||||
if not (base and base.members) and not members and not variants:
|
||||
if (not base or base.is_empty()) and not members and not variants:
|
||||
ret += mcgen('''
|
||||
char qapi_dummy_for_empty_struct;
|
||||
''')
|
||||
|
@ -47,9 +47,11 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
''',
|
||||
c_type=base.c_name())
|
||||
ret += gen_err_check()
|
||||
|
||||
for memb in members:
|
||||
if memb.optional:
|
||||
@ -60,10 +62,12 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
push_indent()
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
''',
|
||||
c_type=memb.type.c_name(), name=memb.name,
|
||||
c_name=c_name(memb.name))
|
||||
ret += gen_err_check()
|
||||
if memb.optional:
|
||||
pop_indent()
|
||||
ret += mcgen('''
|
||||
|
127
scripts/qapi.py
127
scripts/qapi.py
@ -522,10 +522,14 @@ def check_type(expr_info, source, value, allow_array=False,
|
||||
|
||||
def check_command(expr, expr_info):
|
||||
name = expr['command']
|
||||
boxed = expr.get('boxed', False)
|
||||
|
||||
args_meta = ['struct']
|
||||
if boxed:
|
||||
args_meta += ['union', 'alternate']
|
||||
check_type(expr_info, "'data' for command '%s'" % name,
|
||||
expr.get('data'), allow_dict=True, allow_optional=True,
|
||||
allow_metas=['struct'])
|
||||
expr.get('data'), allow_dict=not boxed, allow_optional=True,
|
||||
allow_metas=args_meta)
|
||||
returns_meta = ['union', 'struct']
|
||||
if name in returns_whitelist:
|
||||
returns_meta += ['built-in', 'alternate', 'enum']
|
||||
@ -537,11 +541,15 @@ def check_command(expr, expr_info):
|
||||
def check_event(expr, expr_info):
|
||||
global events
|
||||
name = expr['event']
|
||||
boxed = expr.get('boxed', False)
|
||||
|
||||
meta = ['struct']
|
||||
if boxed:
|
||||
meta += ['union', 'alternate']
|
||||
events.append(name)
|
||||
check_type(expr_info, "'data' for event '%s'" % name,
|
||||
expr.get('data'), allow_dict=True, allow_optional=True,
|
||||
allow_metas=['struct'])
|
||||
expr.get('data'), allow_dict=not boxed, allow_optional=True,
|
||||
allow_metas=meta)
|
||||
|
||||
|
||||
def check_union(expr, expr_info):
|
||||
@ -612,6 +620,14 @@ def check_union(expr, expr_info):
|
||||
"enum '%s'" %
|
||||
(key, enum_define["enum_name"]))
|
||||
|
||||
# If discriminator is user-defined, ensure all values are covered
|
||||
if enum_define:
|
||||
for value in enum_define['enum_values']:
|
||||
if value not in members.keys():
|
||||
raise QAPIExprError(expr_info,
|
||||
"Union '%s' data missing '%s' branch"
|
||||
% (name, value))
|
||||
|
||||
|
||||
def check_alternate(expr, expr_info):
|
||||
name = expr['alternate']
|
||||
@ -686,6 +702,10 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
||||
raise QAPIExprError(info,
|
||||
"'%s' of %s '%s' should only use false value"
|
||||
% (key, meta, name))
|
||||
if key == 'boxed' and value is not True:
|
||||
raise QAPIExprError(info,
|
||||
"'%s' of %s '%s' should only use true value"
|
||||
% (key, meta, name))
|
||||
for key in required:
|
||||
if key not in expr:
|
||||
raise QAPIExprError(info,
|
||||
@ -717,10 +737,10 @@ def check_exprs(exprs):
|
||||
add_struct(expr, info)
|
||||
elif 'command' in expr:
|
||||
check_keys(expr_elem, 'command', [],
|
||||
['data', 'returns', 'gen', 'success-response'])
|
||||
['data', 'returns', 'gen', 'success-response', 'boxed'])
|
||||
add_name(expr['command'], info, 'command')
|
||||
elif 'event' in expr:
|
||||
check_keys(expr_elem, 'event', [], ['data'])
|
||||
check_keys(expr_elem, 'event', [], ['data', 'boxed'])
|
||||
add_name(expr['event'], info, 'event')
|
||||
else:
|
||||
raise QAPIExprError(expr_elem['info'],
|
||||
@ -818,10 +838,10 @@ class QAPISchemaVisitor(object):
|
||||
pass
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response):
|
||||
gen, success_response, boxed):
|
||||
pass
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
pass
|
||||
|
||||
|
||||
@ -991,7 +1011,12 @@ class QAPISchemaObjectType(QAPISchemaType):
|
||||
# _def_predefineds()
|
||||
return self.name.startswith('q_')
|
||||
|
||||
def is_empty(self):
|
||||
assert self.members is not None
|
||||
return not self.members and not self.variants
|
||||
|
||||
def c_name(self):
|
||||
assert self.name != 'q_empty'
|
||||
return QAPISchemaType.c_name(self)
|
||||
|
||||
def c_type(self):
|
||||
@ -1084,7 +1109,7 @@ class QAPISchemaObjectTypeVariants(object):
|
||||
assert len(variants) > 0
|
||||
for v in variants:
|
||||
assert isinstance(v, QAPISchemaObjectTypeVariant)
|
||||
self.tag_name = tag_name
|
||||
self._tag_name = tag_name
|
||||
self.tag_member = tag_member
|
||||
self.variants = variants
|
||||
|
||||
@ -1094,8 +1119,8 @@ class QAPISchemaObjectTypeVariants(object):
|
||||
|
||||
def check(self, schema, seen):
|
||||
if not self.tag_member: # flat union
|
||||
self.tag_member = seen[c_name(self.tag_name)]
|
||||
assert self.tag_name == self.tag_member.name
|
||||
self.tag_member = seen[c_name(self._tag_name)]
|
||||
assert self._tag_name == self.tag_member.name
|
||||
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
|
||||
for v in self.variants:
|
||||
v.check(schema)
|
||||
@ -1125,7 +1150,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
||||
def __init__(self, name, info, variants):
|
||||
QAPISchemaType.__init__(self, name, info)
|
||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||
assert not variants.tag_name
|
||||
assert variants.tag_member
|
||||
variants.set_owner(name)
|
||||
variants.tag_member.set_owner(self.name)
|
||||
self.variants = variants
|
||||
@ -1150,9 +1175,13 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
||||
def visit(self, visitor):
|
||||
visitor.visit_alternate_type(self.name, self.info, self.variants)
|
||||
|
||||
def is_empty(self):
|
||||
return False
|
||||
|
||||
|
||||
class QAPISchemaCommand(QAPISchemaEntity):
|
||||
def __init__(self, name, info, arg_type, ret_type, gen, success_response):
|
||||
def __init__(self, name, info, arg_type, ret_type, gen, success_response,
|
||||
boxed):
|
||||
QAPISchemaEntity.__init__(self, name, info)
|
||||
assert not arg_type or isinstance(arg_type, str)
|
||||
assert not ret_type or isinstance(ret_type, str)
|
||||
@ -1162,12 +1191,24 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||
self.ret_type = None
|
||||
self.gen = gen
|
||||
self.success_response = success_response
|
||||
self.boxed = boxed
|
||||
|
||||
def check(self, schema):
|
||||
if self._arg_type_name:
|
||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||
assert isinstance(self.arg_type, QAPISchemaObjectType)
|
||||
assert not self.arg_type.variants # not implemented
|
||||
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
||||
isinstance(self.arg_type, QAPISchemaAlternateType))
|
||||
self.arg_type.check(schema)
|
||||
if self.boxed:
|
||||
if self.arg_type.is_empty():
|
||||
raise QAPIExprError(self.info,
|
||||
"Cannot use 'boxed' with empty type")
|
||||
else:
|
||||
assert not isinstance(self.arg_type, QAPISchemaAlternateType)
|
||||
assert not self.arg_type.variants
|
||||
elif self.boxed:
|
||||
raise QAPIExprError(self.info,
|
||||
"Use of 'boxed' requires 'data'")
|
||||
if self._ret_type_name:
|
||||
self.ret_type = schema.lookup_type(self._ret_type_name)
|
||||
assert isinstance(self.ret_type, QAPISchemaType)
|
||||
@ -1175,24 +1216,36 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||
def visit(self, visitor):
|
||||
visitor.visit_command(self.name, self.info,
|
||||
self.arg_type, self.ret_type,
|
||||
self.gen, self.success_response)
|
||||
self.gen, self.success_response, self.boxed)
|
||||
|
||||
|
||||
class QAPISchemaEvent(QAPISchemaEntity):
|
||||
def __init__(self, name, info, arg_type):
|
||||
def __init__(self, name, info, arg_type, boxed):
|
||||
QAPISchemaEntity.__init__(self, name, info)
|
||||
assert not arg_type or isinstance(arg_type, str)
|
||||
self._arg_type_name = arg_type
|
||||
self.arg_type = None
|
||||
self.boxed = boxed
|
||||
|
||||
def check(self, schema):
|
||||
if self._arg_type_name:
|
||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||
assert isinstance(self.arg_type, QAPISchemaObjectType)
|
||||
assert not self.arg_type.variants # not implemented
|
||||
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
||||
isinstance(self.arg_type, QAPISchemaAlternateType))
|
||||
self.arg_type.check(schema)
|
||||
if self.boxed:
|
||||
if self.arg_type.is_empty():
|
||||
raise QAPIExprError(self.info,
|
||||
"Cannot use 'boxed' with empty type")
|
||||
else:
|
||||
assert not isinstance(self.arg_type, QAPISchemaAlternateType)
|
||||
assert not self.arg_type.variants
|
||||
elif self.boxed:
|
||||
raise QAPIExprError(self.info,
|
||||
"Use of 'boxed' requires 'data'")
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_event(self.name, self.info, self.arg_type)
|
||||
visitor.visit_event(self.name, self.info, self.arg_type, self.boxed)
|
||||
|
||||
|
||||
class QAPISchema(object):
|
||||
@ -1368,6 +1421,7 @@ class QAPISchema(object):
|
||||
rets = expr.get('returns')
|
||||
gen = expr.get('gen', True)
|
||||
success_response = expr.get('success-response', True)
|
||||
boxed = expr.get('boxed', False)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
name, info, 'arg', self._make_members(data, info))
|
||||
@ -1375,15 +1429,16 @@ class QAPISchema(object):
|
||||
assert len(rets) == 1
|
||||
rets = self._make_array_type(rets[0], info)
|
||||
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
|
||||
success_response))
|
||||
success_response, boxed))
|
||||
|
||||
def _def_event(self, expr, info):
|
||||
name = expr['event']
|
||||
data = expr.get('data')
|
||||
boxed = expr.get('boxed', False)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
name, info, 'arg', self._make_members(data, info))
|
||||
self._def_entity(QAPISchemaEvent(name, info, data))
|
||||
self._def_entity(QAPISchemaEvent(name, info, data, boxed))
|
||||
|
||||
def _def_exprs(self):
|
||||
for expr_elem in self.exprs:
|
||||
@ -1626,31 +1681,29 @@ extern const char *const %(c_name)s_lookup[];
|
||||
return ret
|
||||
|
||||
|
||||
def gen_params(arg_type, extra):
|
||||
def gen_params(arg_type, boxed, extra):
|
||||
if not arg_type:
|
||||
assert not boxed
|
||||
return extra
|
||||
assert not arg_type.variants
|
||||
ret = ''
|
||||
sep = ''
|
||||
for memb in arg_type.members:
|
||||
ret += sep
|
||||
if boxed:
|
||||
ret += '%s arg' % arg_type.c_param_type()
|
||||
sep = ', '
|
||||
if memb.optional:
|
||||
ret += 'bool has_%s, ' % c_name(memb.name)
|
||||
ret += '%s %s' % (memb.type.c_param_type(), c_name(memb.name))
|
||||
else:
|
||||
assert not arg_type.variants
|
||||
for memb in arg_type.members:
|
||||
ret += sep
|
||||
sep = ', '
|
||||
if memb.optional:
|
||||
ret += 'bool has_%s, ' % c_name(memb.name)
|
||||
ret += '%s %s' % (memb.type.c_param_type(),
|
||||
c_name(memb.name))
|
||||
if extra:
|
||||
ret += sep + extra
|
||||
return ret
|
||||
|
||||
|
||||
def gen_err_check():
|
||||
return mcgen('''
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
''')
|
||||
|
||||
|
||||
#
|
||||
# Common command line parsing
|
||||
#
|
||||
|
@ -284,6 +284,10 @@ qapi-schema += args-alternate.json
|
||||
qapi-schema += args-any.json
|
||||
qapi-schema += args-array-empty.json
|
||||
qapi-schema += args-array-unknown.json
|
||||
qapi-schema += args-bad-boxed.json
|
||||
qapi-schema += args-boxed-anon.json
|
||||
qapi-schema += args-boxed-empty.json
|
||||
qapi-schema += args-boxed-string.json
|
||||
qapi-schema += args-int.json
|
||||
qapi-schema += args-invalid.json
|
||||
qapi-schema += args-member-array-bad.json
|
||||
@ -317,6 +321,7 @@ qapi-schema += enum-wrong-data.json
|
||||
qapi-schema += escape-outside-string.json
|
||||
qapi-schema += escape-too-big.json
|
||||
qapi-schema += escape-too-short.json
|
||||
qapi-schema += event-boxed-empty.json
|
||||
qapi-schema += event-case.json
|
||||
qapi-schema += event-nest-struct.json
|
||||
qapi-schema += flat-union-array-branch.json
|
||||
@ -326,6 +331,7 @@ qapi-schema += flat-union-base-any.json
|
||||
qapi-schema += flat-union-base-union.json
|
||||
qapi-schema += flat-union-clash-member.json
|
||||
qapi-schema += flat-union-empty.json
|
||||
qapi-schema += flat-union-incomplete-branch.json
|
||||
qapi-schema += flat-union-inline.json
|
||||
qapi-schema += flat-union-int-branch.json
|
||||
qapi-schema += flat-union-invalid-branch-key.json
|
||||
|
1
tests/qapi-schema/args-bad-boxed.err
Normal file
1
tests/qapi-schema/args-bad-boxed.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value
|
1
tests/qapi-schema/args-bad-boxed.exit
Normal file
1
tests/qapi-schema/args-bad-boxed.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
tests/qapi-schema/args-bad-boxed.json
Normal file
2
tests/qapi-schema/args-bad-boxed.json
Normal file
@ -0,0 +1,2 @@
|
||||
# 'boxed' should only appear with value true
|
||||
{ 'command': 'foo', 'boxed': false }
|
0
tests/qapi-schema/args-bad-boxed.out
Normal file
0
tests/qapi-schema/args-bad-boxed.out
Normal file
1
tests/qapi-schema/args-boxed-anon.err
Normal file
1
tests/qapi-schema/args-boxed-anon.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name
|
1
tests/qapi-schema/args-boxed-anon.exit
Normal file
1
tests/qapi-schema/args-boxed-anon.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
tests/qapi-schema/args-boxed-anon.json
Normal file
2
tests/qapi-schema/args-boxed-anon.json
Normal file
@ -0,0 +1,2 @@
|
||||
# 'boxed' can only be used with named types
|
||||
{ 'command': 'foo', 'boxed': true, 'data': { 'string': 'str' } }
|
0
tests/qapi-schema/args-boxed-anon.out
Normal file
0
tests/qapi-schema/args-boxed-anon.out
Normal file
1
tests/qapi-schema/args-boxed-empty.err
Normal file
1
tests/qapi-schema/args-boxed-empty.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type
|
1
tests/qapi-schema/args-boxed-empty.exit
Normal file
1
tests/qapi-schema/args-boxed-empty.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
3
tests/qapi-schema/args-boxed-empty.json
Normal file
3
tests/qapi-schema/args-boxed-empty.json
Normal file
@ -0,0 +1,3 @@
|
||||
# 'boxed' requires a non-empty type
|
||||
{ 'struct': 'Empty', 'data': {} }
|
||||
{ 'command': 'foo', 'boxed': true, 'data': 'Empty' }
|
0
tests/qapi-schema/args-boxed-empty.out
Normal file
0
tests/qapi-schema/args-boxed-empty.out
Normal file
1
tests/qapi-schema/args-boxed-string.err
Normal file
1
tests/qapi-schema/args-boxed-string.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str'
|
1
tests/qapi-schema/args-boxed-string.exit
Normal file
1
tests/qapi-schema/args-boxed-string.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
tests/qapi-schema/args-boxed-string.json
Normal file
2
tests/qapi-schema/args-boxed-string.json
Normal file
@ -0,0 +1,2 @@
|
||||
# 'boxed' requires a complex (not built-in) type
|
||||
{ 'command': 'foo', 'boxed': true, 'data': 'str' }
|
0
tests/qapi-schema/args-boxed-string.out
Normal file
0
tests/qapi-schema/args-boxed-string.out
Normal file
@ -1 +1 @@
|
||||
tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni'
|
||||
tests/qapi-schema/args-union.json:3: 'data' for command 'oops' cannot use union type 'Uni'
|
||||
|
@ -1,4 +1,3 @@
|
||||
# we do not allow union arguments
|
||||
# TODO should we support this?
|
||||
# use of union arguments requires 'boxed':true
|
||||
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
|
||||
{ 'command': 'oops', 'data': 'Uni' }
|
||||
|
1
tests/qapi-schema/event-boxed-empty.err
Normal file
1
tests/qapi-schema/event-boxed-empty.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data'
|
1
tests/qapi-schema/event-boxed-empty.exit
Normal file
1
tests/qapi-schema/event-boxed-empty.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
tests/qapi-schema/event-boxed-empty.json
Normal file
2
tests/qapi-schema/event-boxed-empty.json
Normal file
@ -0,0 +1,2 @@
|
||||
# 'boxed' requires a non-empty type
|
||||
{ 'event': 'FOO', 'boxed': true }
|
0
tests/qapi-schema/event-boxed-empty.out
Normal file
0
tests/qapi-schema/event-boxed-empty.out
Normal file
@ -1,4 +1,5 @@
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
event oops None
|
||||
boxed=False
|
||||
object q_empty
|
||||
|
1
tests/qapi-schema/flat-union-incomplete-branch.err
Normal file
1
tests/qapi-schema/flat-union-incomplete-branch.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch
|
1
tests/qapi-schema/flat-union-incomplete-branch.exit
Normal file
1
tests/qapi-schema/flat-union-incomplete-branch.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
9
tests/qapi-schema/flat-union-incomplete-branch.json
Normal file
9
tests/qapi-schema/flat-union-incomplete-branch.json
Normal file
@ -0,0 +1,9 @@
|
||||
# we require all branches of the union to be covered
|
||||
{ 'enum': 'TestEnum',
|
||||
'data': [ 'value1', 'value2' ] }
|
||||
{ 'struct': 'TestTypeA',
|
||||
'data': { 'string': 'str' } }
|
||||
{ 'union': 'TestUnion',
|
||||
'base': { 'type': 'TestEnum' },
|
||||
'discriminator': 'type',
|
||||
'data': { 'value1': 'TestTypeA' } }
|
0
tests/qapi-schema/flat-union-incomplete-branch.out
Normal file
0
tests/qapi-schema/flat-union-incomplete-branch.out
Normal file
@ -1,7 +1,7 @@
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
command fooA q_obj_fooA-arg -> None
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
object q_empty
|
||||
object q_obj_fooA-arg
|
||||
member bar1: str optional=False
|
||||
|
@ -1,7 +1,7 @@
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
command eins None -> None
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
object q_empty
|
||||
command zwei None -> None
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
|
@ -127,6 +127,8 @@
|
||||
{ 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' },
|
||||
'returns': 'int' }
|
||||
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
|
||||
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
|
||||
{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
|
||||
|
||||
# For testing integer range flattening in opts-visitor. The following schema
|
||||
# corresponds to the option format:
|
||||
@ -154,6 +156,8 @@
|
||||
'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
|
||||
{ 'event': 'EVENT_D',
|
||||
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
|
||||
{ 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' }
|
||||
{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefAlternate' }
|
||||
|
||||
# test that we correctly compile downstream extensions, as well as munge
|
||||
# ticklish names
|
||||
|
@ -1,25 +1,39 @@
|
||||
alternate AltIntNum
|
||||
tag type
|
||||
case i: int
|
||||
case n: number
|
||||
alternate AltNumInt
|
||||
tag type
|
||||
case n: number
|
||||
case i: int
|
||||
alternate AltNumStr
|
||||
tag type
|
||||
case n: number
|
||||
case s: str
|
||||
alternate AltStrBool
|
||||
tag type
|
||||
case s: str
|
||||
case b: bool
|
||||
alternate AltStrInt
|
||||
tag type
|
||||
case s: str
|
||||
case i: int
|
||||
alternate AltStrNum
|
||||
tag type
|
||||
case s: str
|
||||
case n: number
|
||||
event EVENT_A None
|
||||
boxed=False
|
||||
event EVENT_B None
|
||||
boxed=False
|
||||
event EVENT_C q_obj_EVENT_C-arg
|
||||
boxed=False
|
||||
event EVENT_D q_obj_EVENT_D-arg
|
||||
boxed=False
|
||||
event EVENT_E UserDefZero
|
||||
boxed=True
|
||||
event EVENT_F UserDefAlternate
|
||||
boxed=True
|
||||
object Empty1
|
||||
object Empty2
|
||||
base Empty1
|
||||
@ -50,6 +64,7 @@ object UserDefA
|
||||
member boolean: bool optional=False
|
||||
member a_b: int optional=True
|
||||
alternate UserDefAlternate
|
||||
tag type
|
||||
case udfu: UserDefFlatUnion
|
||||
case s: str
|
||||
case i: int
|
||||
@ -72,6 +87,7 @@ object UserDefFlatUnion2
|
||||
case value2: UserDefB
|
||||
object UserDefNativeListUnion
|
||||
member type: UserDefNativeListUnionKind optional=False
|
||||
tag type
|
||||
case integer: q_obj_intList-wrapper
|
||||
case s8: q_obj_int8List-wrapper
|
||||
case s16: q_obj_int16List-wrapper
|
||||
@ -116,7 +132,9 @@ object UserDefZero
|
||||
object WrapAlternate
|
||||
member alt: UserDefAlternate optional=False
|
||||
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
|
||||
boxed=False
|
||||
alternate __org.qemu_x-Alt
|
||||
tag type
|
||||
case __org.qemu_x-branch: str
|
||||
case b: __org.qemu_x-Base
|
||||
object __org.qemu_x-Base
|
||||
@ -130,6 +148,7 @@ object __org.qemu_x-Struct2
|
||||
member array: __org.qemu_x-Union1List optional=False
|
||||
object __org.qemu_x-Union1
|
||||
member type: __org.qemu_x-Union1Kind optional=False
|
||||
tag type
|
||||
case __org.qemu_x-branch: q_obj_str-wrapper
|
||||
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
|
||||
object __org.qemu_x-Union2
|
||||
@ -137,11 +156,15 @@ object __org.qemu_x-Union2
|
||||
tag __org.qemu_x-member1
|
||||
case __org.qemu_x-value: __org.qemu_x-Struct2
|
||||
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
command boxed-struct UserDefZero -> None
|
||||
gen=True success_response=True boxed=True
|
||||
command boxed-union UserDefNativeListUnion -> None
|
||||
gen=True success_response=True boxed=True
|
||||
command guest-get-time q_obj_guest-get-time-arg -> int
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
command guest-sync q_obj_guest-sync-arg -> any
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
object q_empty
|
||||
object q_obj_EVENT_C-arg
|
||||
member a: int optional=True
|
||||
@ -202,10 +225,10 @@ object q_obj_user_def_cmd2-arg
|
||||
member ud1a: UserDefOne optional=False
|
||||
member ud1b: UserDefOne optional=True
|
||||
command user_def_cmd None -> None
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
command user_def_cmd0 Empty2 -> Empty2
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
|
||||
gen=True success_response=True
|
||||
gen=True success_response=True boxed=False
|
||||
|
@ -36,19 +36,20 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||
self._print_variants(variants)
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response):
|
||||
gen, success_response, boxed):
|
||||
print 'command %s %s -> %s' % \
|
||||
(name, arg_type and arg_type.name, ret_type and ret_type.name)
|
||||
print ' gen=%s success_response=%s' % (gen, success_response)
|
||||
print ' gen=%s success_response=%s boxed=%s' % \
|
||||
(gen, success_response, boxed)
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
print 'event %s %s' % (name, arg_type and arg_type.name)
|
||||
print ' boxed=%s' % boxed
|
||||
|
||||
@staticmethod
|
||||
def _print_variants(variants):
|
||||
if variants:
|
||||
if variants.tag_name:
|
||||
print ' tag %s' % variants.tag_name
|
||||
print ' tag %s' % variants.tag_member.name
|
||||
for v in variants.variants:
|
||||
print ' case %s: %s' % (v.name, v.type.name)
|
||||
|
||||
|
@ -59,6 +59,14 @@ QObject *qmp_guest_sync(QObject *arg, Error **errp)
|
||||
return arg;
|
||||
}
|
||||
|
||||
void qmp_boxed_struct(UserDefZero *arg, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
|
||||
__org_qemu_x_StructList *b,
|
||||
__org_qemu_x_Union2 *c,
|
||||
|
Loading…
Reference in New Issue
Block a user