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

View File

@ -410,7 +410,7 @@ following example objects:
=== Commands ===
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
'*returns': TYPE-NAME,
'*returns': TYPE-NAME, '*boxed': true,
'*gen': false, '*success-response': false }
Commands are defined by using a dictionary containing several members,
@ -461,6 +461,20 @@ which would validate this Client JSON Protocol transaction:
=> { "execute": "my-second-command" }
<= { "return": [ { "value": "one" }, { } ] }
The generator emits a prototype for the user's function implementing
the command. Normally, 'data' is a dictionary for an anonymous type,
or names a struct type (possibly empty, but not a union), and its
members are passed as separate arguments to this function. If the
command definition includes a key 'boxed' with the boolean value true,
then 'data' is instead the name of any non-empty complex type
(struct, union, or alternate), and a pointer to that QAPI type is
passed as a single argument.
The generator also emits a marshalling function that extracts
arguments for the user's function out of an input QDict, calls the
user's function, and if it succeeded, builds an output QObject from
its return value.
In rare cases, QAPI cannot express a type-safe representation of a
corresponding Client JSON Protocol command. You then have to suppress
generation of a marshalling function by including a key 'gen' with
@ -484,7 +498,8 @@ use of this member.
=== Events ===
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT }
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
'*boxed': true }
Events are defined with the keyword 'event'. It is not allowed to
name an event 'MAX', since the generator also produces a C enumeration
@ -505,6 +520,14 @@ Resulting in this JSON object:
"data": { "b": "test string" },
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
The generator emits a function to send the event. Normally, 'data' is
a dictionary for an anonymous type, or names a struct type (possibly
empty, but not a union), and its members are passed as separate
arguments to this function. If the event definition includes a key
'boxed' with the boolean value true, then 'data' is instead the name of
any non-empty complex type (struct, union, or alternate), and a
pointer to that QAPI type is passed as a single argument.
== Client JSON Protocol introspection ==

70
hmp.c
View File

@ -1077,31 +1077,28 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_str(qdict, "device");
const char *filename = qdict_get_str(qdict, "target");
const char *format = qdict_get_try_str(qdict, "format");
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
bool full = qdict_get_try_bool(qdict, "full", false);
enum NewImageMode mode;
Error *err = NULL;
DriveMirror mirror = {
.device = (char *)qdict_get_str(qdict, "device"),
.target = (char *)filename,
.has_format = !!format,
.format = (char *)format,
.sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
.has_mode = true,
.mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
.unmap = true,
};
if (!filename) {
error_setg(&err, QERR_MISSING_PARAMETER, "target");
hmp_handle_error(mon, &err);
return;
}
if (reuse) {
mode = NEW_IMAGE_MODE_EXISTING;
} else {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
qmp_drive_mirror(false, NULL, device, filename, !!format, format,
false, NULL, false, NULL,
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
true, mode, false, 0, false, 0, false, 0,
false, 0, false, 0, false, true, &err);
qmp_drive_mirror(&mirror, &err);
hmp_handle_error(mon, &err);
}
@ -1439,42 +1436,17 @@ void hmp_change(Monitor *mon, const QDict *qdict)
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
BlockIOThrottle throttle = {
.device = (char *) qdict_get_str(qdict, "device"),
.bps = qdict_get_int(qdict, "bps"),
.bps_rd = qdict_get_int(qdict, "bps_rd"),
.bps_wr = qdict_get_int(qdict, "bps_wr"),
.iops = qdict_get_int(qdict, "iops"),
.iops_rd = qdict_get_int(qdict, "iops_rd"),
.iops_wr = qdict_get_int(qdict, "iops_wr"),
};
qmp_block_set_io_throttle(qdict_get_str(qdict, "device"),
qdict_get_int(qdict, "bps"),
qdict_get_int(qdict, "bps_rd"),
qdict_get_int(qdict, "bps_wr"),
qdict_get_int(qdict, "iops"),
qdict_get_int(qdict, "iops_rd"),
qdict_get_int(qdict, "iops_wr"),
false, /* no burst max via HMP */
0,
false,
0,
false,
0,
false,
0,
false,
0,
false,
0,
false, /* no burst length via HMP */
0,
false,
0,
false,
0,
false,
0,
false,
0,
false,
0,
false, /* No default I/O size */
0,
false,
NULL, &err);
qmp_block_set_io_throttle(&throttle, &err);
hmp_handle_error(mon, &err);
}

