diff --git a/blockdev.c b/blockdev.c index 384ad3bba6..eafeba96d0 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2634,49 +2634,17 @@ fail: } /* throttling disk I/O limits */ -void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, - int64_t bps_wr, - int64_t iops, - int64_t iops_rd, - int64_t iops_wr, - bool has_bps_max, - int64_t bps_max, - bool has_bps_rd_max, - int64_t bps_rd_max, - bool has_bps_wr_max, - int64_t bps_wr_max, - bool has_iops_max, - int64_t iops_max, - bool has_iops_rd_max, - int64_t iops_rd_max, - bool has_iops_wr_max, - int64_t iops_wr_max, - bool has_bps_max_length, - int64_t bps_max_length, - bool has_bps_rd_max_length, - int64_t bps_rd_max_length, - bool has_bps_wr_max_length, - int64_t bps_wr_max_length, - bool has_iops_max_length, - int64_t iops_max_length, - bool has_iops_rd_max_length, - int64_t iops_rd_max_length, - bool has_iops_wr_max_length, - int64_t iops_wr_max_length, - bool has_iops_size, - int64_t iops_size, - bool has_group, - const char *group, Error **errp) +void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) { ThrottleConfig cfg; BlockDriverState *bs; BlockBackend *blk; AioContext *aio_context; - blk = blk_by_name(device); + blk = blk_by_name(arg->device); if (!blk) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", device); + "Device '%s' not found", arg->device); return; } @@ -2685,59 +2653,59 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, bs = blk_bs(blk); if (!bs) { - error_setg(errp, "Device '%s' has no medium", device); + error_setg(errp, "Device '%s' has no medium", arg->device); goto out; } throttle_config_init(&cfg); - cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps; - cfg.buckets[THROTTLE_BPS_READ].avg = bps_rd; - cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr; + cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps; + cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd; + cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr; - cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops; - cfg.buckets[THROTTLE_OPS_READ].avg = iops_rd; - cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr; + cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops; + cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd; + cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr; - if (has_bps_max) { - cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max; + if (arg->has_bps_max) { + cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max; } - if (has_bps_rd_max) { - cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max; + if (arg->has_bps_rd_max) { + cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max; } - if (has_bps_wr_max) { - cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max; + if (arg->has_bps_wr_max) { + cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max; } - if (has_iops_max) { - cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max; + if (arg->has_iops_max) { + cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max; } - if (has_iops_rd_max) { - cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max; + if (arg->has_iops_rd_max) { + cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max; } - if (has_iops_wr_max) { - cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max; + if (arg->has_iops_wr_max) { + cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max; } - if (has_bps_max_length) { - cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = bps_max_length; + if (arg->has_bps_max_length) { + cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length; } - if (has_bps_rd_max_length) { - cfg.buckets[THROTTLE_BPS_READ].burst_length = bps_rd_max_length; + if (arg->has_bps_rd_max_length) { + cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length; } - if (has_bps_wr_max_length) { - cfg.buckets[THROTTLE_BPS_WRITE].burst_length = bps_wr_max_length; + if (arg->has_bps_wr_max_length) { + cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length; } - if (has_iops_max_length) { - cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = iops_max_length; + if (arg->has_iops_max_length) { + cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length; } - if (has_iops_rd_max_length) { - cfg.buckets[THROTTLE_OPS_READ].burst_length = iops_rd_max_length; + if (arg->has_iops_rd_max_length) { + cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length; } - if (has_iops_wr_max_length) { - cfg.buckets[THROTTLE_OPS_WRITE].burst_length = iops_wr_max_length; + if (arg->has_iops_wr_max_length) { + cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length; } - if (has_iops_size) { - cfg.op_size = iops_size; + if (arg->has_iops_size) { + cfg.op_size = arg->iops_size; } if (!throttle_is_valid(&cfg, errp)) { @@ -2748,9 +2716,10 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, /* Enable I/O limits if they're not enabled yet, otherwise * just update the throttling group. */ if (!blk_get_public(blk)->throttle_state) { - blk_io_limits_enable(blk, has_group ? group : device); - } else if (has_group) { - blk_io_limits_update_group(blk, group); + blk_io_limits_enable(blk, + arg->has_group ? arg->group : arg->device); + } else if (arg->has_group) { + blk_io_limits_update_group(blk, arg->group); } /* Set the new throttling configuration */ blk_set_io_limits(blk, &cfg); @@ -3497,19 +3466,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, block_job_cb, bs, errp); } -void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, - const char *target, bool has_format, const char *format, - bool has_node_name, const char *node_name, - bool has_replaces, const char *replaces, - enum MirrorSyncMode sync, - bool has_mode, enum NewImageMode mode, - bool has_speed, int64_t speed, - bool has_granularity, uint32_t granularity, - bool has_buf_size, int64_t buf_size, - bool has_on_source_error, BlockdevOnError on_source_error, - bool has_on_target_error, BlockdevOnError on_target_error, - bool has_unmap, bool unmap, - Error **errp) +void qmp_drive_mirror(DriveMirror *arg, Error **errp) { BlockDriverState *bs; BlockBackend *blk; @@ -3520,11 +3477,12 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, QDict *options = NULL; int flags; int64_t size; + const char *format = arg->format; - blk = blk_by_name(device); + blk = blk_by_name(arg->device); if (!blk) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", device); + "Device '%s' not found", arg->device); return; } @@ -3532,24 +3490,25 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, aio_context_acquire(aio_context); if (!blk_is_available(blk)) { - error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); + error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, arg->device); goto out; } bs = blk_bs(blk); - if (!has_mode) { - mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + if (!arg->has_mode) { + arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; } - if (!has_format) { - format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name; + if (!arg->has_format) { + format = (arg->mode == NEW_IMAGE_MODE_EXISTING + ? NULL : bs->drv->format_name); } flags = bs->open_flags | BDRV_O_RDWR; source = backing_bs(bs); - if (!source && sync == MIRROR_SYNC_MODE_TOP) { - sync = MIRROR_SYNC_MODE_FULL; + if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) { + arg->sync = MIRROR_SYNC_MODE_FULL; } - if (sync == MIRROR_SYNC_MODE_NONE) { + if (arg->sync == MIRROR_SYNC_MODE_NONE) { source = bs; } @@ -3559,18 +3518,18 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, goto out; } - if (has_replaces) { + if (arg->has_replaces) { BlockDriverState *to_replace_bs; AioContext *replace_aio_context; int64_t replace_size; - if (!has_node_name) { + if (!arg->has_node_name) { error_setg(errp, "a node-name must be provided when replacing a" " named node of the graph"); goto out; } - to_replace_bs = check_to_replace_node(bs, replaces, &local_err); + to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err); if (!to_replace_bs) { error_propagate(errp, local_err); @@ -3589,26 +3548,26 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, } } - if (mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) { + if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) { backing_mode = MIRROR_SOURCE_BACKING_CHAIN; } else { backing_mode = MIRROR_OPEN_BACKING_CHAIN; } - if ((sync == MIRROR_SYNC_MODE_FULL || !source) - && mode != NEW_IMAGE_MODE_EXISTING) + if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source) + && arg->mode != NEW_IMAGE_MODE_EXISTING) { /* create new image w/o backing file */ assert(format); - bdrv_img_create(target, format, + bdrv_img_create(arg->target, format, NULL, NULL, NULL, size, flags, &local_err, false); } else { - switch (mode) { + switch (arg->mode) { case NEW_IMAGE_MODE_EXISTING: break; case NEW_IMAGE_MODE_ABSOLUTE_PATHS: /* create new image with backing file */ - bdrv_img_create(target, format, + bdrv_img_create(arg->target, format, source->filename, source->drv->format_name, NULL, size, flags, &local_err, false); @@ -3624,8 +3583,8 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, } options = qdict_new(); - if (has_node_name) { - qdict_put(options, "node-name", qstring_from_str(node_name)); + if (arg->has_node_name) { + qdict_put(options, "node-name", qstring_from_str(arg->node_name)); } if (format) { qdict_put(options, "driver", qstring_from_str(format)); @@ -3634,22 +3593,22 @@ void qmp_drive_mirror(bool has_job_id, const char *job_id, const char *device, /* Mirroring takes care of copy-on-write using the source's backing * file. */ - target_bs = bdrv_open(target, NULL, options, flags | BDRV_O_NO_BACKING, - errp); + target_bs = bdrv_open(arg->target, NULL, options, + flags | BDRV_O_NO_BACKING, errp); if (!target_bs) { goto out; } bdrv_set_aio_context(target_bs, aio_context); - blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, - has_replaces, replaces, sync, backing_mode, - has_speed, speed, - has_granularity, granularity, - has_buf_size, buf_size, - has_on_source_error, on_source_error, - has_on_target_error, on_target_error, - has_unmap, unmap, + blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, + arg->has_replaces, arg->replaces, arg->sync, + backing_mode, arg->has_speed, arg->speed, + arg->has_granularity, arg->granularity, + arg->has_buf_size, arg->buf_size, + arg->has_on_source_error, arg->on_source_error, + arg->has_on_target_error, arg->on_target_error, + arg->has_unmap, arg->unmap, &local_err); bdrv_unref(target_bs); error_propagate(errp, local_err); diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 48b0b31f2e..de298dcaec 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -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 == diff --git a/hmp.c b/hmp.c index 3ca79c3ea3..cc2056e9e2 100644 --- a/hmp.c +++ b/hmp.c @@ -1077,31 +1077,28 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict) void hmp_drive_mirror(Monitor *mon, const QDict *qdict) { - const char *device = qdict_get_str(qdict, "device"); const char *filename = qdict_get_str(qdict, "target"); const char *format = qdict_get_try_str(qdict, "format"); bool reuse = qdict_get_try_bool(qdict, "reuse", false); bool full = qdict_get_try_bool(qdict, "full", false); - enum NewImageMode mode; Error *err = NULL; + DriveMirror mirror = { + .device = (char *)qdict_get_str(qdict, "device"), + .target = (char *)filename, + .has_format = !!format, + .format = (char *)format, + .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + .has_mode = true, + .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS, + .unmap = true, + }; if (!filename) { error_setg(&err, QERR_MISSING_PARAMETER, "target"); hmp_handle_error(mon, &err); return; } - - if (reuse) { - mode = NEW_IMAGE_MODE_EXISTING; - } else { - mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; - } - - qmp_drive_mirror(false, NULL, device, filename, !!format, format, - false, NULL, false, NULL, - full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, - true, mode, false, 0, false, 0, false, 0, - false, 0, false, 0, false, true, &err); + qmp_drive_mirror(&mirror, &err); hmp_handle_error(mon, &err); } @@ -1439,42 +1436,17 @@ void hmp_change(Monitor *mon, const QDict *qdict) void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) { Error *err = NULL; + BlockIOThrottle throttle = { + .device = (char *) qdict_get_str(qdict, "device"), + .bps = qdict_get_int(qdict, "bps"), + .bps_rd = qdict_get_int(qdict, "bps_rd"), + .bps_wr = qdict_get_int(qdict, "bps_wr"), + .iops = qdict_get_int(qdict, "iops"), + .iops_rd = qdict_get_int(qdict, "iops_rd"), + .iops_wr = qdict_get_int(qdict, "iops_wr"), + }; - qmp_block_set_io_throttle(qdict_get_str(qdict, "device"), - qdict_get_int(qdict, "bps"), - qdict_get_int(qdict, "bps_rd"), - qdict_get_int(qdict, "bps_wr"), - qdict_get_int(qdict, "iops"), - qdict_get_int(qdict, "iops_rd"), - qdict_get_int(qdict, "iops_wr"), - false, /* no burst max via HMP */ - 0, - false, - 0, - false, - 0, - false, - 0, - false, - 0, - false, - 0, - false, /* no burst length via HMP */ - 0, - false, - 0, - false, - 0, - false, - 0, - false, - 0, - false, - 0, - false, /* No default I/O size */ - 0, - false, - NULL, &err); + qmp_block_set_io_throttle(&throttle, &err); hmp_handle_error(mon, &err); } diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 7a4cc07dd5..cc50ace13d 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -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, diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index ab1bc5e945..2ba2504ea0 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -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; diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index d57502300c..50e8361e52 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -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, diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 8a4be1e667..db1b301e7f 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -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, diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 0fa652c392..17f0338d1c 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -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, diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 06ca7b2638..93249497f4 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -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, diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index b4758bc441..d001c96668 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -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, diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index b10c419838..bab4dbfc98 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -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, }; diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 05495ec405..efaa49faae 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -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, diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 98250e0591..b5c777fbf6 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -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, diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index d91e029382..1c415ab3b1 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -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, diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index 205207356c..4615d873b1 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -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, diff --git a/hw/net/lance.c b/hw/net/lance.c index 6253d2103d..573d724bcf 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -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, diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index 7c0398ed99..0ee8ad9d66 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -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, }; diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c index 1e147c33c5..c3a12e1197 100644 --- a/hw/net/milkymist-minimac2.c +++ b/hw/net/milkymist-minimac2.c @@ -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, }; diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c index 5115adcaea..5a63df7ccb 100644 --- a/hw/net/mipsnet.c +++ b/hw/net/mipsnet.c @@ -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, }; diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 8fab7ae2ec..f3455339ee 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -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, }; diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index f0feaf96b0..798d681e25 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -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, }; diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 484d113eb6..268d6a7892 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -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, diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 595439a65b..0acf8a4879 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -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, diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c index 0149899c62..1305ac36cc 100644 --- a/hw/net/rocker/rocker_fp.c +++ b/hw/net/rocker/rocker_fp.c @@ -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, diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 07297cb78f..3345bc6b5e 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -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, diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index 21c1b8f54b..3b16dcf5a1 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -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, diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index 8b2eebd4e3..b273eda933 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -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, diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 6880894945..957730e023 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -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, }; diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 11fabc0b0a..f92d3f829e 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -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: diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 999989934e..56d85062ff 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -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, diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index e767fc64b8..bbf44adbcc 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -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, diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index 0b4ddae48c..6856b52999 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -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, }; diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 0c5f793bd2..46b1aa17fa 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -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, }; diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index de23ab5dcd..b6701844d3 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -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, }; diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index bc846e7096..54db2b83bd 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -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, diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 5c18198f55..c0f1193ba9 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -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; diff --git a/include/net/net.h b/include/net/net.h index a5c5095154..e8d9e9e4e9 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -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); diff --git a/monitor.c b/monitor.c index c1591f286d..5d68a5d6fc 100644 --- a/monitor.c +++ b/monitor.c @@ -3080,8 +3080,8 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str) } len = strlen(str); readline_set_completion_index(rs, len); - for (i = 0; NetClientOptionsKind_lookup[i]; i++) { - add_completion_option(rs, str, NetClientOptionsKind_lookup[i]); + for (i = 0; NetClientDriver_lookup[i]; i++) { + add_completion_option(rs, str, NetClientDriver_lookup[i]); } } @@ -3281,7 +3281,7 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str) NetClientState *ncs[MAX_QUEUE_NUM]; int count, i; count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NONE, + NET_CLIENT_DRIVER_NONE, MAX_QUEUE_NUM); for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { const char *name = ncs[i]->name; @@ -3306,7 +3306,7 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str) len = strlen(str); readline_set_completion_index(rs, len); - count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC, + count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { QemuOpts *opts; @@ -3435,7 +3435,7 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) readline_set_completion_index(rs, len); if (nb_args == 2) { count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NONE, + NET_CLIENT_DRIVER_NONE, MAX_QUEUE_NUM); for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { int id; @@ -3452,13 +3452,13 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) return; } else if (nb_args == 3) { count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NIC, + NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { int id; const char *name; - if (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT || + if (ncs[i]->info->type == NET_CLIENT_DRIVER_HUBPORT || net_hub_id_for_client(ncs[i], &id)) { continue; } diff --git a/net/clients.h b/net/clients.h index d47530e82f..5cae479730 100644 --- a/net/clients.h +++ b/net/clients.h @@ -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 */ diff --git a/net/dump.c b/net/dump.c index 41f7673efd..89a149b5dd 100644 --- a/net/dump.c +++ b/net/dump.c @@ -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); diff --git a/net/filter.c b/net/filter.c index 8ac79f3b7b..888fe6dd93 100644 --- a/net/filter.c +++ b/net/filter.c @@ -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", diff --git a/net/hub.c b/net/hub.c index 6d90c6ee67..32d8cf5cd4 100644 --- a/net/hub.c +++ b/net/hub.c @@ -131,7 +131,7 @@ static void net_hub_port_cleanup(NetClientState *nc) } static NetClientInfo net_hub_port_info = { - .type = NET_CLIENT_OPTIONS_KIND_HUBPORT, + .type = NET_CLIENT_DRIVER_HUBPORT, .size = sizeof(NetHubPort), .can_receive = net_hub_port_can_receive, .receive = net_hub_port_receive, @@ -266,10 +266,10 @@ int net_hub_id_for_client(NetClientState *nc, int *id) { NetHubPort *port; - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { + if (nc->info->type == NET_CLIENT_DRIVER_HUBPORT) { port = DO_UPCAST(NetHubPort, nc, nc); } else if (nc->peer != NULL && nc->peer->info->type == - NET_CLIENT_OPTIONS_KIND_HUBPORT) { + NET_CLIENT_DRIVER_HUBPORT) { port = DO_UPCAST(NetHubPort, nc, nc->peer); } else { return -ENOENT; @@ -281,14 +281,14 @@ int net_hub_id_for_client(NetClientState *nc, int *id) return 0; } -int net_init_hubport(const NetClientOptions *opts, const char *name, +int net_init_hubport(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { const NetdevHubPortOptions *hubport; - assert(opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT); + assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT); assert(!peer); - hubport = opts->u.hubport.data; + hubport = &netdev->u.hubport; net_hub_add_port(hubport->hubid, name); return 0; @@ -315,14 +315,14 @@ void net_hub_check_clients(void) } switch (peer->info->type) { - case NET_CLIENT_OPTIONS_KIND_NIC: + case NET_CLIENT_DRIVER_NIC: has_nic = 1; break; - case NET_CLIENT_OPTIONS_KIND_USER: - case NET_CLIENT_OPTIONS_KIND_TAP: - case NET_CLIENT_OPTIONS_KIND_SOCKET: - case NET_CLIENT_OPTIONS_KIND_VDE: - case NET_CLIENT_OPTIONS_KIND_VHOST_USER: + case NET_CLIENT_DRIVER_USER: + case NET_CLIENT_DRIVER_TAP: + case NET_CLIENT_DRIVER_SOCKET: + case NET_CLIENT_DRIVER_VDE: + case NET_CLIENT_DRIVER_VHOST_USER: has_host_dev = 1; break; default: diff --git a/net/l2tpv3.c b/net/l2tpv3.c index 5c668f7376..6745b78990 100644 --- a/net/l2tpv3.c +++ b/net/l2tpv3.c @@ -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; diff --git a/net/net.c b/net/net.c index 019aaad0fc..c124b11e4d 100644 --- a/net/net.c +++ b/net/net.c @@ -289,7 +289,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NICState *nic; int i, queues = MAX(1, conf->peers.queues); - assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); + assert(info->type == NET_CLIENT_DRIVER_NIC); assert(info->size >= sizeof(NICState)); nic = g_malloc0(info->size + sizeof(NetClientState) * queues); @@ -360,13 +360,13 @@ void qemu_del_net_client(NetClientState *nc) int queues, i; NetFilterState *nf, *next; - assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC); + assert(nc->info->type != NET_CLIENT_DRIVER_NIC); /* If the NetClientState belongs to a multiqueue backend, we will change all * other NetClientStates also. */ queues = qemu_find_net_clients_except(nc->name, ncs, - NET_CLIENT_OPTIONS_KIND_NIC, + NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); assert(queues != 0); @@ -375,7 +375,7 @@ void qemu_del_net_client(NetClientState *nc) } /* If there is a peer NIC, delete and cleanup client, but do not free. */ - if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { NICState *nic = qemu_get_nic(nc->peer); if (nic->peer_deleted) { return; @@ -431,7 +431,7 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) NetClientState *nc; QTAILQ_FOREACH(nc, &net_clients, next) { - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->info->type == NET_CLIENT_DRIVER_NIC) { if (nc->queue_index == 0) { func(qemu_get_nic(nc), opaque); } @@ -603,7 +603,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge) { nc->receive_disabled = 0; - if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) { if (net_hub_flush(nc->peer)) { qemu_notify_event(); } @@ -777,7 +777,7 @@ NetClientState *qemu_find_netdev(const char *id) NetClientState *nc; QTAILQ_FOREACH(nc, &net_clients, next) { - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) + if (nc->info->type == NET_CLIENT_DRIVER_NIC) continue; if (!strcmp(nc->name, id)) { return nc; @@ -788,7 +788,7 @@ NetClientState *qemu_find_netdev(const char *id) } int qemu_find_net_clients_except(const char *id, NetClientState **ncs, - NetClientOptionsKind type, int max) + NetClientDriver type, int max) { NetClientState *nc; int ret = 0; @@ -862,15 +862,15 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models, return -1; } -static int net_init_nic(const NetClientOptions *opts, const char *name, +static int net_init_nic(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { int idx; NICInfo *nd; const NetLegacyNicOptions *nic; - assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC); - nic = opts->u.nic.data; + assert(netdev->type == NET_CLIENT_DRIVER_NIC); + nic = &netdev->u.nic; idx = nic_get_free_idx(); if (idx == -1 || nb_nics >= MAX_NICS) { @@ -930,70 +930,111 @@ static int net_init_nic(const NetClientOptions *opts, const char *name, } -static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND__MAX])( - const NetClientOptions *opts, +static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( + const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) = { - [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, + [NET_CLIENT_DRIVER_NIC] = net_init_nic, #ifdef CONFIG_SLIRP - [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, + [NET_CLIENT_DRIVER_USER] = net_init_slirp, #endif - [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, - [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, + [NET_CLIENT_DRIVER_TAP] = net_init_tap, + [NET_CLIENT_DRIVER_SOCKET] = net_init_socket, #ifdef CONFIG_VDE - [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, + [NET_CLIENT_DRIVER_VDE] = net_init_vde, #endif #ifdef CONFIG_NETMAP - [NET_CLIENT_OPTIONS_KIND_NETMAP] = net_init_netmap, + [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap, #endif - [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, + [NET_CLIENT_DRIVER_DUMP] = net_init_dump, #ifdef CONFIG_NET_BRIDGE - [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, + [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge, #endif - [NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport, + [NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport, #ifdef CONFIG_VHOST_NET_USED - [NET_CLIENT_OPTIONS_KIND_VHOST_USER] = net_init_vhost_user, + [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user, #endif #ifdef CONFIG_L2TPV3 - [NET_CLIENT_OPTIONS_KIND_L2TPV3] = net_init_l2tpv3, + [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3, #endif }; -static int net_client_init1(const void *object, int is_netdev, Error **errp) +static int net_client_init1(const void *object, bool is_netdev, Error **errp) { - const NetClientOptions *opts; + Netdev legacy = {0}; + const Netdev *netdev; const char *name; NetClientState *peer = NULL; if (is_netdev) { - const Netdev *netdev = object; - opts = netdev->opts; + netdev = object; name = netdev->id; - if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP || - opts->type == NET_CLIENT_OPTIONS_KIND_NIC || - !net_client_init_fun[opts->type]) { + if (netdev->type == NET_CLIENT_DRIVER_DUMP || + netdev->type == NET_CLIENT_DRIVER_NIC || + !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a netdev backend type"); return -1; } } else { const NetLegacy *net = object; - opts = net->opts; + const NetLegacyOptions *opts = net->opts; + legacy.id = net->id; + netdev = &legacy; /* missing optional values have been initialized to "all bits zero" */ name = net->has_id ? net->id : net->name; - if (opts->type == NET_CLIENT_OPTIONS_KIND_NONE) { + /* Map the old options to the new flat type */ + switch (opts->type) { + case NET_LEGACY_OPTIONS_KIND_NONE: return 0; /* nothing to do */ - } - if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", - "a net type"); - return -1; + case NET_LEGACY_OPTIONS_KIND_NIC: + legacy.type = NET_CLIENT_DRIVER_NIC; + legacy.u.nic = *opts->u.nic.data; + break; + case NET_LEGACY_OPTIONS_KIND_USER: + legacy.type = NET_CLIENT_DRIVER_USER; + legacy.u.user = *opts->u.user.data; + break; + case NET_LEGACY_OPTIONS_KIND_TAP: + legacy.type = NET_CLIENT_DRIVER_TAP; + legacy.u.tap = *opts->u.tap.data; + break; + case NET_LEGACY_OPTIONS_KIND_L2TPV3: + legacy.type = NET_CLIENT_DRIVER_L2TPV3; + legacy.u.l2tpv3 = *opts->u.l2tpv3.data; + break; + case NET_LEGACY_OPTIONS_KIND_SOCKET: + legacy.type = NET_CLIENT_DRIVER_SOCKET; + legacy.u.socket = *opts->u.socket.data; + break; + case NET_LEGACY_OPTIONS_KIND_VDE: + legacy.type = NET_CLIENT_DRIVER_VDE; + legacy.u.vde = *opts->u.vde.data; + break; + case NET_LEGACY_OPTIONS_KIND_DUMP: + legacy.type = NET_CLIENT_DRIVER_DUMP; + legacy.u.dump = *opts->u.dump.data; + break; + case NET_LEGACY_OPTIONS_KIND_BRIDGE: + legacy.type = NET_CLIENT_DRIVER_BRIDGE; + legacy.u.bridge = *opts->u.bridge.data; + break; + case NET_LEGACY_OPTIONS_KIND_NETMAP: + legacy.type = NET_CLIENT_DRIVER_NETMAP; + legacy.u.netmap = *opts->u.netmap.data; + break; + case NET_LEGACY_OPTIONS_KIND_VHOST_USER: + legacy.type = NET_CLIENT_DRIVER_VHOST_USER; + legacy.u.vhost_user = *opts->u.vhost_user.data; + break; + default: + abort(); } - if (!net_client_init_fun[opts->type]) { + if (!net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a net backend type (maybe it is not compiled " "into this binary)"); @@ -1001,17 +1042,17 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) } /* Do not add to a vlan if it's a nic with a netdev= parameter. */ - if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC || + if (netdev->type != NET_CLIENT_DRIVER_NIC || !opts->u.nic.data->has_netdev) { peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL); } } - if (net_client_init_fun[opts->type](opts, name, peer, errp) < 0) { + if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) { /* FIXME drop when all init functions store an Error */ if (errp && !*errp) { error_setg(errp, QERR_DEVICE_INIT_FAILED, - NetClientOptionsKind_lookup[opts->type]); + NetClientDriver_lookup[netdev->type]); } return -1; } @@ -1019,7 +1060,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) } -int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) +int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { void *object = NULL; Error *err = NULL; @@ -1112,7 +1153,7 @@ void hmp_host_net_add(Monitor *mon, const QDict *qdict) qemu_opt_set(opts, "type", device, &error_abort); - net_client_init(opts, 0, &local_err); + net_client_init(opts, false, &local_err); if (local_err) { error_report_err(local_err); monitor_printf(mon, "adding host network device %s failed\n", device); @@ -1131,7 +1172,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict) device, vlan_id); return; } - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->info->type == NET_CLIENT_DRIVER_NIC) { error_report("invalid host network device '%s'", device); return; } @@ -1142,7 +1183,7 @@ void hmp_host_net_remove(Monitor *mon, const QDict *qdict) void netdev_add(QemuOpts *opts, Error **errp) { - net_client_init(opts, 1, errp); + net_client_init(opts, true, errp); } void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp) @@ -1222,7 +1263,7 @@ void print_net_client(Monitor *mon, NetClientState *nc) monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name, nc->queue_index, - NetClientOptionsKind_lookup[nc->info->type], + NetClientDriver_lookup[nc->info->type], nc->info_str); if (!QTAILQ_EMPTY(&nc->filters)) { monitor_printf(mon, "filters:\n"); @@ -1252,7 +1293,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name, } /* only query rx-filter information of NIC */ - if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->info->type != NET_CLIENT_DRIVER_NIC) { if (has_name) { error_setg(errp, "net client(%s) isn't a NIC", name); return NULL; @@ -1298,7 +1339,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name, void hmp_info_network(Monitor *mon, const QDict *qdict) { NetClientState *nc, *peer; - NetClientOptionsKind type; + NetClientDriver type; net_hub_info(mon); @@ -1311,10 +1352,10 @@ void hmp_info_network(Monitor *mon, const QDict *qdict) continue; } - if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (!peer || type == NET_CLIENT_DRIVER_NIC) { print_net_client(mon, nc); } /* else it's a netdev connected to a NIC, printed with the NIC */ - if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (peer && type == NET_CLIENT_DRIVER_NIC) { monitor_printf(mon, " \\ "); print_net_client(mon, peer); } @@ -1328,7 +1369,7 @@ void qmp_set_link(const char *name, bool up, Error **errp) int queues, i; queues = qemu_find_net_clients_except(name, ncs, - NET_CLIENT_OPTIONS_KIND__MAX, + NET_CLIENT_DRIVER__MAX, MAX_QUEUE_NUM); if (queues == 0) { @@ -1355,7 +1396,7 @@ void qmp_set_link(const char *name, bool up, Error **errp) * multiple clients that can still communicate with each other in * disconnected mode. For now maintain this compatibility. */ - if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { for (i = 0; i < queues; i++) { ncs[i]->peer->link_down = !up; } @@ -1396,7 +1437,7 @@ void net_cleanup(void) */ while (!QTAILQ_EMPTY(&net_clients)) { nc = QTAILQ_FIRST(&net_clients); - if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + if (nc->info->type == NET_CLIENT_DRIVER_NIC) { qemu_del_nic(qemu_get_nic(nc)); } else { qemu_del_net_client(nc); @@ -1416,7 +1457,7 @@ void net_check_clients(void) QTAILQ_FOREACH(nc, &net_clients, next) { if (!nc->peer) { fprintf(stderr, "Warning: %s %s has no peer\n", - nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? + nc->info->type == NET_CLIENT_DRIVER_NIC ? "nic" : "netdev", nc->name); } } @@ -1440,7 +1481,7 @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) { Error *local_err = NULL; - net_client_init(opts, 0, &local_err); + net_client_init(opts, false, &local_err); if (local_err) { error_report_err(local_err); return -1; @@ -1454,7 +1495,7 @@ static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) Error *local_err = NULL; int ret; - ret = net_client_init(opts, 1, &local_err); + ret = net_client_init(opts, true, &local_err); if (local_err) { error_report_err(local_err); return -1; diff --git a/net/netmap.c b/net/netmap.c index 64967b947e..2d11a8f4be 100644 --- a/net/netmap.c +++ b/net/netmap.c @@ -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; diff --git a/net/slirp.c b/net/slirp.c index 28207b6614..facc30ed18 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -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)) { diff --git a/net/socket.c b/net/socket.c index ae6f92101d..17e635de20 100644 --- a/net/socket.c +++ b/net/socket.c @@ -311,7 +311,7 @@ static void net_socket_cleanup(NetClientState *nc) } static NetClientInfo net_dgram_socket_info = { - .type = NET_CLIENT_OPTIONS_KIND_SOCKET, + .type = NET_CLIENT_DRIVER_SOCKET, .size = sizeof(NetSocketState), .receive = net_socket_receive_dgram, .cleanup = net_socket_cleanup, @@ -395,7 +395,7 @@ static void net_socket_connect(void *opaque) } static NetClientInfo net_socket_info = { - .type = NET_CLIENT_OPTIONS_KIND_SOCKET, + .type = NET_CLIENT_DRIVER_SOCKET, .size = sizeof(NetSocketState), .receive = net_socket_receive, .cleanup = net_socket_cleanup, @@ -663,15 +663,15 @@ static int net_socket_udp_init(NetClientState *peer, return 0; } -int net_init_socket(const NetClientOptions *opts, const char *name, +int net_init_socket(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { /* FIXME error_setg(errp, ...) on failure */ Error *err = NULL; const NetdevSocketOptions *sock; - assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET); - sock = opts->u.socket.data; + assert(netdev->type == NET_CLIENT_DRIVER_SOCKET); + sock = &netdev->u.socket; if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast + sock->has_udp != 1) { diff --git a/net/tap-win32.c b/net/tap-win32.c index f1e142ace6..662f9b63e1 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -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"); diff --git a/net/tap.c b/net/tap.c index 6a2cedcfb1..40a8c741fc 100644 --- a/net/tap.c +++ b/net/tap.c @@ -223,7 +223,7 @@ static bool tap_has_ufo(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); return s->has_ufo; } @@ -232,7 +232,7 @@ static bool tap_has_vnet_hdr(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); return !!s->host_vnet_hdr_len; } @@ -241,7 +241,7 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); return !!tap_probe_vnet_hdr_len(s->fd, len); } @@ -250,7 +250,7 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) || len == sizeof(struct virtio_net_hdr)); @@ -262,7 +262,7 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); assert(!!s->host_vnet_hdr_len == using_vnet_hdr); s->using_vnet_hdr = using_vnet_hdr; @@ -336,14 +336,14 @@ static void tap_poll(NetClientState *nc, bool enable) int tap_get_fd(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); return s->fd; } /* fd support */ static NetClientInfo net_tap_info = { - .type = NET_CLIENT_OPTIONS_KIND_TAP, + .type = NET_CLIENT_DRIVER_TAP, .size = sizeof(TAPState), .receive = tap_receive, .receive_raw = tap_receive_raw, @@ -571,7 +571,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge, } } -int net_init_bridge(const NetClientOptions *opts, const char *name, +int net_init_bridge(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { const NetdevBridgeOptions *bridge; @@ -579,8 +579,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name, TAPState *s; int fd, vnet_hdr; - assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE); - bridge = opts->u.bridge.data; + assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE); + bridge = &netdev->u.bridge; helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER; br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE; @@ -735,7 +735,7 @@ static int get_fds(char *str, char *fds[], int max) return i; } -int net_init_tap(const NetClientOptions *opts, const char *name, +int net_init_tap(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { const NetdevTapOptions *tap; @@ -747,8 +747,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name, const char *vhostfdname; char ifname[128]; - assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP); - tap = opts->u.tap.data; + assert(netdev->type == NET_CLIENT_DRIVER_TAP); + tap = &netdev->u.tap; queues = tap->has_queues ? tap->queues : 1; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; @@ -921,7 +921,7 @@ free_fail: VHostNetState *tap_get_vhost_net(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); + assert(nc->info->type == NET_CLIENT_DRIVER_TAP); return s->vhost_net; } diff --git a/net/vde.c b/net/vde.c index 9427eaa16f..e50e5d6394 100644 --- a/net/vde.c +++ b/net/vde.c @@ -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, diff --git a/net/vhost-user.c b/net/vhost-user.c index a88dfe0655..c4d63e05eb 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -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) { diff --git a/qapi-schema.json b/qapi-schema.json index d2d650673b..5658723b37 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -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 diff --git a/qapi/block-core.json b/qapi/block-core.json index 3444a9bc3e..f4f3ef970e 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -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', diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 21edb3928e..64dd392e6f 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -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); diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c index 0452056d42..9e3b67ce13 100644 --- a/qapi/qmp-output-visitor.c +++ b/qapi/qmp-output-visitor.c @@ -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; diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 34b6a3a07f..a06a2c4f9b 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -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) diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index 9c88627c9f..38d82111ad 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -14,18 +14,18 @@ from qapi import * -def gen_event_send_proto(name, arg_type): +def gen_event_send_proto(name, arg_type, boxed): return 'void qapi_event_send_%(c_name)s(%(param)s)' % { 'c_name': c_name(name.lower()), - 'param': gen_params(arg_type, 'Error **errp')} + 'param': gen_params(arg_type, boxed, 'Error **errp')} -def gen_event_send_decl(name, arg_type): +def gen_event_send_decl(name, arg_type, boxed): return mcgen(''' %(proto)s; ''', - proto=gen_event_send_proto(name, arg_type)) + proto=gen_event_send_proto(name, arg_type, boxed)) # Declare and initialize an object 'qapi' using parameters from gen_params() @@ -49,10 +49,15 @@ def gen_param_var(typ): }; ''') + if not typ.is_implicit(): + ret += mcgen(''' + %(c_name)s *arg = ¶m; +''', + c_name=typ.c_name()) return ret -def gen_event_send(name, arg_type): +def gen_event_send(name, arg_type, boxed): # FIXME: Our declaration of local variables (and of 'errp' in the # parameter list) can collide with exploded members of the event's # data type passed in as parameters. If this collision ever hits in @@ -67,14 +72,17 @@ def gen_event_send(name, arg_type): Error *err = NULL; QMPEventFuncEmit emit; ''', - proto=gen_event_send_proto(name, arg_type)) + proto=gen_event_send_proto(name, arg_type, boxed)) - if arg_type and arg_type.members: + if arg_type and not arg_type.is_empty(): ret += mcgen(''' QObject *obj; Visitor *v; ''') - ret += gen_param_var(arg_type) + if not boxed: + ret += gen_param_var(arg_type) + else: + assert not boxed ret += mcgen(''' @@ -88,9 +96,17 @@ def gen_event_send(name, arg_type): ''', name=name) - if arg_type and arg_type.members: + if arg_type and not arg_type.is_empty(): ret += mcgen(''' v = qmp_output_visitor_new(&obj); +''') + if not arg_type.is_implicit(): + ret += mcgen(''' + visit_type_%(c_name)s(v, "%(name)s", &arg, &err); +''', + name=name, c_name=arg_type.c_name()) + else: + ret += mcgen(''' visit_start_struct(v, "%(name)s", NULL, 0, &err); if (err) { @@ -101,14 +117,16 @@ def gen_event_send(name, arg_type): visit_check_struct(v, &err); } visit_end_struct(v, NULL); +''', + name=name, c_name=arg_type.c_name()) + ret += mcgen(''' if (err) { goto out; } visit_complete(v, &obj); qdict_put_obj(qmp, "data", obj); -''', - name=name, c_name=arg_type.c_name()) +''') ret += mcgen(''' emit(%(c_enum)s, qmp, &err); @@ -116,7 +134,7 @@ def gen_event_send(name, arg_type): ''', c_enum=c_enum_const(event_enum_name, name)) - if arg_type and arg_type.members: + if arg_type and not arg_type.is_empty(): ret += mcgen(''' out: visit_free(v); @@ -145,9 +163,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor): self.defn += gen_enum_lookup(event_enum_name, self._event_names) self._event_names = None - def visit_event(self, name, info, arg_type): - self.decl += gen_event_send_decl(name, arg_type) - self.defn += gen_event_send(name, arg_type) + def visit_event(self, name, info, arg_type, boxed): + self.decl += gen_event_send_decl(name, arg_type, boxed) + self.defn += gen_event_send(name, arg_type, boxed) self._event_names.append(name) diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index e0f926be04..541644e350 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -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)}) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 5ace2cf065..dabc42e047 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -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; ''') diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 0b9e298bc4..96f2491c16 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -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(''' diff --git a/scripts/qapi.py b/scripts/qapi.py index b13ae47899..21bc32fda3 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -522,10 +522,14 @@ def check_type(expr_info, source, value, allow_array=False, def check_command(expr, expr_info): name = expr['command'] + boxed = expr.get('boxed', False) + args_meta = ['struct'] + if boxed: + args_meta += ['union', 'alternate'] check_type(expr_info, "'data' for command '%s'" % name, - expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['struct']) + expr.get('data'), allow_dict=not boxed, allow_optional=True, + allow_metas=args_meta) returns_meta = ['union', 'struct'] if name in returns_whitelist: returns_meta += ['built-in', 'alternate', 'enum'] @@ -537,11 +541,15 @@ def check_command(expr, expr_info): def check_event(expr, expr_info): global events name = expr['event'] + boxed = expr.get('boxed', False) + meta = ['struct'] + if boxed: + meta += ['union', 'alternate'] events.append(name) check_type(expr_info, "'data' for event '%s'" % name, - expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['struct']) + expr.get('data'), allow_dict=not boxed, allow_optional=True, + allow_metas=meta) def check_union(expr, expr_info): @@ -612,6 +620,14 @@ def check_union(expr, expr_info): "enum '%s'" % (key, enum_define["enum_name"])) + # If discriminator is user-defined, ensure all values are covered + if enum_define: + for value in enum_define['enum_values']: + if value not in members.keys(): + raise QAPIExprError(expr_info, + "Union '%s' data missing '%s' branch" + % (name, value)) + def check_alternate(expr, expr_info): name = expr['alternate'] @@ -686,6 +702,10 @@ def check_keys(expr_elem, meta, required, optional=[]): raise QAPIExprError(info, "'%s' of %s '%s' should only use false value" % (key, meta, name)) + if key == 'boxed' and value is not True: + raise QAPIExprError(info, + "'%s' of %s '%s' should only use true value" + % (key, meta, name)) for key in required: if key not in expr: raise QAPIExprError(info, @@ -717,10 +737,10 @@ def check_exprs(exprs): add_struct(expr, info) elif 'command' in expr: check_keys(expr_elem, 'command', [], - ['data', 'returns', 'gen', 'success-response']) + ['data', 'returns', 'gen', 'success-response', 'boxed']) add_name(expr['command'], info, 'command') elif 'event' in expr: - check_keys(expr_elem, 'event', [], ['data']) + check_keys(expr_elem, 'event', [], ['data', 'boxed']) add_name(expr['event'], info, 'event') else: raise QAPIExprError(expr_elem['info'], @@ -818,10 +838,10 @@ class QAPISchemaVisitor(object): pass def visit_command(self, name, info, arg_type, ret_type, - gen, success_response): + gen, success_response, boxed): pass - def visit_event(self, name, info, arg_type): + def visit_event(self, name, info, arg_type, boxed): pass @@ -991,7 +1011,12 @@ class QAPISchemaObjectType(QAPISchemaType): # _def_predefineds() return self.name.startswith('q_') + def is_empty(self): + assert self.members is not None + return not self.members and not self.variants + def c_name(self): + assert self.name != 'q_empty' return QAPISchemaType.c_name(self) def c_type(self): @@ -1084,7 +1109,7 @@ class QAPISchemaObjectTypeVariants(object): assert len(variants) > 0 for v in variants: assert isinstance(v, QAPISchemaObjectTypeVariant) - self.tag_name = tag_name + self._tag_name = tag_name self.tag_member = tag_member self.variants = variants @@ -1094,8 +1119,8 @@ class QAPISchemaObjectTypeVariants(object): def check(self, schema, seen): if not self.tag_member: # flat union - self.tag_member = seen[c_name(self.tag_name)] - assert self.tag_name == self.tag_member.name + self.tag_member = seen[c_name(self._tag_name)] + assert self._tag_name == self.tag_member.name assert isinstance(self.tag_member.type, QAPISchemaEnumType) for v in self.variants: v.check(schema) @@ -1125,7 +1150,7 @@ class QAPISchemaAlternateType(QAPISchemaType): def __init__(self, name, info, variants): QAPISchemaType.__init__(self, name, info) assert isinstance(variants, QAPISchemaObjectTypeVariants) - assert not variants.tag_name + assert variants.tag_member variants.set_owner(name) variants.tag_member.set_owner(self.name) self.variants = variants @@ -1150,9 +1175,13 @@ class QAPISchemaAlternateType(QAPISchemaType): def visit(self, visitor): visitor.visit_alternate_type(self.name, self.info, self.variants) + def is_empty(self): + return False + class QAPISchemaCommand(QAPISchemaEntity): - def __init__(self, name, info, arg_type, ret_type, gen, success_response): + def __init__(self, name, info, arg_type, ret_type, gen, success_response, + boxed): QAPISchemaEntity.__init__(self, name, info) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -1162,12 +1191,24 @@ class QAPISchemaCommand(QAPISchemaEntity): self.ret_type = None self.gen = gen self.success_response = success_response + self.boxed = boxed def check(self, schema): if self._arg_type_name: self.arg_type = schema.lookup_type(self._arg_type_name) - assert isinstance(self.arg_type, QAPISchemaObjectType) - assert not self.arg_type.variants # not implemented + assert (isinstance(self.arg_type, QAPISchemaObjectType) or + isinstance(self.arg_type, QAPISchemaAlternateType)) + self.arg_type.check(schema) + if self.boxed: + if self.arg_type.is_empty(): + raise QAPIExprError(self.info, + "Cannot use 'boxed' with empty type") + else: + assert not isinstance(self.arg_type, QAPISchemaAlternateType) + assert not self.arg_type.variants + elif self.boxed: + raise QAPIExprError(self.info, + "Use of 'boxed' requires 'data'") if self._ret_type_name: self.ret_type = schema.lookup_type(self._ret_type_name) assert isinstance(self.ret_type, QAPISchemaType) @@ -1175,24 +1216,36 @@ class QAPISchemaCommand(QAPISchemaEntity): def visit(self, visitor): visitor.visit_command(self.name, self.info, self.arg_type, self.ret_type, - self.gen, self.success_response) + self.gen, self.success_response, self.boxed) class QAPISchemaEvent(QAPISchemaEntity): - def __init__(self, name, info, arg_type): + def __init__(self, name, info, arg_type, boxed): QAPISchemaEntity.__init__(self, name, info) assert not arg_type or isinstance(arg_type, str) self._arg_type_name = arg_type self.arg_type = None + self.boxed = boxed def check(self, schema): if self._arg_type_name: self.arg_type = schema.lookup_type(self._arg_type_name) - assert isinstance(self.arg_type, QAPISchemaObjectType) - assert not self.arg_type.variants # not implemented + assert (isinstance(self.arg_type, QAPISchemaObjectType) or + isinstance(self.arg_type, QAPISchemaAlternateType)) + self.arg_type.check(schema) + if self.boxed: + if self.arg_type.is_empty(): + raise QAPIExprError(self.info, + "Cannot use 'boxed' with empty type") + else: + assert not isinstance(self.arg_type, QAPISchemaAlternateType) + assert not self.arg_type.variants + elif self.boxed: + raise QAPIExprError(self.info, + "Use of 'boxed' requires 'data'") def visit(self, visitor): - visitor.visit_event(self.name, self.info, self.arg_type) + visitor.visit_event(self.name, self.info, self.arg_type, self.boxed) class QAPISchema(object): @@ -1368,6 +1421,7 @@ class QAPISchema(object): rets = expr.get('returns') gen = expr.get('gen', True) success_response = expr.get('success-response', True) + boxed = expr.get('boxed', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( name, info, 'arg', self._make_members(data, info)) @@ -1375,15 +1429,16 @@ class QAPISchema(object): assert len(rets) == 1 rets = self._make_array_type(rets[0], info) self._def_entity(QAPISchemaCommand(name, info, data, rets, gen, - success_response)) + success_response, boxed)) def _def_event(self, expr, info): name = expr['event'] data = expr.get('data') + boxed = expr.get('boxed', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( name, info, 'arg', self._make_members(data, info)) - self._def_entity(QAPISchemaEvent(name, info, data)) + self._def_entity(QAPISchemaEvent(name, info, data, boxed)) def _def_exprs(self): for expr_elem in self.exprs: @@ -1626,31 +1681,29 @@ extern const char *const %(c_name)s_lookup[]; return ret -def gen_params(arg_type, extra): +def gen_params(arg_type, boxed, extra): if not arg_type: + assert not boxed return extra - assert not arg_type.variants ret = '' sep = '' - for memb in arg_type.members: - ret += sep + if boxed: + ret += '%s arg' % arg_type.c_param_type() sep = ', ' - if memb.optional: - ret += 'bool has_%s, ' % c_name(memb.name) - ret += '%s %s' % (memb.type.c_param_type(), c_name(memb.name)) + else: + assert not arg_type.variants + for memb in arg_type.members: + ret += sep + sep = ', ' + if memb.optional: + ret += 'bool has_%s, ' % c_name(memb.name) + ret += '%s %s' % (memb.type.c_param_type(), + c_name(memb.name)) if extra: ret += sep + extra return ret -def gen_err_check(): - return mcgen(''' - if (err) { - goto out; - } -''') - - # # Common command line parsing # diff --git a/tests/Makefile.include b/tests/Makefile.include index 2010b11b6c..e7e50d6bd9 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -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 diff --git a/tests/qapi-schema/args-bad-boxed.err b/tests/qapi-schema/args-bad-boxed.err new file mode 100644 index 0000000000..ad0d417321 --- /dev/null +++ b/tests/qapi-schema/args-bad-boxed.err @@ -0,0 +1 @@ +tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value diff --git a/tests/qapi-schema/args-bad-boxed.exit b/tests/qapi-schema/args-bad-boxed.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/args-bad-boxed.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-bad-boxed.json b/tests/qapi-schema/args-bad-boxed.json new file mode 100644 index 0000000000..dea0cd0aa5 --- /dev/null +++ b/tests/qapi-schema/args-bad-boxed.json @@ -0,0 +1,2 @@ +# 'boxed' should only appear with value true +{ 'command': 'foo', 'boxed': false } diff --git a/tests/qapi-schema/args-bad-boxed.out b/tests/qapi-schema/args-bad-boxed.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/args-boxed-anon.err b/tests/qapi-schema/args-boxed-anon.err new file mode 100644 index 0000000000..f24f345218 --- /dev/null +++ b/tests/qapi-schema/args-boxed-anon.err @@ -0,0 +1 @@ +tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name diff --git a/tests/qapi-schema/args-boxed-anon.exit b/tests/qapi-schema/args-boxed-anon.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/args-boxed-anon.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-boxed-anon.json b/tests/qapi-schema/args-boxed-anon.json new file mode 100644 index 0000000000..95f60da2ed --- /dev/null +++ b/tests/qapi-schema/args-boxed-anon.json @@ -0,0 +1,2 @@ +# 'boxed' can only be used with named types +{ 'command': 'foo', 'boxed': true, 'data': { 'string': 'str' } } diff --git a/tests/qapi-schema/args-boxed-anon.out b/tests/qapi-schema/args-boxed-anon.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/args-boxed-empty.err b/tests/qapi-schema/args-boxed-empty.err new file mode 100644 index 0000000000..039603e85c --- /dev/null +++ b/tests/qapi-schema/args-boxed-empty.err @@ -0,0 +1 @@ +tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type diff --git a/tests/qapi-schema/args-boxed-empty.exit b/tests/qapi-schema/args-boxed-empty.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/args-boxed-empty.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-boxed-empty.json b/tests/qapi-schema/args-boxed-empty.json new file mode 100644 index 0000000000..52717e065f --- /dev/null +++ b/tests/qapi-schema/args-boxed-empty.json @@ -0,0 +1,3 @@ +# 'boxed' requires a non-empty type +{ 'struct': 'Empty', 'data': {} } +{ 'command': 'foo', 'boxed': true, 'data': 'Empty' } diff --git a/tests/qapi-schema/args-boxed-empty.out b/tests/qapi-schema/args-boxed-empty.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/args-boxed-string.err b/tests/qapi-schema/args-boxed-string.err new file mode 100644 index 0000000000..d326b48aef --- /dev/null +++ b/tests/qapi-schema/args-boxed-string.err @@ -0,0 +1 @@ +tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str' diff --git a/tests/qapi-schema/args-boxed-string.exit b/tests/qapi-schema/args-boxed-string.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/args-boxed-string.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-boxed-string.json b/tests/qapi-schema/args-boxed-string.json new file mode 100644 index 0000000000..f91a1502e7 --- /dev/null +++ b/tests/qapi-schema/args-boxed-string.json @@ -0,0 +1,2 @@ +# 'boxed' requires a complex (not built-in) type +{ 'command': 'foo', 'boxed': true, 'data': 'str' } diff --git a/tests/qapi-schema/args-boxed-string.out b/tests/qapi-schema/args-boxed-string.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err index 1d693d74da..f8ad223dde 100644 --- a/tests/qapi-schema/args-union.err +++ b/tests/qapi-schema/args-union.err @@ -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' diff --git a/tests/qapi-schema/args-union.json b/tests/qapi-schema/args-union.json index 7bdcbb7f08..2fcaeaae16 100644 --- a/tests/qapi-schema/args-union.json +++ b/tests/qapi-schema/args-union.json @@ -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' } diff --git a/tests/qapi-schema/event-boxed-empty.err b/tests/qapi-schema/event-boxed-empty.err new file mode 100644 index 0000000000..68ec6f2d2b --- /dev/null +++ b/tests/qapi-schema/event-boxed-empty.err @@ -0,0 +1 @@ +tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data' diff --git a/tests/qapi-schema/event-boxed-empty.exit b/tests/qapi-schema/event-boxed-empty.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/event-boxed-empty.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/event-boxed-empty.json b/tests/qapi-schema/event-boxed-empty.json new file mode 100644 index 0000000000..cb145f1433 --- /dev/null +++ b/tests/qapi-schema/event-boxed-empty.json @@ -0,0 +1,2 @@ +# 'boxed' requires a non-empty type +{ 'event': 'FOO', 'boxed': true } diff --git a/tests/qapi-schema/event-boxed-empty.out b/tests/qapi-schema/event-boxed-empty.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out index b6b4134a80..5a0f2bf805 100644 --- a/tests/qapi-schema/event-case.out +++ b/tests/qapi-schema/event-case.out @@ -1,4 +1,5 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool'] prefix QTYPE event oops None + boxed=False object q_empty diff --git a/tests/qapi-schema/flat-union-incomplete-branch.err b/tests/qapi-schema/flat-union-incomplete-branch.err new file mode 100644 index 0000000000..e826bf0789 --- /dev/null +++ b/tests/qapi-schema/flat-union-incomplete-branch.err @@ -0,0 +1 @@ +tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch diff --git a/tests/qapi-schema/flat-union-incomplete-branch.exit b/tests/qapi-schema/flat-union-incomplete-branch.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/flat-union-incomplete-branch.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/flat-union-incomplete-branch.json b/tests/qapi-schema/flat-union-incomplete-branch.json new file mode 100644 index 0000000000..25a411bc83 --- /dev/null +++ b/tests/qapi-schema/flat-union-incomplete-branch.json @@ -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' } } diff --git a/tests/qapi-schema/flat-union-incomplete-branch.out b/tests/qapi-schema/flat-union-incomplete-branch.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out index 382ce2fa27..1d2722c02e 100644 --- a/tests/qapi-schema/ident-with-escape.out +++ b/tests/qapi-schema/ident-with-escape.out @@ -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 diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out index ae3293a3ae..e8171c935f 100644 --- a/tests/qapi-schema/indented-expr.out +++ b/tests/qapi-schema/indented-expr.out @@ -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 diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index f571e1bb34..17194637ba 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -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 diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 19cd214f6b..9d99c4eebb 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -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 diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 649677e017..ef74e2c4c8 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -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) diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index 8ffeb045cd..5af1a468b8 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -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,