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:
Peter Maydell 2016-07-20 14:34:08 +01:00
commit 3b2e6798ff
95 changed files with 700 additions and 509 deletions

View File

@ -2634,49 +2634,17 @@ fail:
} }
/* throttling disk I/O limits */ /* throttling disk I/O limits */
void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
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)
{ {
ThrottleConfig cfg; ThrottleConfig cfg;
BlockDriverState *bs; BlockDriverState *bs;
BlockBackend *blk; BlockBackend *blk;
AioContext *aio_context; AioContext *aio_context;
blk = blk_by_name(device); blk = blk_by_name(arg->device);
if (!blk) { if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device); "Device '%s' not found", arg->device);
return; 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); bs = blk_bs(blk);
if (!bs) { if (!bs) {
error_setg(errp, "Device '%s' has no medium", device); error_setg(errp, "Device '%s' has no medium", arg->device);
goto out; goto out;
} }
throttle_config_init(&cfg); throttle_config_init(&cfg);
cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps; cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps;
cfg.buckets[THROTTLE_BPS_READ].avg = bps_rd; cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd;
cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr; cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr;
cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops; cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops;
cfg.buckets[THROTTLE_OPS_READ].avg = iops_rd; cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd;
cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr; cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr;
if (has_bps_max) { if (arg->has_bps_max) {
cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max; cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max;
} }
if (has_bps_rd_max) { if (arg->has_bps_rd_max) {
cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max; cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max;
} }
if (has_bps_wr_max) { if (arg->has_bps_wr_max) {
cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max; cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max;
} }
if (has_iops_max) { if (arg->has_iops_max) {
cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max; cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max;
} }
if (has_iops_rd_max) { if (arg->has_iops_rd_max) {
cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max; cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max;
} }
if (has_iops_wr_max) { if (arg->has_iops_wr_max) {
cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max; cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max;
} }
if (has_bps_max_length) { if (arg->has_bps_max_length) {
cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = bps_max_length; cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length;
} }
if (has_bps_rd_max_length) { if (arg->has_bps_rd_max_length) {
cfg.buckets[THROTTLE_BPS_READ].burst_length = bps_rd_max_length; cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length;
} }
if (has_bps_wr_max_length) { if (arg->has_bps_wr_max_length) {
cfg.buckets[THROTTLE_BPS_WRITE].burst_length = bps_wr_max_length; cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length;
} }
if (has_iops_max_length) { if (arg->has_iops_max_length) {
cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = iops_max_length; cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length;
} }
if (has_iops_rd_max_length) { if (arg->has_iops_rd_max_length) {
cfg.buckets[THROTTLE_OPS_READ].burst_length = iops_rd_max_length; cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length;
} }
if (has_iops_wr_max_length) { if (arg->has_iops_wr_max_length) {
cfg.buckets[THROTTLE_OPS_WRITE].burst_length = iops_wr_max_length; cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length;
} }
if (has_iops_size) { if (arg->has_iops_size) {
cfg.op_size = iops_size; cfg.op_size = arg->iops_size;
} }
if (!throttle_is_valid(&cfg, errp)) { 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 /* Enable I/O limits if they're not enabled yet, otherwise
* just update the throttling group. */ * just update the throttling group. */
if (!blk_get_public(blk)->throttle_state) { if (!blk_get_public(blk)->throttle_state) {
blk_io_limits_enable(blk, has_group ? group : device); blk_io_limits_enable(blk,
} else if (has_group) { arg->has_group ? arg->group : arg->device);
blk_io_limits_update_group(blk, group); } else if (arg->has_group) {
blk_io_limits_update_group(blk, arg->group);
} }
/* Set the new throttling configuration */ /* Set the new throttling configuration */
blk_set_io_limits(blk, &cfg); 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); block_job_cb, bs, errp);
} }
void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, void qmp_drive_mirror(DriveMirror *arg, Error **errp)
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)
{ {
BlockDriverState *bs; BlockDriverState *bs;
BlockBackend *blk; BlockBackend *blk;
@ -3520,11 +3477,12 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
QDict *options = NULL; QDict *options = NULL;
int flags; int flags;
int64_t size; int64_t size;
const char *format = arg->format;
blk = blk_by_name(device); blk = blk_by_name(arg->device);
if (!blk) { if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device); "Device '%s' not found", arg->device);
return; 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); aio_context_acquire(aio_context);
if (!blk_is_available(blk)) { 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; goto out;
} }
bs = blk_bs(blk); bs = blk_bs(blk);
if (!has_mode) { if (!arg->has_mode) {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
} }
if (!has_format) { if (!arg->has_format) {
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name; format = (arg->mode == NEW_IMAGE_MODE_EXISTING
? NULL : bs->drv->format_name);
} }
flags = bs->open_flags | BDRV_O_RDWR; flags = bs->open_flags | BDRV_O_RDWR;
source = backing_bs(bs); source = backing_bs(bs);
if (!source && sync == MIRROR_SYNC_MODE_TOP) { if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) {
sync = MIRROR_SYNC_MODE_FULL; arg->sync = MIRROR_SYNC_MODE_FULL;
} }
if (sync == MIRROR_SYNC_MODE_NONE) { if (arg->sync == MIRROR_SYNC_MODE_NONE) {
source = bs; source = bs;
} }
@ -3559,18 +3518,18 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device,
goto out; goto out;
} }
if (has_replaces) { if (arg->has_replaces) {
BlockDriverState *to_replace_bs; BlockDriverState *to_replace_bs;
AioContext *replace_aio_context; AioContext *replace_aio_context;
int64_t replace_size; 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" error_setg(errp, "a node-name must be provided when replacing a"
" named node of the graph"); " named node of the graph");
goto out; 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) { if (!to_replace_bs) {
error_propagate(errp, local_err); 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; backing_mode = MIRROR_SOURCE_BACKING_CHAIN;
} else { } else {
backing_mode = MIRROR_OPEN_BACKING_CHAIN; backing_mode = MIRROR_OPEN_BACKING_CHAIN;
} }
if ((sync == MIRROR_SYNC_MODE_FULL || !source) if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)
&& mode != NEW_IMAGE_MODE_EXISTING) && arg->mode != NEW_IMAGE_MODE_EXISTING)
{ {
/* create new image w/o backing file */ /* create new image w/o backing file */
assert(format); assert(format);
bdrv_img_create(target, format, bdrv_img_create(arg->target, format,
NULL, NULL, NULL, size, flags, &local_err, false); NULL, NULL, NULL, size, flags, &local_err, false);
} else { } else {
switch (mode) { switch (arg->mode) {
case NEW_IMAGE_MODE_EXISTING: case NEW_IMAGE_MODE_EXISTING:
break; break;
case NEW_IMAGE_MODE_ABSOLUTE_PATHS: case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
/* create new image with backing file */ /* create new image with backing file */
bdrv_img_create(target, format, bdrv_img_create(arg->target, format,
source->filename, source->filename,
source->drv->format_name, source->drv->format_name,
NULL, size, flags, &local_err, false); 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(); options = qdict_new();
if (has_node_name) { if (arg->has_node_name) {
qdict_put(options, "node-name", qstring_from_str(node_name)); qdict_put(options, "node-name", qstring_from_str(arg->node_name));
} }
if (format) { if (format) {
qdict_put(options, "driver", qstring_from_str(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 /* Mirroring takes care of copy-on-write using the source's backing
* file. * file.
*/ */
target_bs = bdrv_open(target, NULL, options, flags | BDRV_O_NO_BACKING, target_bs = bdrv_open(arg->target, NULL, options,
errp); flags | BDRV_O_NO_BACKING, errp);
if (!target_bs) { if (!target_bs) {
goto out; goto out;
} }
bdrv_set_aio_context(target_bs, aio_context); bdrv_set_aio_context(target_bs, aio_context);
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
has_replaces, replaces, sync, backing_mode, arg->has_replaces, arg->replaces, arg->sync,
has_speed, speed, backing_mode, arg->has_speed, arg->speed,
has_granularity, granularity, arg->has_granularity, arg->granularity,
has_buf_size, buf_size, arg->has_buf_size, arg->buf_size,
has_on_source_error, on_source_error, arg->has_on_source_error, arg->on_source_error,
has_on_target_error, on_target_error, arg->has_on_target_error, arg->on_target_error,
has_unmap, unmap, arg->has_unmap, arg->unmap,
&local_err); &local_err);
bdrv_unref(target_bs); bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);

View File

@ -410,7 +410,7 @@ following example objects:
=== Commands === === Commands ===
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
'*returns': TYPE-NAME, '*returns': TYPE-NAME, '*boxed': true,
'*gen': false, '*success-response': false } '*gen': false, '*success-response': false }
Commands are defined by using a dictionary containing several members, 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" } => { "execute": "my-second-command" }
<= { "return": [ { "value": "one" }, { } ] } <= { "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 In rare cases, QAPI cannot express a type-safe representation of a
corresponding Client JSON Protocol command. You then have to suppress corresponding Client JSON Protocol command. You then have to suppress
generation of a marshalling function by including a key 'gen' with generation of a marshalling function by including a key 'gen' with
@ -484,7 +498,8 @@ use of this member.
=== Events === === 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 Events are defined with the keyword 'event'. It is not allowed to
name an event 'MAX', since the generator also produces a C enumeration 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" }, "data": { "b": "test string" },
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } } "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 == == Client JSON Protocol introspection ==

70
hmp.c
View File

@ -1077,31 +1077,28 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
void hmp_drive_mirror(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 *filename = qdict_get_str(qdict, "target");
const char *format = qdict_get_try_str(qdict, "format"); const char *format = qdict_get_try_str(qdict, "format");
bool reuse = qdict_get_try_bool(qdict, "reuse", false); bool reuse = qdict_get_try_bool(qdict, "reuse", false);
bool full = qdict_get_try_bool(qdict, "full", false); bool full = qdict_get_try_bool(qdict, "full", false);
enum NewImageMode mode;
Error *err = NULL; 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) { if (!filename) {
error_setg(&err, QERR_MISSING_PARAMETER, "target"); error_setg(&err, QERR_MISSING_PARAMETER, "target");
hmp_handle_error(mon, &err); hmp_handle_error(mon, &err);
return; return;
} }
qmp_drive_mirror(&mirror, &err);
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);
hmp_handle_error(mon, &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) void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
{ {
Error *err = NULL; 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"), qmp_block_set_io_throttle(&throttle, &err);
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);
hmp_handle_error(mon, &err); hmp_handle_error(mon, &err);
} }

View File

@ -378,7 +378,7 @@ static void eth_cleanup(NetClientState *nc)
} }
static NetClientInfo net_mv88w8618_info = { static NetClientInfo net_mv88w8618_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = eth_receive, .receive = eth_receive,
.cleanup = eth_cleanup, .cleanup = eth_cleanup,

View File

@ -247,7 +247,7 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
} }
queues = qemu_find_net_clients_except(str, peers, queues = qemu_find_net_clients_except(str, peers,
NET_CLIENT_OPTIONS_KIND_NIC, NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
if (queues == 0) { if (queues == 0) {
err = -ENOENT; err = -ENOENT;

View File

@ -424,7 +424,7 @@ static const MemoryRegionOps aw_emac_mem_ops = {
}; };
static NetClientInfo net_aw_emac_info = { static NetClientInfo net_aw_emac_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = aw_emac_can_receive, .can_receive = aw_emac_can_receive,
.receive = aw_emac_receive, .receive = aw_emac_receive,

View File

@ -1207,7 +1207,7 @@ static void gem_set_link(NetClientState *nc)
} }
static NetClientInfo net_gem_info = { static NetClientInfo net_gem_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = gem_can_receive, .can_receive = gem_can_receive,
.receive = gem_receive, .receive = gem_receive,

View File

@ -812,7 +812,7 @@ static void dp8393x_reset(DeviceState *dev)
} }
static NetClientInfo net_dp83932_info = { static NetClientInfo net_dp83932_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = dp8393x_can_receive, .can_receive = dp8393x_can_receive,
.receive = dp8393x_receive, .receive = dp8393x_receive,

View File

@ -1563,7 +1563,7 @@ pci_e1000_uninit(PCIDevice *dev)
} }
static NetClientInfo net_e1000_info = { static NetClientInfo net_e1000_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = e1000_can_receive, .can_receive = e1000_can_receive,
.receive = e1000_receive, .receive = e1000_receive,

View File

@ -225,7 +225,7 @@ e1000e_set_link_status(NetClientState *nc)
} }
static NetClientInfo net_e1000e_info = { static NetClientInfo net_e1000e_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = e1000e_nc_can_receive, .can_receive = e1000e_nc_can_receive,
.receive = e1000e_nc_receive, .receive = e1000e_nc_receive,

View File

@ -1848,7 +1848,7 @@ static void pci_nic_uninit(PCIDevice *pci_dev)
} }
static NetClientInfo net_eepro100_info = { static NetClientInfo net_eepro100_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = nic_receive, .receive = nic_receive,
}; };