View File

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

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,
NET_CLIENT_OPTIONS_KIND_NIC,
NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM);
if (queues == 0) {
err = -ENOENT;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -88,10 +88,10 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net)
const int *feature_bits = 0;
switch (net->nc->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP:
case NET_CLIENT_DRIVER_TAP:
feature_bits = kernel_feature_bits;
break;
case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
case NET_CLIENT_DRIVER_VHOST_USER:
feature_bits = user_feature_bits;
break;
default:
@ -128,7 +128,7 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net)
static int vhost_net_get_fd(NetClientState *backend)
{
switch (backend->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP:
case NET_CLIENT_DRIVER_TAP:
return tap_get_fd(backend);
default:
fprintf(stderr, "vhost-net requires tap backend\n");
@ -191,7 +191,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
}
/* Set sane init value. Override when guest acks. */
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
features = vhost_user_get_acked_features(net->nc);
if (~net->dev.features & features) {
fprintf(stderr, "vhost lacks feature mask %" PRIu64
@ -238,7 +238,7 @@ static int vhost_net_start_one(struct vhost_net *net,
net->nc->info->poll(net->nc, false);
}
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
file.fd = net->backend;
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
@ -253,7 +253,7 @@ static int vhost_net_start_one(struct vhost_net *net,
return 0;
fail:
file.fd = -1;
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
while (file.index-- > 0) {
const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
@ -275,7 +275,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
{
struct vhost_vring_file file = { .fd = -1 };
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
@ -312,7 +312,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
* because vhost user doesn't interrupt masking/unmasking
* properly.
*/
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
dev->use_guest_notifier_mask = false;
}
}
@ -413,10 +413,10 @@ VHostNetState *get_vhost_net(NetClientState *nc)
}
switch (nc->info->type) {
case NET_CLIENT_OPTIONS_KIND_TAP:
case NET_CLIENT_DRIVER_TAP:
vhost_net = tap_get_vhost_net(nc);
break;
case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
case NET_CLIENT_DRIVER_VHOST_USER:
vhost_net = vhost_user_get_vhost_net(nc);
break;
default:

View File

@ -468,11 +468,11 @@ static int peer_attach(VirtIONet *n, int index)
return 0;
}
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
vhost_set_vring_enable(nc->peer, 1);
}
if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
return 0;
}
@ -487,11 +487,11 @@ static int peer_detach(VirtIONet *n, int index)
return 0;
}
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
vhost_set_vring_enable(nc->peer, 0);
}
if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
return 0;
}
@ -1680,7 +1680,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
}
static NetClientInfo net_virtio_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.can_receive = virtio_net_can_receive,
.receive = virtio_net_receive,

View File

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

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 = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.receive = net_rx_packet,
};

View File

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

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 = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.receive = eth_rx,
};

View File

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

View File

@ -1334,7 +1334,7 @@ static void usb_net_handle_destroy(USBDevice *dev)
}
static NetClientInfo net_usbnet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.receive = usbnet_receive,
.cleanup = usbnet_cleanup,
@ -1396,7 +1396,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
qemu_opt_set(opts, "type", "nic", &error_abort);
qemu_opt_set(opts, "model", "usb", &error_abort);
idx = net_client_init(opts, 0, &local_err);
idx = net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
return NULL;

View File

@ -66,7 +66,7 @@ typedef struct SocketReadState SocketReadState;
typedef void (SocketReadStateFinalize)(SocketReadState *rs);
typedef struct NetClientInfo {
NetClientOptionsKind type;
NetClientDriver type;
size_t size;
NetReceive *receive;
NetReceive *receive_raw;
@ -122,7 +122,7 @@ int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size);
char *qemu_mac_strdup_printf(const uint8_t *macaddr);
NetClientState *qemu_find_netdev(const char *id);
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
NetClientOptionsKind type, int max);
NetClientDriver type, int max);
NetClientState *qemu_new_net_client(NetClientInfo *info,
NetClientState *peer,
const char *model,
@ -203,7 +203,7 @@ extern const char *host_net_devices[];
extern const char *legacy_tftp_prefix;
extern const char *legacy_bootp_filename;
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp);
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp);
int net_client_parse(QemuOptsList *opts_list, const char *str);
int net_init_clients(void);
void net_check_clients(void);

View File

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

View File

@ -27,39 +27,39 @@
#include "net/net.h"
#include "qapi-types.h"
int net_init_dump(const NetClientOptions *opts, const char *name,
int net_init_dump(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#ifdef CONFIG_SLIRP
int net_init_slirp(const NetClientOptions *opts, const char *name,
int net_init_slirp(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#endif
int net_init_hubport(const NetClientOptions *opts, const char *name,
int net_init_hubport(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
int net_init_socket(const NetClientOptions *opts, const char *name,
int net_init_socket(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
int net_init_tap(const NetClientOptions *opts, const char *name,
int net_init_tap(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
int net_init_bridge(const NetClientOptions *opts, const char *name,
int net_init_bridge(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
int net_init_l2tpv3(const NetClientOptions *opts, const char *name,
int net_init_l2tpv3(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#ifdef CONFIG_VDE
int net_init_vde(const NetClientOptions *opts, const char *name,
int net_init_vde(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#endif
#ifdef CONFIG_NETMAP
int net_init_netmap(const NetClientOptions *opts, const char *name,
int net_init_netmap(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#endif
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
int net_init_vhost_user(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
#endif /* QEMU_NET_CLIENTS_H */

View File

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

View File

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

View File

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

View File

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

155
net/net.c
View File

@ -289,7 +289,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
NICState *nic;
int i, queues = MAX(1, conf->peers.queues);
assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
assert(info->type == NET_CLIENT_DRIVER_NIC);
assert(info->size >= sizeof(NICState));
nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
@ -360,13 +360,13 @@ void qemu_del_net_client(NetClientState *nc)
int queues, i;
NetFilterState *nf, *next;
assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
/* If the NetClientState belongs to a multiqueue backend, we will change all
* other NetClientStates also.
*/
queues = qemu_find_net_clients_except(nc->name, ncs,
NET_CLIENT_OPTIONS_KIND_NIC,
NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM);
assert(queues != 0);
@ -375,7 +375,7 @@ void qemu_del_net_client(NetClientState *nc)
}
/* If there is a peer NIC, delete and cleanup client, but do not free. */
if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
NICState *nic = qemu_get_nic(nc->peer);
if (nic->peer_deleted) {
return;
@ -431,7 +431,7 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
NetClientState *nc;
QTAILQ_FOREACH(nc, &net_clients, next) {
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
if (nc->queue_index == 0) {
func(qemu_get_nic(nc), opaque);
}
@ -603,7 +603,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
{
nc->receive_disabled = 0;
if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
if (net_hub_flush(nc->peer)) {
qemu_notify_event();
}
@ -777,7 +777,7 @@ NetClientState *qemu_find_netdev(const char *id)
NetClientState *nc;
QTAILQ_FOREACH(nc, &net_clients, next) {
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
if (nc->info->type == NET_CLIENT_DRIVER_NIC)
continue;
if (!strcmp(nc->name, id)) {
return nc;
@ -788,7 +788,7 @@ NetClientState *qemu_find_netdev(const char *id)
}
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
NetClientOptionsKind type, int max)
NetClientDriver type, int max)
{
NetClientState *nc;
int ret = 0;
@ -862,15 +862,15 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
return -1;
}
static int net_init_nic(const NetClientOptions *opts, const char *name,
static int net_init_nic(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp)
{
int idx;
NICInfo *nd;
const NetLegacyNicOptions *nic;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
nic = opts->u.nic.data;
assert(netdev->type == NET_CLIENT_DRIVER_NIC);
nic = &netdev->u.nic;
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
@ -930,70 +930,111 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
}
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND__MAX])(
const NetClientOptions *opts,
static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
const Netdev *netdev,
const char *name,
NetClientState *peer, Error **errp) = {
[NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic,
[NET_CLIENT_DRIVER_NIC] = net_init_nic,
#ifdef CONFIG_SLIRP
[NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp,
[NET_CLIENT_DRIVER_USER] = net_init_slirp,
#endif
[NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap,
[NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket,
[NET_CLIENT_DRIVER_TAP] = net_init_tap,
[NET_CLIENT_DRIVER_SOCKET] = net_init_socket,
#ifdef CONFIG_VDE
[NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde,
[NET_CLIENT_DRIVER_VDE] = net_init_vde,
#endif
#ifdef CONFIG_NETMAP
[NET_CLIENT_OPTIONS_KIND_NETMAP] = net_init_netmap,
[NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
#endif
[NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump,
[NET_CLIENT_DRIVER_DUMP] = net_init_dump,
#ifdef CONFIG_NET_BRIDGE
[NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge,
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
#endif
[NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport,
[NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
#ifdef CONFIG_VHOST_NET_USED
[NET_CLIENT_OPTIONS_KIND_VHOST_USER] = net_init_vhost_user,
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
#endif
#ifdef CONFIG_L2TPV3
[NET_CLIENT_OPTIONS_KIND_L2TPV3] = net_init_l2tpv3,
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
#endif
};
static int net_client_init1(const void *object, int is_netdev, Error **errp)
static int net_client_init1(const void *object, bool is_netdev, Error **errp)
{
const NetClientOptions *opts;
Netdev legacy = {0};
const Netdev *netdev;
const char *name;
NetClientState *peer = NULL;
if (is_netdev) {
const Netdev *netdev = object;
opts = netdev->opts;
netdev = object;
name = netdev->id;
if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP ||
opts->type == NET_CLIENT_OPTIONS_KIND_NIC ||
!net_client_init_fun[opts->type]) {
if (netdev->type == NET_CLIENT_DRIVER_DUMP ||
netdev->type == NET_CLIENT_DRIVER_NIC ||
!net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a netdev backend type");
return -1;
}
} else {
const NetLegacy *net = object;
opts = net->opts;
const NetLegacyOptions *opts = net->opts;
legacy.id = net->id;
netdev = &legacy;
/* missing optional values have been initialized to "all bits zero" */
name = net->has_id ? net->id : net->name;
if (opts->type == NET_CLIENT_OPTIONS_KIND_NONE) {
/* Map the old options to the new flat type */
switch (opts->type) {
case NET_LEGACY_OPTIONS_KIND_NONE:
return 0; /* nothing to do */
}
if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net type");
return -1;
case NET_LEGACY_OPTIONS_KIND_NIC:
legacy.type = NET_CLIENT_DRIVER_NIC;
legacy.u.nic = *opts->u.nic.data;
break;
case NET_LEGACY_OPTIONS_KIND_USER:
legacy.type = NET_CLIENT_DRIVER_USER;
legacy.u.user = *opts->u.user.data;
break;
case NET_LEGACY_OPTIONS_KIND_TAP:
legacy.type = NET_CLIENT_DRIVER_TAP;
legacy.u.tap = *opts->u.tap.data;
break;
case NET_LEGACY_OPTIONS_KIND_L2TPV3:
legacy.type = NET_CLIENT_DRIVER_L2TPV3;
legacy.u.l2tpv3 = *opts->u.l2tpv3.data;
break;
case NET_LEGACY_OPTIONS_KIND_SOCKET:
legacy.type = NET_CLIENT_DRIVER_SOCKET;
legacy.u.socket = *opts->u.socket.data;
break;
case NET_LEGACY_OPTIONS_KIND_VDE:
legacy.type = NET_CLIENT_DRIVER_VDE;
legacy.u.vde = *opts->u.vde.data;
break;
case NET_LEGACY_OPTIONS_KIND_DUMP:
legacy.type = NET_CLIENT_DRIVER_DUMP;
legacy.u.dump = *opts->u.dump.data;
break;
case NET_LEGACY_OPTIONS_KIND_BRIDGE:
legacy.type = NET_CLIENT_DRIVER_BRIDGE;
legacy.u.bridge = *opts->u.bridge.data;
break;
case NET_LEGACY_OPTIONS_KIND_NETMAP:
legacy.type = NET_CLIENT_DRIVER_NETMAP;
legacy.u.netmap = *opts->u.netmap.data;
break;
case NET_LEGACY_OPTIONS_KIND_VHOST_USER:
legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
legacy.u.vhost_user = *opts->u.vhost_user.data;
break;
default:
abort();
}
if (!net_client_init_fun[opts->type]) {
if (!net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net backend type (maybe it is not compiled "
"into this binary)");
@ -1001,17 +1042,17 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
}
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC ||
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
!opts->u.nic.data->has_netdev) {
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
}
}
if (net_client_init_fun[opts->type](opts, name, peer, errp) < 0) {
if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
/* FIXME drop when all init functions store an Error */
if (errp && !*errp) {
error_setg(errp, QERR_DEVICE_INIT_FAILED,
NetClientOptionsKind_lookup[opts->type]);
NetClientDriver_lookup[netdev->type]);
}
return -1;
}
@ -1019,7 +1060,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
}
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
{
void *object = NULL;
Error *err = NULL;
@ -1112,7 +1153,7 @@ void hmp_host_net_add(Monitor *mon, const QDict *qdict)
qemu_opt_set(opts, "type", device, &error_abort);
net_client_init(opts, 0, &local_err);
net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
monitor_printf(mon, "adding host network device %s failed\n", device);
@ -1131,7 +1172,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
device, vlan_id);
return;
}
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
error_report("invalid host network device '%s'", device);
return;
}
@ -1142,7 +1183,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
void netdev_add(QemuOpts *opts, Error **errp)
{
net_client_init(opts, 1, errp);
net_client_init(opts, true, errp);
}
void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp)
@ -1222,7 +1263,7 @@ void print_net_client(Monitor *mon, NetClientState *nc)
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
nc->queue_index,
NetClientOptionsKind_lookup[nc->info->type],
NetClientDriver_lookup[nc->info->type],
nc->info_str);
if (!QTAILQ_EMPTY(&nc->filters)) {
monitor_printf(mon, "filters:\n");
@ -1252,7 +1293,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
}
/* only query rx-filter information of NIC */
if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
if (has_name) {
error_setg(errp, "net client(%s) isn't a NIC", name);
return NULL;
@ -1298,7 +1339,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
void hmp_info_network(Monitor *mon, const QDict *qdict)
{
NetClientState *nc, *peer;
NetClientOptionsKind type;
NetClientDriver type;
net_hub_info(mon);
@ -1311,10 +1352,10 @@ void hmp_info_network(Monitor *mon, const QDict *qdict)
continue;
}
if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (!peer || type == NET_CLIENT_DRIVER_NIC) {
print_net_client(mon, nc);
} /* else it's a netdev connected to a NIC, printed with the NIC */
if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (peer && type == NET_CLIENT_DRIVER_NIC) {
monitor_printf(mon, " \\ ");
print_net_client(mon, peer);
}
@ -1328,7 +1369,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
int queues, i;
queues = qemu_find_net_clients_except(name, ncs,
NET_CLIENT_OPTIONS_KIND__MAX,
NET_CLIENT_DRIVER__MAX,
MAX_QUEUE_NUM);
if (queues == 0) {
@ -1355,7 +1396,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
* multiple clients that can still communicate with each other in
* disconnected mode. For now maintain this compatibility.
*/
if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
for (i = 0; i < queues; i++) {
ncs[i]->peer->link_down = !up;
}
@ -1396,7 +1437,7 @@ void net_cleanup(void)
*/
while (!QTAILQ_EMPTY(&net_clients)) {
nc = QTAILQ_FIRST(&net_clients);
if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
qemu_del_nic(qemu_get_nic(nc));
} else {
qemu_del_net_client(nc);
@ -1416,7 +1457,7 @@ void net_check_clients(void)
QTAILQ_FOREACH(nc, &net_clients, next) {
if (!nc->peer) {
fprintf(stderr, "Warning: %s %s has no peer\n",
nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
nc->info->type == NET_CLIENT_DRIVER_NIC ?
"nic" : "netdev", nc->name);
}
}
@ -1440,7 +1481,7 @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
{
Error *local_err = NULL;
net_client_init(opts, 0, &local_err);
net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
return -1;
@ -1454,7 +1495,7 @@ static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
Error *local_err = NULL;
int ret;
ret = net_client_init(opts, 1, &local_err);
ret = net_client_init(opts, true, &local_err);
if (local_err) {
error_report_err(local_err);
return -1;

View File

@ -400,7 +400,7 @@ static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
/* NetClientInfo methods */
static NetClientInfo net_netmap_info = {
.type = NET_CLIENT_OPTIONS_KIND_NETMAP,
.type = NET_CLIENT_DRIVER_NETMAP,
.size = sizeof(NetmapState),
.receive = netmap_receive,
.receive_iov = netmap_receive_iov,
@ -418,10 +418,10 @@ static NetClientInfo net_netmap_info = {
*
* ... -net netmap,ifname="..."
*/
int net_init_netmap(const NetClientOptions *opts,
int net_init_netmap(const Netdev *netdev,
const char *name, NetClientState *peer, Error **errp)
{
const NetdevNetmapOptions *netmap_opts = opts->u.netmap.data;
const NetdevNetmapOptions *netmap_opts = &netdev->u.netmap;
struct nm_desc *nmd;
NetClientState *nc;
Error *err = NULL;

View File

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

View File

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

View File

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

View File

@ -223,7 +223,7 @@ static bool tap_has_ufo(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->has_ufo;
}
@ -232,7 +232,7 @@ static bool tap_has_vnet_hdr(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return !!s->host_vnet_hdr_len;
}
@ -241,7 +241,7 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return !!tap_probe_vnet_hdr_len(s->fd, len);
}
@ -250,7 +250,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
len == sizeof(struct virtio_net_hdr));
@ -262,7 +262,7 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
s->using_vnet_hdr = using_vnet_hdr;
@ -336,14 +336,14 @@ static void tap_poll(NetClientState *nc, bool enable)
int tap_get_fd(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->fd;
}
/* fd support */
static NetClientInfo net_tap_info = {
.type = NET_CLIENT_OPTIONS_KIND_TAP,
.type = NET_CLIENT_DRIVER_TAP,
.size = sizeof(TAPState),
.receive = tap_receive,
.receive_raw = tap_receive_raw,
@ -571,7 +571,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge,
}
}
int net_init_bridge(const NetClientOptions *opts, const char *name,
int net_init_bridge(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp)
{
const NetdevBridgeOptions *bridge;
@ -579,8 +579,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
TAPState *s;
int fd, vnet_hdr;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
bridge = opts->u.bridge.data;
assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
bridge = &netdev->u.bridge;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
@ -735,7 +735,7 @@ static int get_fds(char *str, char *fds[], int max)
return i;
}
int net_init_tap(const NetClientOptions *opts, const char *name,
int net_init_tap(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp)
{
const NetdevTapOptions *tap;
@ -747,8 +747,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
const char *vhostfdname;
char ifname[128];
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
tap = opts->u.tap.data;
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
tap = &netdev->u.tap;
queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
@ -921,7 +921,7 @@ free_fail:
VHostNetState *tap_get_vhost_net(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->vhost_net;
}

View File

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

View File

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

View File

@ -2809,16 +2809,32 @@
'*queues': 'int' } }
##
# @NetClientOptions
# @NetClientDriver
#
# A discriminated record of network device traits.
# Available netdev drivers.
#
# Since 2.7
##
{ 'enum': 'NetClientDriver',
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump',
'bridge', 'hubport', 'netmap', 'vhost-user' ] }
##
# @Netdev
#
# Captures the configuration of a network device.
#
# @id: identifier for monitor commands.
#
# @type: Specify the driver used for interpreting remaining arguments.
#
# Since 1.2
#
# 'l2tpv3' - since 2.1
#
##
{ 'union': 'NetClientOptions',
{ 'union': 'Netdev',
'base': { 'id': 'str', 'type': 'NetClientDriver' },
'discriminator': 'type',
'data': {
'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions',
@ -2853,23 +2869,28 @@
'*vlan': 'int32',
'*id': 'str',
'*name': 'str',
'opts': 'NetClientOptions' } }
'opts': 'NetLegacyOptions' } }
##
# @Netdev
# @NetLegacyOptions
#
# Captures the configuration of a network device.
#
# @id: identifier for monitor commands.
#
# @opts: device type specific properties
# Like Netdev, but for use only by the legacy command line options
#
# Since 1.2
##
{ 'struct': 'Netdev',
{ 'union': 'NetLegacyOptions',
'data': {
'id': 'str',
'opts': 'NetClientOptions' } }
'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions',
'user': 'NetdevUserOptions',
'tap': 'NetdevTapOptions',
'l2tpv3': 'NetdevL2TPv3Options',
'socket': 'NetdevSocketOptions',
'vde': 'NetdevVdeOptions',
'dump': 'NetdevDumpOptions',
'bridge': 'NetdevBridgeOptions',
'netmap': 'NetdevNetmapOptions',
'vhost-user': 'NetdevVhostUserOptions' } }
##
# @NetFilterDirection

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -154,14 +154,14 @@ const char %(c_name)s[] = %(c_string)s;
for m in variants.variants]})
def visit_command(self, name, info, arg_type, ret_type,
gen, success_response):
gen, success_response, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type
self._gen_json(name, 'command',
{'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_type)})
def visit_event(self, name, info, arg_type):
def visit_event(self, name, info, arg_type, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})

View File

@ -91,7 +91,7 @@ struct %(c_name)s {
# potential issues with attempting to malloc space for zero-length
# structs in C, and also incompatibility with C++ (where an empty
# struct is size 1).
if not (base and base.members) and not members and not variants:
if (not base or base.is_empty()) and not members and not variants:
ret += mcgen('''
char qapi_dummy_for_empty_struct;
''')

View File

@ -47,9 +47,11 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
if base:
ret += mcgen('''
visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err);
if (err) {
goto out;
}
''',
c_type=base.c_name())
ret += gen_err_check()
for memb in members:
if memb.optional:
@ -60,10 +62,12 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
push_indent()
ret += mcgen('''
visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, &err);
if (err) {
goto out;
}
''',
c_type=memb.type.c_name(), name=memb.name,
c_name=c_name(memb.name))
ret += gen_err_check()
if memb.optional:
pop_indent()
ret += mcgen('''

View File

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

View File

@ -284,6 +284,10 @@ qapi-schema += args-alternate.json
qapi-schema += args-any.json
qapi-schema += args-array-empty.json
qapi-schema += args-array-unknown.json
qapi-schema += args-bad-boxed.json
qapi-schema += args-boxed-anon.json
qapi-schema += args-boxed-empty.json
qapi-schema += args-boxed-string.json
qapi-schema += args-int.json
qapi-schema += args-invalid.json
qapi-schema += args-member-array-bad.json
@ -317,6 +321,7 @@ qapi-schema += enum-wrong-data.json
qapi-schema += escape-outside-string.json
qapi-schema += escape-too-big.json
qapi-schema += escape-too-short.json
qapi-schema += event-boxed-empty.json
qapi-schema += event-case.json
qapi-schema += event-nest-struct.json
qapi-schema += flat-union-array-branch.json
@ -326,6 +331,7 @@ qapi-schema += flat-union-base-any.json
qapi-schema += flat-union-base-union.json
qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json
qapi-schema += flat-union-incomplete-branch.json
qapi-schema += flat-union-inline.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json

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
# TODO should we support this?
# use of union arguments requires 'boxed':true
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
{ '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']
prefix QTYPE
event oops None
boxed=False
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']
prefix QTYPE
command fooA q_obj_fooA-arg -> None
gen=True success_response=True
gen=True success_response=True boxed=False
object q_empty
object q_obj_fooA-arg
member bar1: str optional=False

View File

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

View File

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

View File

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

View File

@ -36,19 +36,20 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
gen, success_response):
gen, success_response, boxed):
print 'command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name)
print ' gen=%s success_response=%s' % (gen, success_response)
print ' gen=%s success_response=%s boxed=%s' % \
(gen, success_response, boxed)
def visit_event(self, name, info, arg_type):
def visit_event(self, name, info, arg_type, boxed):
print 'event %s %s' % (name, arg_type and arg_type.name)
print ' boxed=%s' % boxed
@staticmethod
def _print_variants(variants):
if variants:
if variants.tag_name:
print ' tag %s' % variants.tag_name
print ' tag %s' % variants.tag_member.name
for v in variants.variants:
print ' case %s: %s' % (v.name, v.type.name)

View File

@ -59,6 +59,14 @@ QObject *qmp_guest_sync(QObject *arg, Error **errp)
return arg;
}
void qmp_boxed_struct(UserDefZero *arg, Error **errp)
{
}
void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
{
}
__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
__org_qemu_x_StructList *b,
__org_qemu_x_Union2 *c,