View File

@ -578,7 +578,7 @@ static const MemoryRegionOps eth_ops = {
}; };
static NetClientInfo net_etraxfs_info = { static NetClientInfo net_etraxfs_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = eth_receive, .receive = eth_receive,
.link_status_changed = eth_set_link, .link_status_changed = eth_set_link,

View File

@ -371,7 +371,7 @@ static void etsec_set_link_status(NetClientState *nc)
} }
static NetClientInfo net_etsec_info = { static NetClientInfo net_etsec_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = etsec_receive, .receive = etsec_receive,
.link_status_changed = etsec_set_link_status, .link_status_changed = etsec_set_link_status,

View File

@ -1147,7 +1147,7 @@ static void imx_eth_cleanup(NetClientState *nc)
} }
static NetClientInfo imx_eth_net_info = { static NetClientInfo imx_eth_net_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = imx_eth_can_receive, .can_receive = imx_eth_can_receive,
.receive = imx_eth_receive, .receive = imx_eth_receive,

View File

@ -1313,7 +1313,7 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = {
}; };
static NetClientInfo net_lan9118_info = { static NetClientInfo net_lan9118_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = lan9118_receive, .receive = lan9118_receive,
.link_status_changed = lan9118_set_link, .link_status_changed = lan9118_set_link,

View File

@ -93,7 +93,7 @@ static const MemoryRegionOps lance_mem_ops = {
}; };
static NetClientInfo net_lance_info = { static NetClientInfo net_lance_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = pcnet_receive, .receive = pcnet_receive,
.link_status_changed = pcnet_set_link_status, .link_status_changed = pcnet_set_link_status,

View File

@ -507,7 +507,7 @@ static const MemoryRegionOps mcf_fec_ops = {
}; };
static NetClientInfo net_mcf_fec_info = { static NetClientInfo net_mcf_fec_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = mcf_fec_receive, .receive = mcf_fec_receive,
}; };

View File

@ -447,7 +447,7 @@ static void milkymist_minimac2_reset(DeviceState *d)
} }
static NetClientInfo net_milkymist_minimac2_info = { static NetClientInfo net_milkymist_minimac2_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = minimac2_rx, .receive = minimac2_rx,
}; };

View File

@ -224,7 +224,7 @@ static const VMStateDescription vmstate_mipsnet = {
}; };
static NetClientInfo net_mipsnet_info = { static NetClientInfo net_mipsnet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = mipsnet_receive, .receive = mipsnet_receive,
}; };

View File

@ -44,7 +44,7 @@ typedef struct ISANE2000State {
} ISANE2000State; } ISANE2000State;
static NetClientInfo net_ne2000_isa_info = { static NetClientInfo net_ne2000_isa_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = ne2000_receive, .receive = ne2000_receive,
}; };

View File

@ -712,7 +712,7 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
} }
static NetClientInfo net_ne2000_info = { static NetClientInfo net_ne2000_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = ne2000_receive, .receive = ne2000_receive,
}; };

View File

@ -473,7 +473,7 @@ static ssize_t open_eth_receive(NetClientState *nc,
} }
static NetClientInfo net_open_eth_info = { static NetClientInfo net_open_eth_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = open_eth_can_receive, .can_receive = open_eth_can_receive,
.receive = open_eth_receive, .receive = open_eth_receive,

View File

@ -272,7 +272,7 @@ static void pci_pcnet_uninit(PCIDevice *dev)
} }
static NetClientInfo net_pci_pcnet_info = { static NetClientInfo net_pci_pcnet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = pcnet_receive, .receive = pcnet_receive,
.link_status_changed = pcnet_set_link_status, .link_status_changed = pcnet_set_link_status,

View File

@ -167,7 +167,7 @@ static void fp_port_set_link_status(NetClientState *nc)
} }
static NetClientInfo fp_port_info = { static NetClientInfo fp_port_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = fp_port_receive, .receive = fp_port_receive,
.receive_iov = fp_port_receive_iov, .receive_iov = fp_port_receive_iov,

View File

@ -3393,7 +3393,7 @@ static void rtl8139_set_link_status(NetClientState *nc)
} }
static NetClientInfo net_rtl8139_info = { static NetClientInfo net_rtl8139_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = rtl8139_can_receive, .can_receive = rtl8139_can_receive,
.receive = rtl8139_receive, .receive = rtl8139_receive,

View File

@ -755,7 +755,7 @@ static const MemoryRegionOps smc91c111_mem_ops = {
}; };
static NetClientInfo net_smc91c111_info = { static NetClientInfo net_smc91c111_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = smc91c111_can_receive_nc, .can_receive = smc91c111_can_receive_nc,
.receive = smc91c111_receive, .receive = smc91c111_receive,

View File

@ -278,7 +278,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
} }
static NetClientInfo net_spapr_vlan_info = { static NetClientInfo net_spapr_vlan_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = spapr_vlan_can_receive, .can_receive = spapr_vlan_can_receive,
.receive = spapr_vlan_receive, .receive = spapr_vlan_receive,

View File

@ -460,7 +460,7 @@ static void stellaris_enet_reset(stellaris_enet_state *s)
} }
static NetClientInfo net_stellaris_enet_info = { static NetClientInfo net_stellaris_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = stellaris_enet_receive, .receive = stellaris_enet_receive,
}; };

View File

@ -88,10 +88,10 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net)
const int *feature_bits = 0; const int *feature_bits = 0;
switch (net->nc->info->type) { switch (net->nc->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP: case NET_CLIENT_DRIVER_TAP:
feature_bits = kernel_feature_bits; feature_bits = kernel_feature_bits;
break; break;
case NET_CLIENT_OPTIONS_KIND_VHOST_USER: case NET_CLIENT_DRIVER_VHOST_USER:
feature_bits = user_feature_bits; feature_bits = user_feature_bits;
break; break;
default: default:
@ -128,7 +128,7 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net)
static int vhost_net_get_fd(NetClientState *backend) static int vhost_net_get_fd(NetClientState *backend)
{ {
switch (backend->info->type) { switch (backend->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP: case NET_CLIENT_DRIVER_TAP:
return tap_get_fd(backend); return tap_get_fd(backend);
default: default:
fprintf(stderr, "vhost-net requires tap backend\n"); 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. */ /* 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); features = vhost_user_get_acked_features(net->nc);
if (~net->dev.features & features) { if (~net->dev.features & features) {
fprintf(stderr, "vhost lacks feature mask %" PRIu64 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); 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); qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
file.fd = net->backend; file.fd = net->backend;
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 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; return 0;
fail: fail:
file.fd = -1; 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) { while (file.index-- > 0) {
const VhostOps *vhost_ops = net->dev.vhost_ops; const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file); 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 }; 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) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
const VhostOps *vhost_ops = net->dev.vhost_ops; const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file); 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 * because vhost user doesn't interrupt masking/unmasking
* properly. * 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; dev->use_guest_notifier_mask = false;
} }
} }
@ -413,10 +413,10 @@ VHostNetState *get_vhost_net(NetClientState *nc)
} }
switch (nc->info->type) { switch (nc->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP: case NET_CLIENT_DRIVER_TAP:
vhost_net = tap_get_vhost_net(nc); vhost_net = tap_get_vhost_net(nc);
break; break;
case NET_CLIENT_OPTIONS_KIND_VHOST_USER: case NET_CLIENT_DRIVER_VHOST_USER:
vhost_net = vhost_user_get_vhost_net(nc); vhost_net = vhost_user_get_vhost_net(nc);
break; break;
default: default:

View File

@ -468,11 +468,11 @@ static int peer_attach(VirtIONet *n, int index)
return 0; 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); 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; return 0;
} }
@ -487,11 +487,11 @@ static int peer_detach(VirtIONet *n, int index)
return 0; 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); 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; return 0;
} }
@ -1680,7 +1680,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
} }
static NetClientInfo net_virtio_info = { static NetClientInfo net_virtio_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = virtio_net_can_receive, .can_receive = virtio_net_can_receive,
.receive = virtio_net_receive, .receive = virtio_net_receive,

View File

@ -2087,7 +2087,7 @@ static void vmxnet3_set_link_status(NetClientState *nc)
} }
static NetClientInfo net_vmxnet3_info = { static NetClientInfo net_vmxnet3_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = vmxnet3_receive, .receive = vmxnet3_receive,
.link_status_changed = vmxnet3_set_link_status, .link_status_changed = vmxnet3_set_link_status,

View File

@ -269,7 +269,7 @@ static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static NetClientInfo net_xen_info = { static NetClientInfo net_xen_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = net_rx_packet, .receive = net_rx_packet,
}; };

View File

@ -371,7 +371,7 @@ out:
} }
static NetClientInfo net_xgmac_enet_info = { static NetClientInfo net_xgmac_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = eth_rx, .receive = eth_rx,
}; };

View File

@ -935,7 +935,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
} }
static NetClientInfo net_xilinx_enet_info = { static NetClientInfo net_xilinx_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = eth_rx, .receive = eth_rx,
}; };

View File

@ -217,7 +217,7 @@ static void xilinx_ethlite_reset(DeviceState *dev)
} }
static NetClientInfo net_xilinx_ethlite_info = { static NetClientInfo net_xilinx_ethlite_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = eth_can_rx, .can_receive = eth_can_rx,
.receive = eth_rx, .receive = eth_rx,

View File

@ -1334,7 +1334,7 @@ static void usb_net_handle_destroy(USBDevice *dev)
} }
static NetClientInfo net_usbnet_info = { static NetClientInfo net_usbnet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.receive = usbnet_receive, .receive = usbnet_receive,
.cleanup = usbnet_cleanup, .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, "type", "nic", &error_abort);
qemu_opt_set(opts, "model", "usb", &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) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
return NULL; return NULL;

View File

@ -66,7 +66,7 @@ typedef struct SocketReadState SocketReadState;
typedef void (SocketReadStateFinalize)(SocketReadState *rs); typedef void (SocketReadStateFinalize)(SocketReadState *rs);
typedef struct NetClientInfo { typedef struct NetClientInfo {
NetClientOptionsKind type; NetClientDriver type;
size_t size; size_t size;
NetReceive *receive; NetReceive *receive;
NetReceive *receive_raw; 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); char *qemu_mac_strdup_printf(const uint8_t *macaddr);
NetClientState *qemu_find_netdev(const char *id); NetClientState *qemu_find_netdev(const char *id);
int qemu_find_net_clients_except(const char *id, NetClientState **ncs, 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 *qemu_new_net_client(NetClientInfo *info,
NetClientState *peer, NetClientState *peer,
const char *model, const char *model,
@ -203,7 +203,7 @@ extern const char *host_net_devices[];
extern const char *legacy_tftp_prefix; extern const char *legacy_tftp_prefix;
extern const char *legacy_bootp_filename; 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_client_parse(QemuOptsList *opts_list, const char *str);
int net_init_clients(void); int net_init_clients(void);
void net_check_clients(void); void net_check_clients(void);

View File

@ -3080,8 +3080,8 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
} }
len = strlen(str); len = strlen(str);
readline_set_completion_index(rs, len); readline_set_completion_index(rs, len);
for (i = 0; NetClientOptionsKind_lookup[i]; i++) { for (i = 0; NetClientDriver_lookup[i]; i++) {
add_completion_option(rs, str, NetClientOptionsKind_lookup[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]; NetClientState *ncs[MAX_QUEUE_NUM];
int count, i; int count, i;
count = qemu_find_net_clients_except(NULL, ncs, count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NONE, NET_CLIENT_DRIVER_NONE,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
const char *name = ncs[i]->name; 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); len = strlen(str);
readline_set_completion_index(rs, len); 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); MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
QemuOpts *opts; 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); readline_set_completion_index(rs, len);
if (nb_args == 2) { if (nb_args == 2) {
count = qemu_find_net_clients_except(NULL, ncs, count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NONE, NET_CLIENT_DRIVER_NONE,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id; int id;
@ -3452,13 +3452,13 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
return; return;
} else if (nb_args == 3) { } else if (nb_args == 3) {
count = qemu_find_net_clients_except(NULL, ncs, count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NIC, NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id; int id;
const char *name; 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)) { net_hub_id_for_client(ncs[i], &id)) {
continue; continue;
} }

View File

@ -27,39 +27,39 @@
#include "net/net.h" #include "net/net.h"
#include "qapi-types.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); NetClientState *peer, Error **errp);
#ifdef CONFIG_SLIRP #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); NetClientState *peer, Error **errp);
#endif #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); 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); 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); 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); 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); NetClientState *peer, Error **errp);
#ifdef CONFIG_VDE #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); NetClientState *peer, Error **errp);
#endif #endif
#ifdef CONFIG_NETMAP #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); NetClientState *peer, Error **errp);
#endif #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); NetClientState *peer, Error **errp);
#endif /* QEMU_NET_CLIENTS_H */ #endif /* QEMU_NET_CLIENTS_H */

View File

@ -172,14 +172,14 @@ static void dumpclient_cleanup(NetClientState *nc)
} }
static NetClientInfo net_dump_info = { static NetClientInfo net_dump_info = {
.type = NET_CLIENT_OPTIONS_KIND_DUMP, .type = NET_CLIENT_DRIVER_DUMP,
.size = sizeof(DumpNetClient), .size = sizeof(DumpNetClient),
.receive = dumpclient_receive, .receive = dumpclient_receive,
.receive_iov = dumpclient_receive_iov, .receive_iov = dumpclient_receive_iov,
.cleanup = dumpclient_cleanup, .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) NetClientState *peer, Error **errp)
{ {
int len, rc; int len, rc;
@ -189,8 +189,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
NetClientState *nc; NetClientState *nc;
DumpNetClient *dnc; DumpNetClient *dnc;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_DUMP); assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
dump = opts->u.dump.data; dump = &netdev->u.dump;
assert(peer); assert(peer);

View File

@ -201,7 +201,7 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
} }
queues = qemu_find_net_clients_except(nf->netdev_id, ncs, queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
NET_CLIENT_OPTIONS_KIND_NIC, NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
if (queues < 1) { if (queues < 1) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev", error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",

View File

@ -131,7 +131,7 @@ static void net_hub_port_cleanup(NetClientState *nc)
} }
static NetClientInfo net_hub_port_info = { static NetClientInfo net_hub_port_info = {
.type = NET_CLIENT_OPTIONS_KIND_HUBPORT, .type = NET_CLIENT_DRIVER_HUBPORT,
.size = sizeof(NetHubPort), .size = sizeof(NetHubPort),
.can_receive = net_hub_port_can_receive, .can_receive = net_hub_port_can_receive,
.receive = net_hub_port_receive, .receive = net_hub_port_receive,
@ -266,10 +266,10 @@ int net_hub_id_for_client(NetClientState *nc, int *id)
{ {
NetHubPort *port; 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); port = DO_UPCAST(NetHubPort, nc, nc);
} else if (nc->peer != NULL && nc->peer->info->type == } 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); port = DO_UPCAST(NetHubPort, nc, nc->peer);
} else { } else {
return -ENOENT; return -ENOENT;
@ -281,14 +281,14 @@ int net_hub_id_for_client(NetClientState *nc, int *id)
return 0; 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) NetClientState *peer, Error **errp)
{ {
const NetdevHubPortOptions *hubport; const NetdevHubPortOptions *hubport;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT); assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
assert(!peer); assert(!peer);
hubport = opts->u.hubport.data; hubport = &netdev->u.hubport;
net_hub_add_port(hubport->hubid, name); net_hub_add_port(hubport->hubid, name);
return 0; return 0;
@ -315,14 +315,14 @@ void net_hub_check_clients(void)
} }
switch (peer->info->type) { switch (peer->info->type) {
case NET_CLIENT_OPTIONS_KIND_NIC: case NET_CLIENT_DRIVER_NIC:
has_nic = 1; has_nic = 1;
break; break;
case NET_CLIENT_OPTIONS_KIND_USER: case NET_CLIENT_DRIVER_USER:
case NET_CLIENT_OPTIONS_KIND_TAP: case NET_CLIENT_DRIVER_TAP:
case NET_CLIENT_OPTIONS_KIND_SOCKET: case NET_CLIENT_DRIVER_SOCKET:
case NET_CLIENT_OPTIONS_KIND_VDE: case NET_CLIENT_DRIVER_VDE:
case NET_CLIENT_OPTIONS_KIND_VHOST_USER: case NET_CLIENT_DRIVER_VHOST_USER:
has_host_dev = 1; has_host_dev = 1;
break; break;
default: default:

View File

@ -516,7 +516,7 @@ static void net_l2tpv3_cleanup(NetClientState *nc)
} }
static NetClientInfo net_l2tpv3_info = { static NetClientInfo net_l2tpv3_info = {
.type = NET_CLIENT_OPTIONS_KIND_L2TPV3, .type = NET_CLIENT_DRIVER_L2TPV3,
.size = sizeof(NetL2TPV3State), .size = sizeof(NetL2TPV3State),
.receive = net_l2tpv3_receive_dgram, .receive = net_l2tpv3_receive_dgram,
.receive_iov = net_l2tpv3_receive_dgram_iov, .receive_iov = net_l2tpv3_receive_dgram_iov,
@ -524,7 +524,7 @@ static NetClientInfo net_l2tpv3_info = {
.cleanup = net_l2tpv3_cleanup, .cleanup = net_l2tpv3_cleanup,
}; };
int net_init_l2tpv3(const NetClientOptions *opts, int net_init_l2tpv3(const Netdev *netdev,
const char *name, const char *name,
NetClientState *peer, Error **errp) NetClientState *peer, Error **errp)
{ {
@ -545,8 +545,8 @@ int net_init_l2tpv3(const NetClientOptions *opts,
s->queue_tail = 0; s->queue_tail = 0;
s->header_mismatch = false; s->header_mismatch = false;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3); assert(netdev->type == NET_CLIENT_DRIVER_L2TPV3);
l2tpv3 = opts->u.l2tpv3.data; l2tpv3 = &netdev->u.l2tpv3;
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) { if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
s->ipv6 = l2tpv3->ipv6; s->ipv6 = l2tpv3->ipv6;

155
net/net.c
View File

@ -289,7 +289,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
NICState *nic; NICState *nic;
int i, queues = MAX(1, conf->peers.queues); 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)); assert(info->size >= sizeof(NICState));
nic = g_malloc0(info->size + sizeof(NetClientState) * queues); nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
@ -360,13 +360,13 @@ void qemu_del_net_client(NetClientState *nc)
int queues, i; int queues, i;
NetFilterState *nf, *next; 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 /* If the NetClientState belongs to a multiqueue backend, we will change all
* other NetClientStates also. * other NetClientStates also.
*/ */
queues = qemu_find_net_clients_except(nc->name, ncs, queues = qemu_find_net_clients_except(nc->name, ncs,
NET_CLIENT_OPTIONS_KIND_NIC, NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
assert(queues != 0); 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 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); NICState *nic = qemu_get_nic(nc->peer);
if (nic->peer_deleted) { if (nic->peer_deleted) {
return; return;
@ -431,7 +431,7 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
NetClientState *nc; NetClientState *nc;
QTAILQ_FOREACH(nc, &net_clients, next) { 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) { if (nc->queue_index == 0) {
func(qemu_get_nic(nc), opaque); 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; 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)) { if (net_hub_flush(nc->peer)) {
qemu_notify_event(); qemu_notify_event();
} }
@ -777,7 +777,7 @@ NetClientState *qemu_find_netdev(const char *id)
NetClientState *nc; NetClientState *nc;
QTAILQ_FOREACH(nc, &net_clients, next) { QTAILQ_FOREACH(nc, &net_clients, next) {
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) if (nc->info->type == NET_CLIENT_DRIVER_NIC)
continue; continue;
if (!strcmp(nc->name, id)) { if (!strcmp(nc->name, id)) {
return nc; return nc;
@ -788,7 +788,7 @@ NetClientState *qemu_find_netdev(const char *id)
} }
int qemu_find_net_clients_except(const char *id, NetClientState **ncs, int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
NetClientOptionsKind type, int max) NetClientDriver type, int max)
{ {
NetClientState *nc; NetClientState *nc;
int ret = 0; int ret = 0;
@ -862,15 +862,15 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
return -1; 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) NetClientState *peer, Error **errp)
{ {
int idx; int idx;
NICInfo *nd; NICInfo *nd;
const NetLegacyNicOptions *nic; const NetLegacyNicOptions *nic;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC); assert(netdev->type == NET_CLIENT_DRIVER_NIC);
nic = opts->u.nic.data; nic = &netdev->u.nic;
idx = nic_get_free_idx(); idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) { 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])( static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
const NetClientOptions *opts, const Netdev *netdev,
const char *name, const char *name,
NetClientState *peer, Error **errp) = { NetClientState *peer, Error **errp) = {
[NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, [NET_CLIENT_DRIVER_NIC] = net_init_nic,
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
[NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, [NET_CLIENT_DRIVER_USER] = net_init_slirp,
#endif #endif
[NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, [NET_CLIENT_DRIVER_TAP] = net_init_tap,
[NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, [NET_CLIENT_DRIVER_SOCKET] = net_init_socket,
#ifdef CONFIG_VDE #ifdef CONFIG_VDE
[NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, [NET_CLIENT_DRIVER_VDE] = net_init_vde,
#endif #endif
#ifdef CONFIG_NETMAP #ifdef CONFIG_NETMAP
[NET_CLIENT_OPTIONS_KIND_NETMAP] = net_init_netmap, [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
#endif #endif
[NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, [NET_CLIENT_DRIVER_DUMP] = net_init_dump,
#ifdef CONFIG_NET_BRIDGE #ifdef CONFIG_NET_BRIDGE
[NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
#endif #endif
[NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport, [NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
#ifdef CONFIG_VHOST_NET_USED #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 #endif
#ifdef CONFIG_L2TPV3 #ifdef CONFIG_L2TPV3
[NET_CLIENT_OPTIONS_KIND_L2TPV3] = net_init_l2tpv3, [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
#endif #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; const char *name;
NetClientState *peer = NULL; NetClientState *peer = NULL;
if (is_netdev) { if (is_netdev) {
const Netdev *netdev = object; netdev = object;
opts = netdev->opts;
name = netdev->id; name = netdev->id;
if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP || if (netdev->type == NET_CLIENT_DRIVER_DUMP ||
opts->type == NET_CLIENT_OPTIONS_KIND_NIC || netdev->type == NET_CLIENT_DRIVER_NIC ||
!net_client_init_fun[opts->type]) { !net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a netdev backend type"); "a netdev backend type");
return -1; return -1;
} }
} else { } else {
const NetLegacy *net = object; 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" */ /* missing optional values have been initialized to "all bits zero" */
name = net->has_id ? net->id : net->name; 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 */ return 0; /* nothing to do */
} case NET_LEGACY_OPTIONS_KIND_NIC:
if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { legacy.type = NET_CLIENT_DRIVER_NIC;
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", legacy.u.nic = *opts->u.nic.data;
"a net type"); break;
return -1; 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", error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net backend type (maybe it is not compiled " "a net backend type (maybe it is not compiled "
"into this binary)"); "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. */ /* 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) { !opts->u.nic.data->has_netdev) {
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL); 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 */ /* FIXME drop when all init functions store an Error */
if (errp && !*errp) { if (errp && !*errp) {
error_setg(errp, QERR_DEVICE_INIT_FAILED, error_setg(errp, QERR_DEVICE_INIT_FAILED,
NetClientOptionsKind_lookup[opts->type]); NetClientDriver_lookup[netdev->type]);
} }
return -1; 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; void *object = NULL;
Error *err = 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); 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) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
monitor_printf(mon, "adding host network device %s failed\n", device); 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); device, vlan_id);
return; 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); error_report("invalid host network device '%s'", device);
return; return;
} }
@ -1142,7 +1183,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
void netdev_add(QemuOpts *opts, Error **errp) 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) 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, monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
nc->queue_index, nc->queue_index,
NetClientOptionsKind_lookup[nc->info->type], NetClientDriver_lookup[nc->info->type],
nc->info_str); nc->info_str);
if (!QTAILQ_EMPTY(&nc->filters)) { if (!QTAILQ_EMPTY(&nc->filters)) {
monitor_printf(mon, "filters:\n"); 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 */ /* 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) { if (has_name) {
error_setg(errp, "net client(%s) isn't a NIC", name); error_setg(errp, "net client(%s) isn't a NIC", name);
return NULL; 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) void hmp_info_network(Monitor *mon, const QDict *qdict)
{ {
NetClientState *nc, *peer; NetClientState *nc, *peer;
NetClientOptionsKind type; NetClientDriver type;
net_hub_info(mon); net_hub_info(mon);
@ -1311,10 +1352,10 @@ void hmp_info_network(Monitor *mon, const QDict *qdict)
continue; continue;
} }
if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) { if (!peer || type == NET_CLIENT_DRIVER_NIC) {
print_net_client(mon, nc); print_net_client(mon, nc);
} /* else it's a netdev connected to a NIC, printed with the NIC */ } /* 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, " \\ "); monitor_printf(mon, " \\ ");
print_net_client(mon, peer); print_net_client(mon, peer);
} }
@ -1328,7 +1369,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
int queues, i; int queues, i;
queues = qemu_find_net_clients_except(name, ncs, queues = qemu_find_net_clients_except(name, ncs,
NET_CLIENT_OPTIONS_KIND__MAX, NET_CLIENT_DRIVER__MAX,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
if (queues == 0) { 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 * multiple clients that can still communicate with each other in
* disconnected mode. For now maintain this compatibility. * 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++) { for (i = 0; i < queues; i++) {
ncs[i]->peer->link_down = !up; ncs[i]->peer->link_down = !up;
} }
@ -1396,7 +1437,7 @@ void net_cleanup(void)
*/ */
while (!QTAILQ_EMPTY(&net_clients)) { while (!QTAILQ_EMPTY(&net_clients)) {
nc = QTAILQ_FIRST(&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)); qemu_del_nic(qemu_get_nic(nc));
} else { } else {
qemu_del_net_client(nc); qemu_del_net_client(nc);
@ -1416,7 +1457,7 @@ void net_check_clients(void)
QTAILQ_FOREACH(nc, &net_clients, next) { QTAILQ_FOREACH(nc, &net_clients, next) {
if (!nc->peer) { if (!nc->peer) {
fprintf(stderr, "Warning: %s %s has no peer\n", 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); "nic" : "netdev", nc->name);
} }
} }
@ -1440,7 +1481,7 @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
net_client_init(opts, 0, &local_err); net_client_init(opts, false, &local_err);
if (local_err) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
return -1; return -1;
@ -1454,7 +1495,7 @@ static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
ret = net_client_init(opts, 1, &local_err); ret = net_client_init(opts, true, &local_err);
if (local_err) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
return -1; return -1;

View File

@ -400,7 +400,7 @@ static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
/* NetClientInfo methods */ /* NetClientInfo methods */
static NetClientInfo net_netmap_info = { static NetClientInfo net_netmap_info = {
.type = NET_CLIENT_OPTIONS_KIND_NETMAP, .type = NET_CLIENT_DRIVER_NETMAP,
.size = sizeof(NetmapState), .size = sizeof(NetmapState),
.receive = netmap_receive, .receive = netmap_receive,
.receive_iov = netmap_receive_iov, .receive_iov = netmap_receive_iov,
@ -418,10 +418,10 @@ static NetClientInfo net_netmap_info = {
* *
* ... -net netmap,ifname="..." * ... -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 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; struct nm_desc *nmd;
NetClientState *nc; NetClientState *nc;
Error *err = NULL; Error *err = NULL;

View File

@ -137,7 +137,7 @@ static void net_slirp_cleanup(NetClientState *nc)
} }
static NetClientInfo net_slirp_info = { static NetClientInfo net_slirp_info = {
.type = NET_CLIENT_OPTIONS_KIND_USER, .type = NET_CLIENT_DRIVER_USER,
.size = sizeof(SlirpState), .size = sizeof(SlirpState),
.receive = net_slirp_receive, .receive = net_slirp_receive,
.cleanup = net_slirp_cleanup, .cleanup = net_slirp_cleanup,
@ -828,7 +828,7 @@ static const char **slirp_dnssearch(const StringList *dnsname)
return ret; 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) NetClientState *peer, Error **errp)
{ {
/* FIXME error_setg(errp, ...) on failure */ /* FIXME error_setg(errp, ...) on failure */
@ -839,8 +839,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
const char **dnssearch; const char **dnssearch;
bool ipv4 = true, ipv6 = true; bool ipv4 = true, ipv6 = true;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER); assert(netdev->type == NET_CLIENT_DRIVER_USER);
user = opts->u.user.data; user = &netdev->u.user;
if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) || if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
(user->has_ipv4 && !user->ipv4)) { (user->has_ipv4 && !user->ipv4)) {

View File

@ -311,7 +311,7 @@ static void net_socket_cleanup(NetClientState *nc)
} }
static NetClientInfo net_dgram_socket_info = { static NetClientInfo net_dgram_socket_info = {
.type = NET_CLIENT_OPTIONS_KIND_SOCKET, .type = NET_CLIENT_DRIVER_SOCKET,
.size = sizeof(NetSocketState), .size = sizeof(NetSocketState),
.receive = net_socket_receive_dgram, .receive = net_socket_receive_dgram,
.cleanup = net_socket_cleanup, .cleanup = net_socket_cleanup,
@ -395,7 +395,7 @@ static void net_socket_connect(void *opaque)
} }
static NetClientInfo net_socket_info = { static NetClientInfo net_socket_info = {
.type = NET_CLIENT_OPTIONS_KIND_SOCKET, .type = NET_CLIENT_DRIVER_SOCKET,
.size = sizeof(NetSocketState), .size = sizeof(NetSocketState),
.receive = net_socket_receive, .receive = net_socket_receive,
.cleanup = net_socket_cleanup, .cleanup = net_socket_cleanup,
@ -663,15 +663,15 @@ static int net_socket_udp_init(NetClientState *peer,
return 0; 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) NetClientState *peer, Error **errp)
{ {
/* FIXME error_setg(errp, ...) on failure */ /* FIXME error_setg(errp, ...) on failure */
Error *err = NULL; Error *err = NULL;
const NetdevSocketOptions *sock; const NetdevSocketOptions *sock;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET); assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
sock = opts->u.socket.data; sock = &netdev->u.socket;
if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast + if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
sock->has_udp != 1) { sock->has_udp != 1) {

View File

@ -750,7 +750,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
} }
static NetClientInfo net_tap_win32_info = { static NetClientInfo net_tap_win32_info = {
.type = NET_CLIENT_OPTIONS_KIND_TAP, .type = NET_CLIENT_DRIVER_TAP,
.size = sizeof(TAPState), .size = sizeof(TAPState),
.receive = tap_receive, .receive = tap_receive,
.cleanup = tap_cleanup, .cleanup = tap_cleanup,
@ -788,14 +788,14 @@ static int tap_win32_init(NetClientState *peer, const char *model,
return 0; 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) NetClientState *peer, Error **errp)
{ {
/* FIXME error_setg(errp, ...) on failure */ /* FIXME error_setg(errp, ...) on failure */
const NetdevTapOptions *tap; const NetdevTapOptions *tap;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP); assert(netdev->type == NET_CLIENT_DRIVER_TAP);
tap = opts->u.tap.data; tap = &netdev->u.tap;
if (!tap->has_ifname) { if (!tap->has_ifname) {
error_report("tap: no interface name"); error_report("tap: no interface name");

View File

@ -223,7 +223,7 @@ static bool tap_has_ufo(NetClientState *nc)
{ {
TAPState *s = DO_UPCAST(TAPState, nc, 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; return s->has_ufo;
} }
@ -232,7 +232,7 @@ static bool tap_has_vnet_hdr(NetClientState *nc)
{ {
TAPState *s = DO_UPCAST(TAPState, nc, 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; 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); 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); 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); 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) || assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
len == sizeof(struct virtio_net_hdr)); 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); 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); assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
s->using_vnet_hdr = 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) int tap_get_fd(NetClientState *nc)
{ {
TAPState *s = DO_UPCAST(TAPState, nc, 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; return s->fd;
} }
/* fd support */ /* fd support */
static NetClientInfo net_tap_info = { static NetClientInfo net_tap_info = {
.type = NET_CLIENT_OPTIONS_KIND_TAP, .type = NET_CLIENT_DRIVER_TAP,
.size = sizeof(TAPState), .size = sizeof(TAPState),
.receive = tap_receive, .receive = tap_receive,
.receive_raw = tap_receive_raw, .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) NetClientState *peer, Error **errp)
{ {
const NetdevBridgeOptions *bridge; const NetdevBridgeOptions *bridge;
@ -579,8 +579,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
TAPState *s; TAPState *s;
int fd, vnet_hdr; int fd, vnet_hdr;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE); assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
bridge = opts->u.bridge.data; bridge = &netdev->u.bridge;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER; helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE; 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; 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) NetClientState *peer, Error **errp)
{ {
const NetdevTapOptions *tap; const NetdevTapOptions *tap;
@ -747,8 +747,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
const char *vhostfdname; const char *vhostfdname;
char ifname[128]; char ifname[128];
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP); assert(netdev->type == NET_CLIENT_DRIVER_TAP);
tap = opts->u.tap.data; tap = &netdev->u.tap;
queues = tap->has_queues ? tap->queues : 1; queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
@ -921,7 +921,7 @@ free_fail:
VHostNetState *tap_get_vhost_net(NetClientState *nc) VHostNetState *tap_get_vhost_net(NetClientState *nc)
{ {
TAPState *s = DO_UPCAST(TAPState, nc, 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; return s->vhost_net;
} }

View File

@ -68,7 +68,7 @@ static void vde_cleanup(NetClientState *nc)
} }
static NetClientInfo net_vde_info = { static NetClientInfo net_vde_info = {
.type = NET_CLIENT_OPTIONS_KIND_VDE, .type = NET_CLIENT_DRIVER_VDE,
.size = sizeof(VDEState), .size = sizeof(VDEState),
.receive = vde_receive, .receive = vde_receive,
.cleanup = vde_cleanup, .cleanup = vde_cleanup,
@ -109,14 +109,14 @@ static int net_vde_init(NetClientState *peer, const char *model,
return 0; 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) NetClientState *peer, Error **errp)
{ {
/* FIXME error_setg(errp, ...) on failure */ /* FIXME error_setg(errp, ...) on failure */
const NetdevVdeOptions *vde; const NetdevVdeOptions *vde;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VDE); assert(netdev->type == NET_CLIENT_DRIVER_VDE);
vde = opts->u.vde.data; vde = &netdev->u.vde;
/* missing optional values have been initialized to "all bits zero" */ /* missing optional values have been initialized to "all bits zero" */
if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group, if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group,

View File

@ -34,14 +34,14 @@ typedef struct VhostUserChardevProps {
VHostNetState *vhost_user_get_vhost_net(NetClientState *nc) VHostNetState *vhost_user_get_vhost_net(NetClientState *nc)
{ {
VhostUserState *s = DO_UPCAST(VhostUserState, nc, 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; return s->vhost_net;
} }
uint64_t vhost_user_get_acked_features(NetClientState *nc) uint64_t vhost_user_get_acked_features(NetClientState *nc)
{ {
VhostUserState *s = DO_UPCAST(VhostUserState, nc, 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; return s->acked_features;
} }
@ -56,7 +56,7 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
int i; int i;
for (i = 0; i < queues; 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]); s = DO_UPCAST(VhostUserState, nc, ncs[i]);
if (!vhost_user_running(s)) { 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; options.backend_type = VHOST_BACKEND_TYPE_USER;
for (i = 0; i < queues; 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]); s = DO_UPCAST(VhostUserState, nc, ncs[i]);
if (vhost_user_running(s)) { 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) 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; return true;
} }
static bool vhost_user_has_ufo(NetClientState *nc) 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; return true;
} }
static NetClientInfo net_vhost_user_info = { static NetClientInfo net_vhost_user_info = {
.type = NET_CLIENT_OPTIONS_KIND_VHOST_USER, .type = NET_CLIENT_DRIVER_VHOST_USER,
.size = sizeof(VhostUserState), .size = sizeof(VhostUserState),
.receive = vhost_user_receive, .receive = vhost_user_receive,
.cleanup = vhost_user_cleanup, .cleanup = vhost_user_cleanup,
@ -207,7 +207,7 @@ static void net_vhost_user_event(void *opaque, int event)
int queues; int queues;
queues = qemu_find_net_clients_except(name, ncs, queues = qemu_find_net_clients_except(name, ncs,
NET_CLIENT_OPTIONS_KIND_NIC, NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM); MAX_QUEUE_NUM);
assert(queues < 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; 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) NetClientState *peer, Error **errp)
{ {
int queues; int queues;
const NetdevVhostUserOptions *vhost_user_opts; const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr; CharDriverState *chr;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER); assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER);
vhost_user_opts = opts->u.vhost_user.data; vhost_user_opts = &netdev->u.vhost_user;
chr = net_vhost_parse_chardev(vhost_user_opts, errp); chr = net_vhost_parse_chardev(vhost_user_opts, errp);
if (!chr) { if (!chr) {

View File

@ -2809,16 +2809,32 @@
'*queues': 'int' } } '*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 # Since 1.2
# #
# 'l2tpv3' - since 2.1 # 'l2tpv3' - since 2.1
#
## ##
{ 'union': 'NetClientOptions', { 'union': 'Netdev',
'base': { 'id': 'str', 'type': 'NetClientDriver' },
'discriminator': 'type',
'data': { 'data': {
'none': 'NetdevNoneOptions', 'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions', 'nic': 'NetLegacyNicOptions',
@ -2853,23 +2869,28 @@
'*vlan': 'int32', '*vlan': 'int32',
'*id': 'str', '*id': 'str',
'*name': 'str', '*name': 'str',
'opts': 'NetClientOptions' } } 'opts': 'NetLegacyOptions' } }
## ##
# @Netdev # @NetLegacyOptions
# #
# Captures the configuration of a network device. # Like Netdev, but for use only by the legacy command line options
#
# @id: identifier for monitor commands.
#
# @opts: device type specific properties
# #
# Since 1.2 # Since 1.2
## ##
{ 'struct': 'Netdev', { 'union': 'NetLegacyOptions',
'data': { 'data': {
'id': 'str', 'none': 'NetdevNoneOptions',
'opts': 'NetClientOptions' } } 'nic': 'NetLegacyNicOptions',
'user': 'NetdevUserOptions',
'tap': 'NetdevTapOptions',
'l2tpv3': 'NetdevL2TPv3Options',
'socket': 'NetdevSocketOptions',
'vde': 'NetdevVdeOptions',
'dump': 'NetdevDumpOptions',
'bridge': 'NetdevBridgeOptions',
'netmap': 'NetdevNetmapOptions',
'vhost-user': 'NetdevVhostUserOptions' } }
## ##
# @NetFilterDirection # @NetFilterDirection

View File

@ -1120,6 +1120,21 @@
# #
# Start mirroring a block device's writes to a new destination. # 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 # @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7) # omitted, the device name will be used. (Since 2.7)
# #
@ -1169,12 +1184,9 @@
# written. Both will result in identical contents. # written. Both will result in identical contents.
# Default is true. (Since 2.4) # Default is true. (Since 2.4)
# #
# Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound
#
# Since 1.3 # Since 1.3
## ##
{ 'command': 'drive-mirror', { 'struct': 'DriveMirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*format': 'str', '*node-name': 'str', '*replaces': 'str', '*format': 'str', '*node-name': 'str', '*replaces': 'str',
'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
@ -1330,6 +1342,21 @@
# the device will be removed from its group and the rest of its # the device will be removed from its group and the rest of its
# members will not be affected. The 'group' parameter is ignored. # 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 # @device: The name of the device
# #
# @bps: total throughput limit in bytes per second # @bps: total throughput limit in bytes per second
@ -1396,12 +1423,9 @@
# #
# @group: #optional throttle group name (Since 2.4) # @group: #optional throttle group name (Since 2.4)
# #
# Returns: Nothing on success
# If @device is not a valid block device, DeviceNotFound
#
# Since: 1.1 # Since: 1.1
## ##
{ 'command': 'block_set_io_throttle', { 'struct': 'BlockIOThrottle',
'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', 'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
'*bps_max': 'int', '*bps_rd_max': 'int', '*bps_max': 'int', '*bps_rd_max': 'int',

View File

@ -30,6 +30,8 @@ typedef struct StackObject
GHashTable *h; /* If obj is dict: unvisited keys */ GHashTable *h; /* If obj is dict: unvisited keys */
const QListEntry *entry; /* If obj is list: unvisited tail */ const QListEntry *entry; /* If obj is list: unvisited tail */
QSLIST_ENTRY(StackObject) node;
} StackObject; } StackObject;
struct QmpInputVisitor struct QmpInputVisitor
@ -41,8 +43,7 @@ struct QmpInputVisitor
/* Stack of objects being visited (all entries will be either /* Stack of objects being visited (all entries will be either
* QDict or QList). */ * QDict or QList). */
StackObject stack[QIV_STACK_SIZE]; QSLIST_HEAD(, StackObject) stack;
int nb_stack;
/* True to reject parse in visit_end_struct() if unvisited keys remain. */ /* True to reject parse in visit_end_struct() if unvisited keys remain. */
bool strict; bool strict;
@ -61,13 +62,13 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
QObject *qobj; QObject *qobj;
QObject *ret; QObject *ret;
if (!qiv->nb_stack) { if (QSLIST_EMPTY(&qiv->stack)) {
/* Starting at root, name is ignored. */ /* Starting at root, name is ignored. */
return qiv->root; return qiv->root;
} }
/* We are in a container; find the next element. */ /* We are in a container; find the next element. */
tos = &qiv->stack[qiv->nb_stack - 1]; tos = QSLIST_FIRST(&qiv->stack);
qobj = tos->obj; qobj = tos->obj;
assert(qobj); assert(qobj);
@ -100,18 +101,11 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
void *qapi, Error **errp) void *qapi, Error **errp)
{ {
GHashTable *h; GHashTable *h;
StackObject *tos = &qiv->stack[qiv->nb_stack]; StackObject *tos = g_new0(StackObject, 1);
assert(obj); assert(obj);
if (qiv->nb_stack >= QIV_STACK_SIZE) {
error_setg(errp, "An internal buffer overran");
return NULL;
}
tos->obj = obj; tos->obj = obj;
tos->qapi = qapi; tos->qapi = qapi;
assert(!tos->h);
assert(!tos->entry);
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) { if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
h = g_hash_table_new(g_str_hash, g_str_equal); 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)); tos->entry = qlist_first(qobject_to_qlist(obj));
} }
qiv->nb_stack++; QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
return tos->entry; 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) static void qmp_input_check_struct(Visitor *v, Error **errp)
{ {
QmpInputVisitor *qiv = to_qiv(v); 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 && !tos->entry);
if (qiv->strict) { if (qiv->strict) {
GHashTable *const top_ht = tos->h; GHashTable *const top_ht = tos->h;
if (top_ht) { 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) static void qmp_input_pop(Visitor *v, void **obj)
{ {
QmpInputVisitor *qiv = to_qiv(v); 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 && tos->qapi == obj);
assert(tos->qapi == obj); QSLIST_REMOVE_HEAD(&qiv->stack, node);
qmp_input_stack_object_free(tos);
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--;
} }
static void qmp_input_start_struct(Visitor *v, const char *name, void **obj, 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) size_t size)
{ {
QmpInputVisitor *qiv = to_qiv(v); QmpInputVisitor *qiv = to_qiv(v);
StackObject *so = &qiv->stack[qiv->nb_stack - 1]; StackObject *so = QSLIST_FIRST(&qiv->stack);
if (!so->entry) { if (!so->entry) {
return NULL; 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) static void qmp_input_free(Visitor *v)
{ {
QmpInputVisitor *qiv = to_qiv(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); qobject_decref(qiv->root);
g_free(qiv); g_free(qiv);

View File

@ -23,15 +23,13 @@ typedef struct QStackEntry
{ {
QObject *value; QObject *value;
void *qapi; /* sanity check that caller uses same pointer */ void *qapi; /* sanity check that caller uses same pointer */
QTAILQ_ENTRY(QStackEntry) node; QSLIST_ENTRY(QStackEntry) node;
} QStackEntry; } QStackEntry;
typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
struct QmpOutputVisitor struct QmpOutputVisitor
{ {
Visitor visitor; 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 *root; /* Root of the output visit */
QObject **result; /* User's storage location for result */ QObject **result; /* User's storage location for result */
}; };
@ -56,18 +54,18 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value,
assert(value); assert(value);
e->value = value; e->value = value;
e->qapi = qapi; 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. */ /* Pop a value off the stack of QObjects being built, and return it. */
static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi) static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
{ {
QStackEntry *e = QTAILQ_FIRST(&qov->stack); QStackEntry *e = QSLIST_FIRST(&qov->stack);
QObject *value; QObject *value;
assert(e); assert(e);
assert(e->qapi == qapi); assert(e->qapi == qapi);
QTAILQ_REMOVE(&qov->stack, e, node); QSLIST_REMOVE_HEAD(&qov->stack, node);
value = e->value; value = e->value;
assert(value); assert(value);
g_free(e); 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, static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
QObject *value) QObject *value)
{ {
QStackEntry *e = QTAILQ_FIRST(&qov->stack); QStackEntry *e = QSLIST_FIRST(&qov->stack);
QObject *cur = e ? e->value : NULL; QObject *cur = e ? e->value : NULL;
if (!cur) { if (!cur) {
@ -206,7 +204,7 @@ static void qmp_output_complete(Visitor *v, void *opaque)
QmpOutputVisitor *qov = to_qov(v); QmpOutputVisitor *qov = to_qov(v);
/* A visit must have occurred, with each start paired with end. */ /* 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); assert(opaque == qov->result);
qobject_incref(qov->root); qobject_incref(qov->root);
@ -217,10 +215,11 @@ static void qmp_output_complete(Visitor *v, void *opaque)
static void qmp_output_free(Visitor *v) static void qmp_output_free(Visitor *v)
{ {
QmpOutputVisitor *qov = to_qov(v); QmpOutputVisitor *qov = to_qov(v);
QStackEntry *e, *tmp; QStackEntry *e;
QTAILQ_FOREACH_SAFE(e, &qov->stack, node, tmp) { while (!QSLIST_EMPTY(&qov->stack)) {
QTAILQ_REMOVE(&qov->stack, e, node); e = QSLIST_FIRST(&qov->stack);
QSLIST_REMOVE_HEAD(&qov->stack, node);
g_free(e); g_free(e);
} }
@ -250,7 +249,6 @@ Visitor *qmp_output_visitor_new(QObject **result)
v->visitor.complete = qmp_output_complete; v->visitor.complete = qmp_output_complete;
v->visitor.free = qmp_output_free; v->visitor.free = qmp_output_free;
QTAILQ_INIT(&v->stack);
*result = NULL; *result = NULL;
v->result = result; v->result = result;

View File

@ -16,20 +16,23 @@
import re import re
def gen_command_decl(name, arg_type, ret_type): def gen_command_decl(name, arg_type, boxed, ret_type):
return mcgen(''' return mcgen('''
%(c_type)s qmp_%(c_name)s(%(params)s); %(c_type)s qmp_%(c_name)s(%(params)s);
''', ''',
c_type=(ret_type and ret_type.c_type()) or 'void', c_type=(ret_type and ret_type.c_type()) or 'void',
c_name=c_name(name), 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 = '' ret = ''
argstr = '' 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 assert not arg_type.variants
for memb in arg_type.members: for memb in arg_type.members:
if memb.optional: if memb.optional:
@ -46,8 +49,10 @@ def gen_call(name, arg_type, ret_type):
''', ''',
c_name=c_name(name), args=argstr, lhs=lhs) c_name=c_name(name), args=argstr, lhs=lhs)
if ret_type: if ret_type:
ret += gen_err_check()
ret += mcgen(''' ret += mcgen('''
if (err) {
goto out;
}
qmp_marshal_output_%(c_name)s(retval, ret, &err); qmp_marshal_output_%(c_name)s(retval, ret, &err);
''', ''',
@ -92,7 +97,7 @@ def gen_marshal_decl(name):
proto=gen_marshal_proto(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(''' ret = mcgen('''
%(proto)s %(proto)s
@ -107,7 +112,7 @@ def gen_marshal(name, arg_type, ret_type):
''', ''',
c_type=ret_type.c_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(''' ret += mcgen('''
Visitor *v; Visitor *v;
%(c_name)s arg = {0}; %(c_name)s arg = {0};
@ -134,10 +139,10 @@ def gen_marshal(name, arg_type, ret_type):
(void)args; (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 # '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(''' ret += mcgen('''
out: out:
@ -145,7 +150,7 @@ def gen_marshal(name, arg_type, ret_type):
ret += mcgen(''' ret += mcgen('''
error_propagate(errp, err); error_propagate(errp, err);
''') ''')
if arg_type and arg_type.members: if arg_type and not arg_type.is_empty():
ret += mcgen(''' ret += mcgen('''
visit_free(v); visit_free(v);
v = qapi_dealloc_visitor_new(); v = qapi_dealloc_visitor_new();
@ -210,16 +215,16 @@ def visit_end(self):
self._visited_ret_types = None self._visited_ret_types = None
def visit_command(self, name, info, arg_type, ret_type, def visit_command(self, name, info, arg_type, ret_type,
gen, success_response): gen, success_response, boxed):
if not gen: if not gen:
return 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: if ret_type and ret_type not in self._visited_ret_types:
self._visited_ret_types.add(ret_type) self._visited_ret_types.add(ret_type)
self.defn += gen_marshal_output(ret_type) self.defn += gen_marshal_output(ret_type)
if middle_mode: if middle_mode:
self.decl += gen_marshal_decl(name) 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: if not middle_mode:
self._regy += gen_register_command(name, success_response) self._regy += gen_register_command(name, success_response)

View File

@ -14,18 +14,18 @@
from qapi import * 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)' % { return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
'c_name': c_name(name.lower()), '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(''' return mcgen('''
%(proto)s; %(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() # 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 = &param;
''',
c_name=typ.c_name())
return ret 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 # FIXME: Our declaration of local variables (and of 'errp' in the
# parameter list) can collide with exploded members of the event's # parameter list) can collide with exploded members of the event's
# data type passed in as parameters. If this collision ever hits in # 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; Error *err = NULL;
QMPEventFuncEmit emit; 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(''' ret += mcgen('''
QObject *obj; QObject *obj;
Visitor *v; Visitor *v;
''') ''')
if not boxed:
ret += gen_param_var(arg_type) ret += gen_param_var(arg_type)
else:
assert not boxed
ret += mcgen(''' ret += mcgen('''
@ -88,9 +96,17 @@ def gen_event_send(name, arg_type):
''', ''',
name=name) name=name)
if arg_type and arg_type.members: if arg_type and not arg_type.is_empty():
ret += mcgen(''' ret += mcgen('''
v = qmp_output_visitor_new(&obj); 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); visit_start_struct(v, "%(name)s", NULL, 0, &err);
if (err) { if (err) {
@ -101,14 +117,16 @@ def gen_event_send(name, arg_type):
visit_check_struct(v, &err); visit_check_struct(v, &err);
} }
visit_end_struct(v, NULL); visit_end_struct(v, NULL);
''',
name=name, c_name=arg_type.c_name())
ret += mcgen('''
if (err) { if (err) {
goto out; goto out;
} }
visit_complete(v, &obj); visit_complete(v, &obj);
qdict_put_obj(qmp, "data", obj); qdict_put_obj(qmp, "data", obj);
''', ''')
name=name, c_name=arg_type.c_name())
ret += mcgen(''' ret += mcgen('''
emit(%(c_enum)s, qmp, &err); 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)) 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(''' ret += mcgen('''
out: out:
visit_free(v); visit_free(v);
@ -145,9 +163,9 @@ def visit_end(self):
self.defn += gen_enum_lookup(event_enum_name, self._event_names) self.defn += gen_enum_lookup(event_enum_name, self._event_names)
self._event_names = None self._event_names = None
def visit_event(self, name, info, arg_type): def visit_event(self, name, info, arg_type, boxed):
self.decl += gen_event_send_decl(name, arg_type) self.decl += gen_event_send_decl(name, arg_type, boxed)
self.defn += gen_event_send(name, arg_type) self.defn += gen_event_send(name, arg_type, boxed)
self._event_names.append(name) self._event_names.append(name)

View File

@ -154,14 +154,14 @@ def visit_alternate_type(self, name, info, variants):
for m in variants.variants]}) for m in variants.variants]})
def visit_command(self, name, info, arg_type, ret_type, 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 arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type
self._gen_json(name, 'command', self._gen_json(name, 'command',
{'arg-type': self._use_type(arg_type), {'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_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 arg_type = arg_type or self._schema.the_empty_object_type
self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)}) self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})

View File

@ -91,7 +91,7 @@ def gen_object(name, base, members, variants):
# potential issues with attempting to malloc space for zero-length # potential issues with attempting to malloc space for zero-length
# structs in C, and also incompatibility with C++ (where an empty # structs in C, and also incompatibility with C++ (where an empty
# struct is size 1). # 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(''' ret += mcgen('''
char qapi_dummy_for_empty_struct; char qapi_dummy_for_empty_struct;
''') ''')

View File

@ -47,9 +47,11 @@ def gen_visit_object_members(name, base, members, variants):
if base: if base:
ret += mcgen(''' ret += mcgen('''
visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err); visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err);
if (err) {
goto out;
}
''', ''',
c_type=base.c_name()) c_type=base.c_name())
ret += gen_err_check()
for memb in members: for memb in members:
if memb.optional: if memb.optional:
@ -60,10 +62,12 @@ def gen_visit_object_members(name, base, members, variants):
push_indent() push_indent()
ret += mcgen(''' ret += mcgen('''
visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, &err); 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_type=memb.type.c_name(), name=memb.name,
c_name=c_name(memb.name)) c_name=c_name(memb.name))
ret += gen_err_check()
if memb.optional: if memb.optional:
pop_indent() pop_indent()
ret += mcgen(''' ret += mcgen('''

View File

@ -522,10 +522,14 @@ def check_type(expr_info, source, value, allow_array=False,
def check_command(expr, expr_info): def check_command(expr, expr_info):
name = expr['command'] 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, check_type(expr_info, "'data' for command '%s'" % name,
expr.get('data'), allow_dict=True, allow_optional=True, expr.get('data'), allow_dict=not boxed, allow_optional=True,
allow_metas=['struct']) allow_metas=args_meta)
returns_meta = ['union', 'struct'] returns_meta = ['union', 'struct']
if name in returns_whitelist: if name in returns_whitelist:
returns_meta += ['built-in', 'alternate', 'enum'] returns_meta += ['built-in', 'alternate', 'enum']
@ -537,11 +541,15 @@ def check_command(expr, expr_info):
def check_event(expr, expr_info): def check_event(expr, expr_info):
global events global events
name = expr['event'] name = expr['event']
boxed = expr.get('boxed', False)
meta = ['struct']
if boxed:
meta += ['union', 'alternate']
events.append(name) events.append(name)
check_type(expr_info, "'data' for event '%s'" % name, check_type(expr_info, "'data' for event '%s'" % name,
expr.get('data'), allow_dict=True, allow_optional=True, expr.get('data'), allow_dict=not boxed, allow_optional=True,
allow_metas=['struct']) allow_metas=meta)
def check_union(expr, expr_info): def check_union(expr, expr_info):
@ -612,6 +620,14 @@ def check_union(expr, expr_info):
"enum '%s'" % "enum '%s'" %
(key, enum_define["enum_name"])) (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): def check_alternate(expr, expr_info):
name = expr['alternate'] name = expr['alternate']
@ -686,6 +702,10 @@ def check_keys(expr_elem, meta, required, optional=[]):
raise QAPIExprError(info, raise QAPIExprError(info,
"'%s' of %s '%s' should only use false value" "'%s' of %s '%s' should only use false value"
% (key, meta, name)) % (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: for key in required:
if key not in expr: if key not in expr:
raise QAPIExprError(info, raise QAPIExprError(info,
@ -717,10 +737,10 @@ def check_exprs(exprs):
add_struct(expr, info) add_struct(expr, info)
elif 'command' in expr: elif 'command' in expr:
check_keys(expr_elem, 'command', [], check_keys(expr_elem, 'command', [],
['data', 'returns', 'gen', 'success-response']) ['data', 'returns', 'gen', 'success-response', 'boxed'])
add_name(expr['command'], info, 'command') add_name(expr['command'], info, 'command')
elif 'event' in expr: elif 'event' in expr:
check_keys(expr_elem, 'event', [], ['data']) check_keys(expr_elem, 'event', [], ['data', 'boxed'])
add_name(expr['event'], info, 'event') add_name(expr['event'], info, 'event')
else: else:
raise QAPIExprError(expr_elem['info'], raise QAPIExprError(expr_elem['info'],
@ -818,10 +838,10 @@ def visit_alternate_type(self, name, info, variants):
pass pass
def visit_command(self, name, info, arg_type, ret_type, def visit_command(self, name, info, arg_type, ret_type,
gen, success_response): gen, success_response, boxed):
pass pass
def visit_event(self, name, info, arg_type): def visit_event(self, name, info, arg_type, boxed):
pass pass
@ -991,7 +1011,12 @@ def is_implicit(self):
# _def_predefineds() # _def_predefineds()
return self.name.startswith('q_') 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): def c_name(self):
assert self.name != 'q_empty'
return QAPISchemaType.c_name(self) return QAPISchemaType.c_name(self)
def c_type(self): def c_type(self):
@ -1084,7 +1109,7 @@ def __init__(self, tag_name, tag_member, variants):
assert len(variants) > 0 assert len(variants) > 0
for v in variants: for v in variants:
assert isinstance(v, QAPISchemaObjectTypeVariant) assert isinstance(v, QAPISchemaObjectTypeVariant)
self.tag_name = tag_name self._tag_name = tag_name
self.tag_member = tag_member self.tag_member = tag_member
self.variants = variants self.variants = variants
@ -1094,8 +1119,8 @@ def set_owner(self, name):
def check(self, schema, seen): def check(self, schema, seen):
if not self.tag_member: # flat union if not self.tag_member: # flat union
self.tag_member = seen[c_name(self.tag_name)] self.tag_member = seen[c_name(self._tag_name)]
assert self.tag_name == self.tag_member.name assert self._tag_name == self.tag_member.name
assert isinstance(self.tag_member.type, QAPISchemaEnumType) assert isinstance(self.tag_member.type, QAPISchemaEnumType)
for v in self.variants: for v in self.variants:
v.check(schema) v.check(schema)
@ -1125,7 +1150,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
def __init__(self, name, info, variants): def __init__(self, name, info, variants):
QAPISchemaType.__init__(self, name, info) QAPISchemaType.__init__(self, name, info)
assert isinstance(variants, QAPISchemaObjectTypeVariants) assert isinstance(variants, QAPISchemaObjectTypeVariants)
assert not variants.tag_name assert variants.tag_member
variants.set_owner(name) variants.set_owner(name)
variants.tag_member.set_owner(self.name) variants.tag_member.set_owner(self.name)
self.variants = variants self.variants = variants
@ -1150,9 +1175,13 @@ def json_type(self):
def visit(self, visitor): def visit(self, visitor):
visitor.visit_alternate_type(self.name, self.info, self.variants) visitor.visit_alternate_type(self.name, self.info, self.variants)
def is_empty(self):
return False
class QAPISchemaCommand(QAPISchemaEntity): 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) QAPISchemaEntity.__init__(self, name, info)
assert not arg_type or isinstance(arg_type, str) assert not arg_type or isinstance(arg_type, str)
assert not ret_type or isinstance(ret_type, str) assert not ret_type or isinstance(ret_type, str)
@ -1162,12 +1191,24 @@ def __init__(self, name, info, arg_type, ret_type, gen, success_response):
self.ret_type = None self.ret_type = None
self.gen = gen self.gen = gen
self.success_response = success_response self.success_response = success_response
self.boxed = boxed
def check(self, schema): def check(self, schema):
if self._arg_type_name: if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name) self.arg_type = schema.lookup_type(self._arg_type_name)
assert isinstance(self.arg_type, QAPISchemaObjectType) assert (isinstance(self.arg_type, QAPISchemaObjectType) or
assert not self.arg_type.variants # not implemented 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: if self._ret_type_name:
self.ret_type = schema.lookup_type(self._ret_type_name) self.ret_type = schema.lookup_type(self._ret_type_name)
assert isinstance(self.ret_type, QAPISchemaType) assert isinstance(self.ret_type, QAPISchemaType)
@ -1175,24 +1216,36 @@ def check(self, schema):
def visit(self, visitor): def visit(self, visitor):
visitor.visit_command(self.name, self.info, visitor.visit_command(self.name, self.info,
self.arg_type, self.ret_type, self.arg_type, self.ret_type,
self.gen, self.success_response) self.gen, self.success_response, self.boxed)
class QAPISchemaEvent(QAPISchemaEntity): class QAPISchemaEvent(QAPISchemaEntity):
def __init__(self, name, info, arg_type): def __init__(self, name, info, arg_type, boxed):
QAPISchemaEntity.__init__(self, name, info) QAPISchemaEntity.__init__(self, name, info)
assert not arg_type or isinstance(arg_type, str) assert not arg_type or isinstance(arg_type, str)
self._arg_type_name = arg_type self._arg_type_name = arg_type
self.arg_type = None self.arg_type = None
self.boxed = boxed
def check(self, schema): def check(self, schema):
if self._arg_type_name: if self._arg_type_name:
self.arg_type = schema.lookup_type(self._arg_type_name) self.arg_type = schema.lookup_type(self._arg_type_name)
assert isinstance(self.arg_type, QAPISchemaObjectType) assert (isinstance(self.arg_type, QAPISchemaObjectType) or
assert not self.arg_type.variants # not implemented 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): 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): class QAPISchema(object):
@ -1368,6 +1421,7 @@ def _def_command(self, expr, info):
rets = expr.get('returns') rets = expr.get('returns')
gen = expr.get('gen', True) gen = expr.get('gen', True)
success_response = expr.get('success-response', True) success_response = expr.get('success-response', True)
boxed = expr.get('boxed', False)
if isinstance(data, OrderedDict): if isinstance(data, OrderedDict):
data = self._make_implicit_object_type( data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info)) name, info, 'arg', self._make_members(data, info))
@ -1375,15 +1429,16 @@ def _def_command(self, expr, info):
assert len(rets) == 1 assert len(rets) == 1
rets = self._make_array_type(rets[0], info) rets = self._make_array_type(rets[0], info)
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen, self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
success_response)) success_response, boxed))
def _def_event(self, expr, info): def _def_event(self, expr, info):
name = expr['event'] name = expr['event']
data = expr.get('data') data = expr.get('data')
boxed = expr.get('boxed', False)
if isinstance(data, OrderedDict): if isinstance(data, OrderedDict):
data = self._make_implicit_object_type( data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info)) 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): def _def_exprs(self):
for expr_elem in self.exprs: for expr_elem in self.exprs:
@ -1626,31 +1681,29 @@ def gen_enum(name, values, prefix=None):
return ret return ret
def gen_params(arg_type, extra): def gen_params(arg_type, boxed, extra):
if not arg_type: if not arg_type:
assert not boxed
return extra return extra
assert not arg_type.variants
ret = '' ret = ''
sep = '' sep = ''
if boxed:
ret += '%s arg' % arg_type.c_param_type()
sep = ', '
else:
assert not arg_type.variants
for memb in arg_type.members: for memb in arg_type.members:
ret += sep ret += sep
sep = ', ' sep = ', '
if memb.optional: if memb.optional:
ret += 'bool has_%s, ' % c_name(memb.name) ret += 'bool has_%s, ' % c_name(memb.name)
ret += '%s %s' % (memb.type.c_param_type(), c_name(memb.name)) ret += '%s %s' % (memb.type.c_param_type(),
c_name(memb.name))
if extra: if extra:
ret += sep + extra ret += sep + extra
return ret return ret
def gen_err_check():
return mcgen('''
if (err) {
goto out;
}
''')
# #
# Common command line parsing # Common command line parsing
# #

View File

@ -284,6 +284,10 @@ qapi-schema += args-alternate.json
qapi-schema += args-any.json qapi-schema += args-any.json
qapi-schema += args-array-empty.json qapi-schema += args-array-empty.json
qapi-schema += args-array-unknown.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-int.json
qapi-schema += args-invalid.json qapi-schema += args-invalid.json
qapi-schema += args-member-array-bad.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-outside-string.json
qapi-schema += escape-too-big.json qapi-schema += escape-too-big.json
qapi-schema += escape-too-short.json qapi-schema += escape-too-short.json
qapi-schema += event-boxed-empty.json
qapi-schema += event-case.json qapi-schema += event-case.json
qapi-schema += event-nest-struct.json qapi-schema += event-nest-struct.json
qapi-schema += flat-union-array-branch.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-base-union.json
qapi-schema += flat-union-clash-member.json qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json qapi-schema += flat-union-empty.json
qapi-schema += flat-union-incomplete-branch.json
qapi-schema += flat-union-inline.json qapi-schema += flat-union-inline.json
qapi-schema += flat-union-int-branch.json qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json qapi-schema += flat-union-invalid-branch-key.json

View File

@ -0,0 +1 @@
tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
# 'boxed' should only appear with value true
{ 'command': 'foo', 'boxed': false }

View File

View File

@ -0,0 +1 @@
tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
# 'boxed' can only be used with named types
{ 'command': 'foo', 'boxed': true, 'data': { 'string': 'str' } }

View File

View File

@ -0,0 +1 @@
tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,3 @@
# 'boxed' requires a non-empty type
{ 'struct': 'Empty', 'data': {} }
{ 'command': 'foo', 'boxed': true, 'data': 'Empty' }

View File

View File

@ -0,0 +1 @@
tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str'

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
# 'boxed' requires a complex (not built-in) type
{ 'command': 'foo', 'boxed': true, 'data': 'str' }

View File

View 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'

View File

@ -1,4 +1,3 @@
# we do not allow union arguments # use of union arguments requires 'boxed':true
# TODO should we support this?
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } } { 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
{ 'command': 'oops', 'data': 'Uni' } { 'command': 'oops', 'data': 'Uni' }

View File

@ -0,0 +1 @@
tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data'

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
# 'boxed' requires a non-empty type
{ 'event': 'FOO', 'boxed': true }

View File

View File

@ -1,4 +1,5 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool'] enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE prefix QTYPE
event oops None event oops None
boxed=False
object q_empty object q_empty

View File

@ -0,0 +1 @@
tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch

View File

@ -0,0 +1 @@
1

View 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' } }

View File

@ -1,7 +1,7 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool'] enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE prefix QTYPE
command fooA q_obj_fooA-arg -> None command fooA q_obj_fooA-arg -> None
gen=True success_response=True gen=True success_response=True boxed=False
object q_empty object q_empty
object q_obj_fooA-arg object q_obj_fooA-arg
member bar1: str optional=False member bar1: str optional=False

View File

@ -1,7 +1,7 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool'] enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE prefix QTYPE
command eins None -> None command eins None -> None
gen=True success_response=True gen=True success_response=True boxed=False
object q_empty object q_empty
command zwei None -> None command zwei None -> None
gen=True success_response=True gen=True success_response=True boxed=False

View File

@ -127,6 +127,8 @@
{ 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' }, { 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' },
'returns': 'int' } 'returns': 'int' }
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' } { '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 # For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format: # corresponds to the option format:
@ -154,6 +156,8 @@
'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } } 'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
{ 'event': 'EVENT_D', { 'event': 'EVENT_D',
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } } '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 # test that we correctly compile downstream extensions, as well as munge
# ticklish names # ticklish names

View File

@ -1,25 +1,39 @@
alternate AltIntNum alternate AltIntNum
tag type
case i: int case i: int
case n: number case n: number
alternate AltNumInt alternate AltNumInt
tag type
case n: number case n: number
case i: int case i: int
alternate AltNumStr alternate AltNumStr
tag type
case n: number case n: number
case s: str case s: str
alternate AltStrBool alternate AltStrBool
tag type
case s: str case s: str
case b: bool case b: bool
alternate AltStrInt alternate AltStrInt
tag type
case s: str case s: str
case i: int case i: int
alternate AltStrNum alternate AltStrNum
tag type
case s: str case s: str
case n: number case n: number
event EVENT_A None event EVENT_A None
boxed=False
event EVENT_B None event EVENT_B None
boxed=False
event EVENT_C q_obj_EVENT_C-arg event EVENT_C q_obj_EVENT_C-arg
boxed=False
event EVENT_D q_obj_EVENT_D-arg 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 Empty1
object Empty2 object Empty2
base Empty1 base Empty1
@ -50,6 +64,7 @@ object UserDefA
member boolean: bool optional=False member boolean: bool optional=False
member a_b: int optional=True member a_b: int optional=True
alternate UserDefAlternate alternate UserDefAlternate
tag type
case udfu: UserDefFlatUnion case udfu: UserDefFlatUnion
case s: str case s: str
case i: int case i: int
@ -72,6 +87,7 @@ object UserDefFlatUnion2
case value2: UserDefB case value2: UserDefB
object UserDefNativeListUnion object UserDefNativeListUnion
member type: UserDefNativeListUnionKind optional=False member type: UserDefNativeListUnionKind optional=False
tag type
case integer: q_obj_intList-wrapper case integer: q_obj_intList-wrapper
case s8: q_obj_int8List-wrapper case s8: q_obj_int8List-wrapper
case s16: q_obj_int16List-wrapper case s16: q_obj_int16List-wrapper
@ -116,7 +132,9 @@ object UserDefZero
object WrapAlternate object WrapAlternate
member alt: UserDefAlternate optional=False member alt: UserDefAlternate optional=False
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
boxed=False
alternate __org.qemu_x-Alt alternate __org.qemu_x-Alt
tag type
case __org.qemu_x-branch: str case __org.qemu_x-branch: str
case b: __org.qemu_x-Base case b: __org.qemu_x-Base
object __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 member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union1 object __org.qemu_x-Union1
member type: __org.qemu_x-Union1Kind optional=False member type: __org.qemu_x-Union1Kind optional=False
tag type
case __org.qemu_x-branch: q_obj_str-wrapper case __org.qemu_x-branch: q_obj_str-wrapper
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch'] enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
object __org.qemu_x-Union2 object __org.qemu_x-Union2
@ -137,11 +156,15 @@ object __org.qemu_x-Union2
tag __org.qemu_x-member1 tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2 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 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 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 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_empty
object q_obj_EVENT_C-arg object q_obj_EVENT_C-arg
member a: int optional=True member a: int optional=True
@ -202,10 +225,10 @@ object q_obj_user_def_cmd2-arg
member ud1a: UserDefOne optional=False member ud1a: UserDefOne optional=False
member ud1b: UserDefOne optional=True member ud1b: UserDefOne optional=True
command user_def_cmd None -> None command user_def_cmd None -> None
gen=True success_response=True gen=True success_response=True boxed=False
command user_def_cmd0 Empty2 -> Empty2 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 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 command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
gen=True success_response=True gen=True success_response=True boxed=False

View File

@ -36,19 +36,20 @@ def visit_alternate_type(self, name, info, variants):
self._print_variants(variants) self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type, def visit_command(self, name, info, arg_type, ret_type,
gen, success_response): gen, success_response, boxed):
print 'command %s %s -> %s' % \ print 'command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name) (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 'event %s %s' % (name, arg_type and arg_type.name)
print ' boxed=%s' % boxed
@staticmethod @staticmethod
def _print_variants(variants): def _print_variants(variants):
if variants: if variants:
if variants.tag_name: print ' tag %s' % variants.tag_member.name
print ' tag %s' % variants.tag_name
for v in variants.variants: for v in variants.variants:
print ' case %s: %s' % (v.name, v.type.name) print ' case %s: %s' % (v.name, v.type.name)

View File

@ -59,6 +59,14 @@ QObject *qmp_guest_sync(QObject *arg, Error **errp)
return arg; 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_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
__org_qemu_x_StructList *b, __org_qemu_x_StructList *b,
__org_qemu_x_Union2 *c, __org_qemu_x_Union2 *c,