* [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups
@ 2015-09-10 4:06 Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 01/29] qapi: Provide nicer array names in introspection Eric Blake
` (28 more replies)
0 siblings, 29 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, armbru, Eduardo Habkost, DirtY.iCE.hu
Still RFC because it depends on Markus' RFC v5 (actually his
qapi-introspect branch at commit 87e905b):
https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01599.html
v1 was here:
https://lists.gnu.org/archive/html/qemu-devel/2015-07/msg05266.html
https://lists.gnu.org/archive/html/qemu-devel/2015-07/msg05325.html
In v2:
https://lists.gnu.org/archive/html/qemu-devel/2015-08/msg00900.html
rebase to Markus' v3 series
rework how comments are emitted for fields inherited from base
additional patches added for deleting colliding 'void *data'
documentation updates to match code changes
In v3:
https://lists.gnu.org/archive/html/qemu-devel/2015-08/msg02059.html
redo cleanup of dealloc of partial struct
add patches to make all visit_type_*() avoid leaks on failure
add patches to allow boxed command arguments and events
In v4:
add some more clean up patches
rebase to Markus' recent work
pull in part of Zoltán's work to make netdev_add a flat union,
further enhancing it to be introspectible
I might be able to rearrange some of these patches, or separate
it into smaller independent series, if requested; but I'm
posting now to get review started.
Eric Blake (27):
qapi: Provide nicer array names in introspection
qapi: use 'type' in generated C code to match QMP union wire form
vnc: hoist allocation of VncBasicInfo to callers
qapi: Unbox base members
qapi-visit: Remove redundant functions for flat union base
qapi: Test use of 'number' within alternates
qapi: Simplify visiting of alternate types
qapi: Hide tag_name data member of variants
qapi: Fix alternates that accept 'number' but not 'int'
qapi: Don't pass pre-existing error to later call
qapi: Use consistent generated code patterns
qapi: Add tests for empty unions
qapi: Rework deallocation of partial struct
qapi: Avoid use of 'data' member of qapi unions
qapi: Forbid empty unions and useless alternates
qapi: Drop useless 'data' member of unions
qapi: Remove dead visitor code
qapi: Document visitor interfaces
qapi: Plug leaks in test-qmp-input-visitor
qapi: Test failure in middle of array parse
qapi: Change visit_type_FOO() to no longer return partial objects
qapi: Plumb in 'box' to qapi generator lower levels
qapi: Implement boxed structs for commands/events
qapi: Support boxed unions
qapi: Clean up qapi.py per pep8
net: Use correct type for bool flag
net: Complete qapi-fication of netdev_add
Kővágó, Zoltán (2):
net: use Netdev instead of NetClientOptions in client init
qapi: Change Netdev into a flat union
block/qcow2.c | 2 +-
block/vmdk.c | 2 +-
blockdev.c | 34 ++--
docs/qapi-code-gen.txt | 47 +++--
hmp.c | 18 +-
hw/arm/musicpal.c | 2 +-
hw/core/qdev-properties-system.c | 2 +-
hw/input/hid.c | 2 +-
hw/input/ps2.c | 2 +-
hw/input/virtio-input-hid.c | 2 +-
hw/mem/pc-dimm.c | 2 +-
hw/net/allwinner_emac.c | 2 +-
hw/net/cadence_gem.c | 2 +-
hw/net/dp8393x.c | 2 +-
hw/net/e1000.c | 2 +-
hw/net/eepro100.c | 2 +-
hw/net/etraxfs_eth.c | 2 +-
hw/net/fsl_etsec/etsec.c | 2 +-
hw/net/imx_fec.c | 2 +-
hw/net/lan9118.c | 2 +-
hw/net/lance.c | 2 +-
hw/net/mcf_fec.c | 2 +-
hw/net/milkymist-minimac2.c | 2 +-
hw/net/mipsnet.c | 2 +-
hw/net/ne2000-isa.c | 2 +-
hw/net/ne2000.c | 2 +-
hw/net/opencores_eth.c | 2 +-
hw/net/pcnet-pci.c | 2 +-
hw/net/rocker/rocker_fp.c | 2 +-
hw/net/rtl8139.c | 2 +-
hw/net/smc91c111.c | 2 +-
hw/net/spapr_llan.c | 2 +-
hw/net/stellaris_enet.c | 2 +-
hw/net/vhost_net.c | 18 +-
hw/net/virtio-net.c | 6 +-
hw/net/vmxnet3.c | 2 +-
hw/net/xen_nic.c | 2 +-
hw/net/xgmac.c | 2 +-
hw/net/xilinx_axienet.c | 2 +-
hw/net/xilinx_ethlite.c | 2 +-
hw/usb/dev-network.c | 4 +-
include/net/net.h | 7 +-
include/qapi/visitor-impl.h | 55 ++++--
include/qapi/visitor.h | 222 ++++++++++++++++++++++--
monitor.c | 14 +-
net/clients.h | 20 +--
net/dump.c | 8 +-
net/hub.c | 24 +--
net/l2tpv3.c | 8 +-
net/net.c | 180 +++++++++++---------
net/netmap.c | 6 +-
net/slirp.c | 8 +-
net/socket.c | 10 +-
net/tap-win32.c | 8 +-
net/tap.c | 28 +--
net/vde.c | 8 +-
net/vhost-user.c | 14 +-
numa.c | 4 +-
qapi-schema.json | 72 +++++---
qapi/qapi-dealloc-visitor.c | 26 ---
qapi/qapi-visit-core.c | 158 +++++++----------
qapi/qmp-input-visitor.c | 8 +-
qemu-char.c | 24 +--
qmp-commands.hx | 2 +-
scripts/qapi-commands.py | 101 ++++++-----
scripts/qapi-event.py | 75 ++++----
scripts/qapi-introspect.py | 12 +-
scripts/qapi-types.py | 83 +++------
scripts/qapi-visit.py | 164 ++++++++++--------
scripts/qapi.py | 284 ++++++++++++++++++++-----------
tests/Makefile | 6 +-
tests/qapi-schema/alternate-empty.err | 1 +
tests/qapi-schema/alternate-empty.exit | 1 +
tests/qapi-schema/alternate-empty.json | 2 +
tests/qapi-schema/alternate-empty.out | 0
tests/qapi-schema/alternate-good.out | 1 -
tests/qapi-schema/alternate-nested.json | 2 +-
tests/qapi-schema/alternate-unknown.json | 2 +-
tests/qapi-schema/args-bad-box.err | 1 +
tests/qapi-schema/args-bad-box.exit | 1 +
tests/qapi-schema/args-bad-box.json | 2 +
tests/qapi-schema/args-bad-box.out | 0
tests/qapi-schema/args-box-anon.err | 1 +
tests/qapi-schema/args-box-anon.exit | 1 +
tests/qapi-schema/args-box-anon.json | 2 +
tests/qapi-schema/args-box-anon.out | 0
tests/qapi-schema/args-box-empty.err | 1 +
tests/qapi-schema/args-box-empty.exit | 1 +
tests/qapi-schema/args-box-empty.json | 2 +
tests/qapi-schema/args-box-empty.out | 0
tests/qapi-schema/args-member-array.out | 2 +-
tests/qapi-schema/args-union.err | 2 +-
tests/qapi-schema/args-union.json | 3 +-
tests/qapi-schema/event-case.out | 1 +
tests/qapi-schema/flat-union-empty.err | 1 +
tests/qapi-schema/flat-union-empty.exit | 1 +
tests/qapi-schema/flat-union-empty.json | 4 +
tests/qapi-schema/flat-union-empty.out | 0
tests/qapi-schema/ident-with-escape.out | 2 +-
tests/qapi-schema/indented-expr.out | 4 +-
tests/qapi-schema/qapi-schema-test.json | 15 +-
tests/qapi-schema/qapi-schema-test.out | 49 ++++--
tests/qapi-schema/returns-int.out | 2 +-
tests/qapi-schema/test-qapi.py | 12 +-
tests/qapi-schema/union-empty.err | 1 +
tests/qapi-schema/union-empty.exit | 1 +
tests/qapi-schema/union-empty.json | 2 +
tests/qapi-schema/union-empty.out | 0
tests/test-qmp-commands.c | 40 ++---
tests/test-qmp-event.c | 8 +-
tests/test-qmp-input-visitor.c | 198 ++++++++++++++++++---
tests/test-qmp-output-visitor.c | 39 +++--
tests/test-visitor-serialization.c | 14 +-
tpm.c | 2 +-
ui/input-keymap.c | 10 +-
ui/input-legacy.c | 2 +-
ui/input.c | 24 +--
ui/spice-core.c | 23 +--
ui/vnc.c | 64 +++----
util/qemu-sockets.c | 12 +-
120 files changed, 1471 insertions(+), 924 deletions(-)
create mode 100644 tests/qapi-schema/alternate-empty.err
create mode 100644 tests/qapi-schema/alternate-empty.exit
create mode 100644 tests/qapi-schema/alternate-empty.json
create mode 100644 tests/qapi-schema/alternate-empty.out
create mode 100644 tests/qapi-schema/args-bad-box.err
create mode 100644 tests/qapi-schema/args-bad-box.exit
create mode 100644 tests/qapi-schema/args-bad-box.json
create mode 100644 tests/qapi-schema/args-bad-box.out
create mode 100644 tests/qapi-schema/args-box-anon.err
create mode 100644 tests/qapi-schema/args-box-anon.exit
create mode 100644 tests/qapi-schema/args-box-anon.json
create mode 100644 tests/qapi-schema/args-box-anon.out
create mode 100644 tests/qapi-schema/args-box-empty.err
create mode 100644 tests/qapi-schema/args-box-empty.exit
create mode 100644 tests/qapi-schema/args-box-empty.json
create mode 100644 tests/qapi-schema/args-box-empty.out
create mode 100644 tests/qapi-schema/flat-union-empty.err
create mode 100644 tests/qapi-schema/flat-union-empty.exit
create mode 100644 tests/qapi-schema/flat-union-empty.json
create mode 100644 tests/qapi-schema/flat-union-empty.out
create mode 100644 tests/qapi-schema/union-empty.err
create mode 100644 tests/qapi-schema/union-empty.exit
create mode 100644 tests/qapi-schema/union-empty.json
create mode 100644 tests/qapi-schema/union-empty.out
--
2.4.3
^ permalink raw reply [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 01/29] qapi: Provide nicer array names in introspection
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 02/29] net: use Netdev instead of NetClientOptions in client init Eric Blake
` (27 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
For the sake of humans reading introspection output, it is nice
to have the name of implicit array types be recognizable as
arrays of the underlying type. However, while this allows
humans to skip from a command with return type "[123]" straight
to the definition of type "123" without having to first inspect
type "[123]", document that this shortcut should not be taken by
client apps.
This makes the resulting introspection string slightly larger by
default, but slightly smaller when -u is in use (as '[FOO]' is
nicer than 'FOOList' for expressing 'array of FOO').
Signed-off-by: Eric Blake <eblake@redhat.com>
---
docs/qapi-code-gen.txt | 7 +++++--
scripts/qapi-introspect.py | 8 +++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 01e292b..8d87e67 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -650,11 +650,14 @@ Example: the SchemaInfo for BlockRef from section Alternate types
The SchemaInfo for an array type has meta-type "array", and variant
member "element-type", which names the array's element type. Array
-types are implicitly defined.
+types are implicitly defined. For convenience, the array's name may
+resemble the element type; however, clients should examine member
+"element-type" instead of making assumptions based on parsing member
+"name".
Example: the SchemaInfo for ['str']
- { "name": "strList", "meta-type": "array",
+ { "name": "[str]", "meta-type": "array",
"element-type": "str" }
The SchemaInfo for an enumeration type has meta-type "enum" and
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index ce98321..eef5f1d 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -104,10 +104,12 @@ const char %(c_name)s[] = %(c_string)s;
# characters.
if isinstance(typ, QAPISchemaBuiltinType):
return typ.name
+ if isinstance(typ, QAPISchemaArrayType):
+ return '[' + self._use_type(typ.element_type) + ']'
return self._name(typ.name)
def _gen_json(self, name, mtype, obj):
- if mtype != 'command' and mtype != 'event' and mtype != 'builtin':
+ if mtype not in ('command', 'event', 'builtin', 'array'):
name = self._name(name)
obj['name'] = name
obj['meta-type'] = mtype
@@ -133,8 +135,8 @@ const char %(c_name)s[] = %(c_string)s;
self._gen_json(name, 'enum', {'values': values})
def visit_array_type(self, name, info, element_type):
- self._gen_json(name, 'array',
- {'element-type': self._use_type(element_type)})
+ element = self._use_type(element_type)
+ self._gen_json('[' + element + ']', 'array', {'element-type': element})
def visit_object_type_flat(self, name, info, members, variants):
obj = {'members': [self._gen_member(m) for m in members]}
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 02/29] net: use Netdev instead of NetClientOptions in client init
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 01/29] qapi: Provide nicer array names in introspection Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 03/29] qapi: use 'type' in generated C code to match QMP union wire form Eric Blake
` (26 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Jason Wang, armbru, Vincenzo Maffione,
Stefan Hajnoczi, Kővágó, Zoltán,
marcandre.lureau, Giuseppe Lettieri, Luigi Rizzo
From: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
This way we no longer need NetClientOptions and can convert Netdev
into a flat union.
Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <93ffdfed7054529635e6acb935150d95dc173a12.1441627176.git.DirtY.iCE.hu@gmail.com>
[rework net_client_init1() to pass Netdev by copying from NetdevLegacy,
rather than merging the two types.]
Signed-off-by: Eric Blake <eblake@redhat.com>
---
net/clients.h | 20 ++++++++++----------
net/dump.c | 6 +++---
net/hub.c | 6 +++---
net/l2tpv3.c | 6 +++---
net/net.c | 18 +++++++++++-------
net/netmap.c | 4 ++--
net/slirp.c | 6 +++---
net/socket.c | 6 +++---
net/tap-win32.c | 6 +++---
net/tap.c | 12 ++++++------
net/vde.c | 6 +++---
net/vhost-user.c | 6 +++---
12 files changed, 53 insertions(+), 49 deletions(-)
diff --git a/net/clients.h b/net/clients.h
index d47530e..5cae479 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 02c8064..d80fa94 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -146,7 +146,7 @@ static int net_dump_init(NetClientState *peer, const char *device,
return 0;
}
-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;
@@ -154,8 +154,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
char def_file[128];
const NetdevDumpOptions *dump;
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
- dump = opts->dump;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
+ dump = netdev->opts->dump;
assert(peer);
diff --git a/net/hub.c b/net/hub.c
index 3047f12..29f65b2 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -280,14 +280,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->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
assert(!peer);
- hubport = opts->hubport;
+ hubport = netdev->opts->hubport;
net_hub_add_port(hubport->hubid, name);
return 0;
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index 4f9bcee..d2f8431 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -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->kind == NET_CLIENT_OPTIONS_KIND_L2TPV3);
- l2tpv3 = opts->l2tpv3;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_L2TPV3);
+ l2tpv3 = netdev->opts->l2tpv3;
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
s->ipv6 = l2tpv3->ipv6;
diff --git a/net/net.c b/net/net.c
index 28a5597..4d99b48 100644
--- a/net/net.c
+++ b/net/net.c
@@ -813,15 +813,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->kind == NET_CLIENT_OPTIONS_KIND_NIC);
- nic = opts->nic;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
+ nic = netdev->opts->nic;
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
@@ -882,7 +882,7 @@ 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,
+ const Netdev *netdev,
const char *name,
NetClientState *peer, Error **errp) = {
[NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic,
@@ -914,11 +914,13 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
static int net_client_init1(const void *object, int 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;
+ netdev = object;
opts = netdev->opts;
name = netdev->id;
@@ -931,7 +933,9 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
}
} else {
const NetLegacy *net = object;
- opts = net->opts;
+ legacy.id = net->id;
+ opts = legacy.opts = net->opts;
+ netdev = &legacy;
/* missing optional values have been initialized to "all bits zero" */
name = net->has_id ? net->id : net->name;
@@ -958,7 +962,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
}
}
- if (net_client_init_fun[opts->kind](opts, name, peer, errp) < 0) {
+ if (net_client_init_fun[opts->kind](netdev, name, peer, errp) < 0) {
/* FIXME drop when all init functions store an Error */
if (errp && !*errp) {
error_setg(errp, QERR_DEVICE_INIT_FAILED,
diff --git a/net/netmap.c b/net/netmap.c
index 508b829..a464618 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -435,11 +435,11 @@ 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)
{
/* FIXME error_setg(errp, ...) on failure */
- const NetdevNetmapOptions *netmap_opts = opts->netmap;
+ const NetdevNetmapOptions *netmap_opts = netdev->opts->netmap;
NetClientState *nc;
NetmapPriv me;
NetmapState *s;
diff --git a/net/slirp.c b/net/slirp.c
index 7657b38..0fc2c52 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -736,7 +736,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 */
@@ -746,8 +746,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
const NetdevUserOptions *user;
const char **dnssearch;
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_USER);
- user = opts->user;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_USER);
+ user = netdev->opts->user;
vnet = user->has_net ? g_strdup(user->net) :
user->has_ip ? g_strdup_printf("%s/24", user->ip) :
diff --git a/net/socket.c b/net/socket.c
index b1e3b1c..75f693c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -699,15 +699,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->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
- sock = opts->socket;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
+ sock = netdev->opts->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 625d53c..acce480 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -761,14 +761,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->kind == NET_CLIENT_OPTIONS_KIND_TAP);
- tap = opts->tap;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
+ tap = netdev->opts->tap;
if (!tap->has_ifname) {
error_report("tap: no interface name");
diff --git a/net/tap.c b/net/tap.c
index bd01590..263f807 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -557,7 +557,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;
@@ -565,8 +565,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
TAPState *s;
int fd, vnet_hdr;
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_BRIDGE);
- bridge = opts->bridge;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_BRIDGE);
+ bridge = netdev->opts->bridge;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
@@ -716,7 +716,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;
@@ -728,8 +728,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
const char *vhostfdname;
char ifname[128];
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
- tap = opts->tap;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
+ tap = netdev->opts->tap;
queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
diff --git a/net/vde.c b/net/vde.c
index dacaa64..0ac2525 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -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->kind == NET_CLIENT_OPTIONS_KIND_VDE);
- vde = opts->vde;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_VDE);
+ vde = netdev->opts->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 93dcecd..20981a9 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -223,14 +223,14 @@ 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)
{
const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr;
- assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
- vhost_user_opts = opts->vhost_user;
+ assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+ vhost_user_opts = netdev->opts->vhost_user;
chr = net_vhost_parse_chardev(vhost_user_opts, errp);
if (!chr) {
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 03/29] qapi: use 'type' in generated C code to match QMP union wire form
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 01/29] qapi: Provide nicer array names in introspection Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 02/29] net: use Netdev instead of NetClientOptions in client init Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 04/29] vnc: hoist allocation of VncBasicInfo to callers Eric Blake
` (25 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Fam Zheng, Eduardo Habkost, open list:qcow2,
Michael S. Tsirkin, Jason Wang, armbru, Luiz Capitulino,
Igor Mammedov, Paolo Bonzini, Gerd Hoffmann, Stefan Hajnoczi,
DirtY.iCE.hu, marcandre.lureau, Michael Roth
When dealing with simple qapi unions, the code was generating a
discriminator field of 'kind' even though the discriminator is
sent as 'type' over QMP. Renaming things to match gets us one
step closer to reusing common generator code for both simple and
flat unions, without having to special case the naming choice
for simple unions. It also gets rid of some TODO markers in
using the raw QAPISchemaObjectTypeVariants.tag_name field,
although we can't yet convert that field to private until later
fixes to alternate types also quit using it.
However, this patch does not rename the generated enum, which is
still 'unionnameKind'; if we wanted, a further patch could
generate implicit enums as 'unionnameType', with even more
churn to C code to react, and probably update the qapi generator
to reserve the 'fooType' namespace instead of 'fooKind', or better
yet ensure that generated names do not conflict with user names.
But that is a lot harder, as we already have existing qapi usage
of types that end in 'Type'.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
block/qcow2.c | 2 +-
block/vmdk.c | 2 +-
blockdev.c | 16 ++++++++--------
hmp.c | 12 ++++++------
hw/input/hid.c | 2 +-
hw/input/ps2.c | 2 +-
hw/input/virtio-input-hid.c | 2 +-
hw/mem/pc-dimm.c | 2 +-
net/dump.c | 2 +-
net/hub.c | 2 +-
net/l2tpv3.c | 2 +-
net/net.c | 20 ++++++++++----------
net/slirp.c | 2 +-
net/socket.c | 2 +-
net/tap.c | 4 ++--
net/vhost-user.c | 2 +-
numa.c | 4 ++--
qemu-char.c | 24 ++++++++++++------------
scripts/qapi-types.py | 7 ++-----
scripts/qapi-visit.py | 13 +++----------
tests/test-qmp-commands.c | 2 +-
tests/test-qmp-input-visitor.c | 10 +++++-----
tests/test-qmp-output-visitor.c | 8 ++++----
tpm.c | 2 +-
ui/input-keymap.c | 10 +++++-----
ui/input-legacy.c | 2 +-
ui/input.c | 22 +++++++++++-----------
util/qemu-sockets.c | 12 ++++++------
28 files changed, 91 insertions(+), 101 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index ea34ae2..dc3a73f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2596,7 +2596,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
*spec_info = (ImageInfoSpecific){
- .kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
+ .type = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
{
.qcow2 = g_new(ImageInfoSpecificQCow2, 1),
},
diff --git a/block/vmdk.c b/block/vmdk.c
index fbaab67..180f416 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2153,7 +2153,7 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
ImageInfoList **next;
*spec_info = (ImageInfoSpecific){
- .kind = IMAGE_INFO_SPECIFIC_KIND_VMDK,
+ .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
{
.vmdk = g_new0(ImageInfoSpecificVmdk, 1),
},
diff --git a/blockdev.c b/blockdev.c
index 6b48be6..e4cec0e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1052,12 +1052,12 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
}
}
-static void blockdev_do_action(int kind, void *data, Error **errp)
+static void blockdev_do_action(int type, void *data, Error **errp)
{
TransactionAction action;
TransactionActionList list;
- action.kind = kind;
+ action.type = type;
action.data = data;
list.value = &action;
list.next = NULL;
@@ -1297,7 +1297,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
InternalSnapshotState *state;
int ret1;
- g_assert(common->action->kind ==
+ g_assert(common->action->type ==
TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
internal = common->action->blockdev_snapshot_internal_sync;
state = DO_UPCAST(InternalSnapshotState, common, common);
@@ -1440,7 +1440,7 @@ static void external_snapshot_prepare(BlkTransactionState *common,
TransactionAction *action = common->action;
/* get parameters */
- g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);
+ g_assert(action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);
has_device = action->blockdev_snapshot_sync->has_device;
device = action->blockdev_snapshot_sync->device;
@@ -1585,7 +1585,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
DriveBackup *backup;
Error *local_err = NULL;
- assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
+ assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
backup = common->action->drive_backup;
blk = blk_by_name(backup->device);
@@ -1653,7 +1653,7 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp)
BlockBackend *blk;
Error *local_err = NULL;
- assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
+ assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
backup = common->action->blockdev_backup;
blk = blk_by_name(backup->device);
@@ -1780,9 +1780,9 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp)
dev_info = dev_entry->value;
dev_entry = dev_entry->next;
- assert(dev_info->kind < ARRAY_SIZE(actions));
+ assert(dev_info->type < ARRAY_SIZE(actions));
- ops = &actions[dev_info->kind];
+ ops = &actions[dev_info->type];
assert(ops->instance_size > 0);
state = g_malloc0(ops->instance_size);
diff --git a/hmp.c b/hmp.c
index 3f807b7..849b292 100644
--- a/hmp.c
+++ b/hmp.c
@@ -830,9 +830,9 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_lookup[ti->model]);
monitor_printf(mon, " \\ %s: type=%s",
- ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]);
+ ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
- switch (ti->options->kind) {
+ switch (ti->options->type) {
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
tpo = ti->options->passthrough;
monitor_printf(mon, "%s%s%s%s",
@@ -1714,14 +1714,14 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
if (*endp != '\0') {
goto err_out;
}
- keylist->value->kind = KEY_VALUE_KIND_NUMBER;
+ keylist->value->type = KEY_VALUE_KIND_NUMBER;
keylist->value->number = value;
} else {
int idx = index_from_key(keyname_buf);
if (idx == Q_KEY_CODE_MAX) {
goto err_out;
}
- keylist->value->kind = KEY_VALUE_KIND_QCODE;
+ keylist->value->type = KEY_VALUE_KIND_QCODE;
keylist->value->qcode = idx;
}
@@ -1937,12 +1937,12 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
value = info->value;
if (value) {
- switch (value->kind) {
+ switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
di = value->dimm;
monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
- MemoryDeviceInfoKind_lookup[value->kind],
+ MemoryDeviceInfoKind_lookup[value->type],
di->id ? di->id : "");
monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr);
monitor_printf(mon, " slot: %" PRId64 "\n", di->slot);
diff --git a/hw/input/hid.c b/hw/input/hid.c
index 21ebd9e..ac02f88 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -119,7 +119,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
assert(hs->n < QUEUE_LENGTH);
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
- switch (evt->kind) {
+ switch (evt->type) {
case INPUT_EVENT_KIND_REL:
if (evt->rel->axis == INPUT_AXIS_X) {
e->xdx += evt->rel->value;
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index fdbe565..58decf2 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -393,7 +393,7 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
return;
- switch (evt->kind) {
+ switch (evt->type) {
case INPUT_EVENT_KIND_REL:
if (evt->rel->axis == INPUT_AXIS_X) {
s->mouse_dx += evt->rel->value;
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index 4d85dad..362dad3 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -191,7 +191,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
virtio_input_event event;
int qcode;
- switch (evt->kind) {
+ switch (evt->type) {
case INPUT_EVENT_KIND_KEY:
qcode = qemu_input_key_value_to_qcode(evt->key->key);
if (qcode && keymap_qcode[qcode]) {
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index bb04862..a444195 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -196,7 +196,7 @@ ram_addr_t get_current_ram_size(void)
MemoryDeviceInfo *value = info->value;
if (value) {
- switch (value->kind) {
+ switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
size += value->dimm->size;
break;
diff --git a/net/dump.c b/net/dump.c
index d80fa94..a1f99c3 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -154,7 +154,7 @@ int net_init_dump(const Netdev *netdev, const char *name,
char def_file[128];
const NetdevDumpOptions *dump;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_DUMP);
dump = netdev->opts->dump;
assert(peer);
diff --git a/net/hub.c b/net/hub.c
index 29f65b2..047d861 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -285,7 +285,7 @@ int net_init_hubport(const Netdev *netdev, const char *name,
{
const NetdevHubPortOptions *hubport;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT);
assert(!peer);
hubport = netdev->opts->hubport;
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index d2f8431..bdb13fa 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -545,7 +545,7 @@ int net_init_l2tpv3(const Netdev *netdev,
s->queue_tail = 0;
s->header_mismatch = false;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_L2TPV3);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3);
l2tpv3 = netdev->opts->l2tpv3;
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
diff --git a/net/net.c b/net/net.c
index 4d99b48..94a3d18 100644
--- a/net/net.c
+++ b/net/net.c
@@ -820,7 +820,7 @@ static int net_init_nic(const Netdev *netdev, const char *name,
NICInfo *nd;
const NetLegacyNicOptions *nic;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
nic = netdev->opts->nic;
idx = nic_get_free_idx();
@@ -924,9 +924,9 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
opts = netdev->opts;
name = netdev->id;
- if (opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP ||
- opts->kind == NET_CLIENT_OPTIONS_KIND_NIC ||
- !net_client_init_fun[opts->kind]) {
+ if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP ||
+ opts->type == NET_CLIENT_OPTIONS_KIND_NIC ||
+ !net_client_init_fun[opts->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a netdev backend type");
return -1;
@@ -939,16 +939,16 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
/* missing optional values have been initialized to "all bits zero" */
name = net->has_id ? net->id : net->name;
- if (opts->kind == NET_CLIENT_OPTIONS_KIND_NONE) {
+ if (opts->type == NET_CLIENT_OPTIONS_KIND_NONE) {
return 0; /* nothing to do */
}
- if (opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
+ if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net type");
return -1;
}
- if (!net_client_init_fun[opts->kind]) {
+ if (!net_client_init_fun[opts->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net backend type (maybe it is not compiled "
"into this binary)");
@@ -956,17 +956,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->kind != NET_CLIENT_OPTIONS_KIND_NIC ||
+ if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC ||
!opts->nic->has_netdev) {
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
}
}
- if (net_client_init_fun[opts->kind](netdev, name, peer, errp) < 0) {
+ if (net_client_init_fun[opts->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->kind]);
+ NetClientOptionsKind_lookup[opts->type]);
}
return -1;
}
diff --git a/net/slirp.c b/net/slirp.c
index 0fc2c52..e160b9c 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -746,7 +746,7 @@ int net_init_slirp(const Netdev *netdev, const char *name,
const NetdevUserOptions *user;
const char **dnssearch;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_USER);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_USER);
user = netdev->opts->user;
vnet = user->has_net ? g_strdup(user->net) :
diff --git a/net/socket.c b/net/socket.c
index 75f693c..7f949e2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -706,7 +706,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
Error *err = NULL;
const NetdevSocketOptions *sock;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET);
sock = netdev->opts->socket;
if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
diff --git a/net/tap.c b/net/tap.c
index 263f807..aecc759 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -565,7 +565,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
TAPState *s;
int fd, vnet_hdr;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_BRIDGE);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
bridge = netdev->opts->bridge;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
@@ -728,7 +728,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
const char *vhostfdname;
char ifname[128];
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
tap = netdev->opts->tap;
queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 20981a9..8597ec4 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -229,7 +229,7 @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+ assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
vhost_user_opts = netdev->opts->vhost_user;
chr = net_vhost_parse_chardev(vhost_user_opts, errp);
diff --git a/numa.c b/numa.c
index 402804b..aa9e0f7 100644
--- a/numa.c
+++ b/numa.c
@@ -226,7 +226,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
goto error;
}
- switch (object->kind) {
+ switch (object->type) {
case NUMA_OPTIONS_KIND_NODE:
numa_node_parse(object->node, opts, &err);
if (err) {
@@ -487,7 +487,7 @@ static void numa_stat_memory_devices(uint64_t node_mem[])
MemoryDeviceInfo *value = info->value;
if (value) {
- switch (value->kind) {
+ switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
node_mem[value->dimm->node] += value->dimm->size;
break;
diff --git a/qemu-char.c b/qemu-char.c
index d956f8d..20fc51f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -123,7 +123,7 @@ static int SocketAddress_to_str(char *dest, int max_len,
const char *prefix, SocketAddress *addr,
bool is_listen, bool is_telnet)
{
- switch (addr->kind) {
+ switch (addr->type) {
case SOCKET_ADDRESS_KIND_INET:
return snprintf(dest, max_len, "%s%s:%s:%s%s", prefix,
is_telnet ? "telnet" : "tcp", addr->inet->host,
@@ -3570,11 +3570,11 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
addr = g_new0(SocketAddress, 1);
if (path) {
- addr->kind = SOCKET_ADDRESS_KIND_UNIX;
+ addr->type = SOCKET_ADDRESS_KIND_UNIX;
addr->q_unix = g_new0(UnixSocketAddress, 1);
addr->q_unix->path = g_strdup(path);
} else {
- addr->kind = SOCKET_ADDRESS_KIND_INET;
+ addr->type = SOCKET_ADDRESS_KIND_INET;
addr->inet = g_new0(InetSocketAddress, 1);
addr->inet->host = g_strdup(host);
addr->inet->port = g_strdup(port);
@@ -3619,7 +3619,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
backend->udp = g_new0(ChardevUdp, 1);
addr = g_new0(SocketAddress, 1);
- addr->kind = SOCKET_ADDRESS_KIND_INET;
+ addr->type = SOCKET_ADDRESS_KIND_INET;
addr->inet = g_new0(InetSocketAddress, 1);
addr->inet->host = g_strdup(host);
addr->inet->port = g_strdup(port);
@@ -3632,7 +3632,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
if (has_local) {
backend->udp->has_local = true;
addr = g_new0(SocketAddress, 1);
- addr->kind = SOCKET_ADDRESS_KIND_INET;
+ addr->type = SOCKET_ADDRESS_KIND_INET;
addr->inet = g_new0(InetSocketAddress, 1);
addr->inet->host = g_strdup(localaddr);
addr->inet->port = g_strdup(localport);
@@ -3704,7 +3704,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
}
chr = NULL;
- backend->kind = cd->kind;
+ backend->type = cd->kind;
if (cd->parse) {
cd->parse(opts, backend, &local_err);
if (local_err) {
@@ -3722,7 +3722,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
qapi_free_ChardevReturn(ret);
backend = g_new0(ChardevBackend, 1);
backend->mux = g_new0(ChardevMux, 1);
- backend->kind = CHARDEV_BACKEND_KIND_MUX;
+ backend->type = CHARDEV_BACKEND_KIND_MUX;
backend->mux->chardev = g_strdup(bid);
ret = qmp_chardev_add(id, backend, errp);
if (!ret) {
@@ -4151,7 +4151,7 @@ static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
s->fd = -1;
s->listen_fd = -1;
- s->is_unix = addr->kind == SOCKET_ADDRESS_KIND_UNIX;
+ s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX;
s->is_listen = is_listen;
s->is_telnet = is_telnet;
s->do_nodelay = do_nodelay;
@@ -4225,7 +4225,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
return NULL;
}
- switch (backend->kind) {
+ switch (backend->type) {
case CHARDEV_BACKEND_KIND_FILE:
chr = qmp_chardev_open_file(backend->file, errp);
break;
@@ -4296,7 +4296,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
chr = qemu_chr_open_ringbuf(backend->ringbuf, errp);
break;
default:
- error_setg(errp, "unknown chardev backend (%d)", backend->kind);
+ error_setg(errp, "unknown chardev backend (%d)", backend->type);
break;
}
@@ -4312,9 +4312,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
if (chr) {
chr->label = g_strdup(id);
chr->avail_connections =
- (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
+ (backend->type == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
if (!chr->filename) {
- chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
+ chr->filename = g_strdup(ChardevBackendKind_lookup[backend->type]);
}
if (!chr->explicit_be_open) {
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 6c9fecd..99bf00a 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -136,7 +136,7 @@ struct %(c_name)s {
''')
else:
ret += mcgen('''
- %(c_type)s kind;
+ %(c_type)s type;
''',
c_type=c_name(variants.tag_member.type.name))
@@ -152,10 +152,7 @@ struct %(c_name)s {
union { /* union tag is @%(c_name)s */
void *data;
''',
- # TODO ugly special case for simple union
- # Use same tag name in C as on the wire to get rid of
- # it, then: c_name=c_name(variants.tag_member.name)
- c_name=c_name(variants.tag_name or 'kind'))
+ c_name=c_name(variants.tag_member.name))
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index d776948..59b46e9 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -207,11 +207,11 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if (err) {
goto out;
}
- visit_get_next_type(m, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err);
+ visit_get_next_type(m, (int*) &(*obj)->type, %(c_name)s_qtypes, name, &err);
if (err) {
goto out_end;
}
- switch ((*obj)->kind) {
+ switch ((*obj)->type) {
''',
c_name=c_name(name))
@@ -278,9 +278,6 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
c_name=c_name(name))
tag_key = variants.tag_member.name
- if not variants.tag_name:
- # we pointlessly use a different key for simple unions
- tag_key = 'type'
ret += mcgen('''
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
if (err) {
@@ -292,11 +289,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
switch ((*obj)->%(c_name)s) {
''',
c_type=variants.tag_member.type.c_name(),
- # TODO ugly special case for simple union
- # Use same tag name in C as on the wire to get rid of
- # it, then: c_name=c_name(variants.tag_member.name)
- c_name=c_name(variants.tag_name or 'kind'),
- name=tag_key)
+ c_name=c_name(tag_key), name=tag_key)
for var in variants.variants:
# TODO ugly special case for simple union
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 8d5249e..6a67e73 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -64,7 +64,7 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
{
__org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
- ret->kind = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
+ ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
ret->__org_qemu_x_branch = strdup("blah1");
return ret;
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 61715b3..da84993 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -374,7 +374,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
visit_type_UserDefAlternate(v, &tmp, NULL, &err);
g_assert(err == NULL);
- g_assert_cmpint(tmp->kind, ==, USER_DEF_ALTERNATE_KIND_I);
+ g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I);
g_assert_cmpint(tmp->i, ==, 42);
qapi_free_UserDefAlternate(tmp);
}
@@ -404,7 +404,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
g_assert(err == NULL);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, kind);
+ g_assert_cmpint(cvalue->type, ==, kind);
switch (kind) {
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
@@ -567,7 +567,7 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
g_assert(err == NULL);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
@@ -602,7 +602,7 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
g_assert(err == NULL);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) {
gchar str[8];
@@ -641,7 +641,7 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
g_assert(err == NULL);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) {
GString *double_expected = g_string_new("");
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index 1a28dc2..2162a4a 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -517,7 +517,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
Error *err = NULL;
UserDefAlternate *tmp = g_malloc0(sizeof(UserDefAlternate));
- tmp->kind = USER_DEF_ALTERNATE_KIND_I;
+ tmp->type = USER_DEF_ALTERNATE_KIND_I;
tmp->i = 42;
visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err);
@@ -542,7 +542,7 @@ static void test_visitor_out_empty(TestOutputVisitorData *data,
static void init_native_list(UserDefNativeListUnion *cvalue)
{
int i;
- switch (cvalue->kind) {
+ switch (cvalue->type) {
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
intList **list = &cvalue->integer;
for (i = 0; i < 32; i++) {
@@ -763,14 +763,14 @@ static void test_native_list(TestOutputVisitorData *data,
Error *err = NULL;
QObject *obj;
- cvalue->kind = kind;
+ cvalue->type = kind;
init_native_list(cvalue);
visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
g_assert(err == NULL);
obj = qmp_output_get_qobject(data->qov);
- check_native_list(obj, cvalue->kind);
+ check_native_list(obj, cvalue->type);
qapi_free_UserDefNativeListUnion(cvalue);
qobject_decref(obj);
}
diff --git a/tpm.c b/tpm.c
index 4e9b109..fcab81c 100644
--- a/tpm.c
+++ b/tpm.c
@@ -260,7 +260,7 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
switch (drv->ops->type) {
case TPM_TYPE_PASSTHROUGH:
- res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
+ res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
tpo = g_new0(TPMPassthroughOptions, 1);
res->options->passthrough = tpo;
if (drv->path) {
diff --git a/ui/input-keymap.c b/ui/input-keymap.c
index 7635cb0..088523d 100644
--- a/ui/input-keymap.c
+++ b/ui/input-keymap.c
@@ -139,10 +139,10 @@ static int number_to_qcode[0x100];
int qemu_input_key_value_to_number(const KeyValue *value)
{
- if (value->kind == KEY_VALUE_KIND_QCODE) {
+ if (value->type == KEY_VALUE_KIND_QCODE) {
return qcode_to_number[value->qcode];
} else {
- assert(value->kind == KEY_VALUE_KIND_NUMBER);
+ assert(value->type == KEY_VALUE_KIND_NUMBER);
return value->number;
}
}
@@ -166,10 +166,10 @@ int qemu_input_key_number_to_qcode(uint8_t nr)
int qemu_input_key_value_to_qcode(const KeyValue *value)
{
- if (value->kind == KEY_VALUE_KIND_QCODE) {
+ if (value->type == KEY_VALUE_KIND_QCODE) {
return value->qcode;
} else {
- assert(value->kind == KEY_VALUE_KIND_NUMBER);
+ assert(value->type == KEY_VALUE_KIND_NUMBER);
return qemu_input_key_number_to_qcode(value->number);
}
}
@@ -180,7 +180,7 @@ int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
int keycode = qemu_input_key_value_to_number(value);
int count = 0;
- if (value->kind == KEY_VALUE_KIND_QCODE &&
+ if (value->type == KEY_VALUE_KIND_QCODE &&
value->qcode == Q_KEY_CODE_PAUSE) {
/* specific case */
int v = down ? 0 : 0x80;
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index e50f296..6149648 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -150,7 +150,7 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
};
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
- switch (evt->kind) {
+ switch (evt->type) {
case INPUT_EVENT_KIND_BTN:
if (evt->btn->down) {
s->buttons |= bmap[evt->btn->button];
diff --git a/ui/input.c b/ui/input.c
index 1a552d1..fd86571 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -147,10 +147,10 @@ void qmp_x_input_send_event(bool has_console, int64_t console,
for (e = events; e != NULL; e = e->next) {
InputEvent *event = e->value;
- if (!qemu_input_find_handler(1 << event->kind, con)) {
+ if (!qemu_input_find_handler(1 << event->type, con)) {
error_setg(errp, "Input handler not found for "
"event type %s",
- InputEventKind_lookup[event->kind]);
+ InputEventKind_lookup[event->type]);
return;
}
}
@@ -197,9 +197,9 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
if (src) {
idx = qemu_console_get_index(src);
}
- switch (evt->kind) {
+ switch (evt->type) {
case INPUT_EVENT_KIND_KEY:
- switch (evt->key->key->kind) {
+ switch (evt->key->key->type) {
case KEY_VALUE_KIND_NUMBER:
qcode = qemu_input_key_number_to_qcode(evt->key->key->number);
name = QKeyCode_lookup[qcode];
@@ -311,12 +311,12 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
qemu_input_event_trace(src, evt);
/* pre processing */
- if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) {
+ if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) {
qemu_input_transform_abs_rotate(evt);
}
/* send event */
- s = qemu_input_find_handler(1 << evt->kind, src);
+ s = qemu_input_find_handler(1 << evt->type, src);
if (!s) {
return;
}
@@ -349,7 +349,7 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool down)
{
InputEvent *evt = g_new0(InputEvent, 1);
evt->key = g_new0(InputKeyEvent, 1);
- evt->kind = INPUT_EVENT_KIND_KEY;
+ evt->type = INPUT_EVENT_KIND_KEY;
evt->key->key = key;
evt->key->down = down;
return evt;
@@ -372,7 +372,7 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
{
KeyValue *key = g_new0(KeyValue, 1);
- key->kind = KEY_VALUE_KIND_NUMBER;
+ key->type = KEY_VALUE_KIND_NUMBER;
key->number = num;
qemu_input_event_send_key(src, key, down);
}
@@ -380,7 +380,7 @@ void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
{
KeyValue *key = g_new0(KeyValue, 1);
- key->kind = KEY_VALUE_KIND_QCODE;
+ key->type = KEY_VALUE_KIND_QCODE;
key->qcode = q;
qemu_input_event_send_key(src, key, down);
}
@@ -399,7 +399,7 @@ InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
{
InputEvent *evt = g_new0(InputEvent, 1);
evt->btn = g_new0(InputBtnEvent, 1);
- evt->kind = INPUT_EVENT_KIND_BTN;
+ evt->type = INPUT_EVENT_KIND_BTN;
evt->btn->button = btn;
evt->btn->down = down;
return evt;
@@ -451,7 +451,7 @@ InputEvent *qemu_input_event_new_move(InputEventKind kind,
InputEvent *evt = g_new0(InputEvent, 1);
InputMoveEvent *move = g_new0(InputMoveEvent, 1);
- evt->kind = kind;
+ evt->type = kind;
evt->data = move;
move->axis = axis;
move->value = value;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 2add83a..277b139 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -904,7 +904,7 @@ SocketAddress *socket_parse(const char *str, Error **errp)
error_setg(errp, "invalid Unix socket address");
goto fail;
} else {
- addr->kind = SOCKET_ADDRESS_KIND_UNIX;
+ addr->type = SOCKET_ADDRESS_KIND_UNIX;
addr->q_unix = g_new(UnixSocketAddress, 1);
addr->q_unix->path = g_strdup(str + 5);
}
@@ -913,12 +913,12 @@ SocketAddress *socket_parse(const char *str, Error **errp)
error_setg(errp, "invalid file descriptor address");
goto fail;
} else {
- addr->kind = SOCKET_ADDRESS_KIND_FD;
+ addr->type = SOCKET_ADDRESS_KIND_FD;
addr->fd = g_new(String, 1);
addr->fd->str = g_strdup(str + 3);
}
} else {
- addr->kind = SOCKET_ADDRESS_KIND_INET;
+ addr->type = SOCKET_ADDRESS_KIND_INET;
addr->inet = inet_parse(str, errp);
if (addr->inet == NULL) {
goto fail;
@@ -938,7 +938,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
int fd;
opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
- switch (addr->kind) {
+ switch (addr->type) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);
fd = inet_connect_opts(opts, errp, callback, opaque);
@@ -970,7 +970,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
int fd;
opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
- switch (addr->kind) {
+ switch (addr->type) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);
fd = inet_listen_opts(opts, 0, errp);
@@ -998,7 +998,7 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
int fd;
opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
- switch (remote->kind) {
+ switch (remote->type) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, remote->inet);
if (local) {
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 04/29] vnc: hoist allocation of VncBasicInfo to callers
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (2 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 03/29] qapi: use 'type' in generated C code to match QMP union wire form Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 05/29] qapi: Unbox base members Eric Blake
` (24 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, Gerd Hoffmann, armbru, DirtY.iCE.hu
A future qapi patch will rework generated structs with a base
class to be unboxed. In preparation for that, change the code
that allocates then populates an info struct to instead merely
populate the fields of an info field passed in as a parameter.
Add rudimentary Error handling for cases where the old code
returned NULL; but as before, callers merely ignore errors for
now.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
ui/vnc.c | 52 ++++++++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index caf82f5..84eab321 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -153,10 +153,11 @@ char *vnc_socket_remote_addr(const char *format, int fd) {
return addr_to_string(format, &sa, salen);
}
-static VncBasicInfo *vnc_basic_info_get(struct sockaddr_storage *sa,
- socklen_t salen)
+static void vnc_basic_info_get(struct sockaddr_storage *sa,
+ socklen_t salen,
+ VncBasicInfo *info,
+ Error **errp)
{
- VncBasicInfo *info;
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
int err;
@@ -165,42 +166,44 @@ static VncBasicInfo *vnc_basic_info_get(struct sockaddr_storage *sa,
host, sizeof(host),
serv, sizeof(serv),
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
- VNC_DEBUG("Cannot resolve address %d: %s\n",
- err, gai_strerror(err));
- return NULL;
+ error_setg(errp, "Cannot resolve address %d: %s",
+ err, gai_strerror(err));
+ return;
}
- info = g_malloc0(sizeof(VncBasicInfo));
info->host = g_strdup(host);
info->service = g_strdup(serv);
info->family = inet_netfamily(sa->ss_family);
- return info;
}
-static VncBasicInfo *vnc_basic_info_get_from_server_addr(int fd)
+static void vnc_basic_info_get_from_server_addr(int fd, VncBasicInfo *info,
+ Error **errp)
{
struct sockaddr_storage sa;
socklen_t salen;
salen = sizeof(sa);
if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
- return NULL;
+ error_setg_errno(errp, errno, "getsockname failed");
+ return;
}
- return vnc_basic_info_get(&sa, salen);
+ vnc_basic_info_get(&sa, salen, info, errp);
}
-static VncBasicInfo *vnc_basic_info_get_from_remote_addr(int fd)
+static void vnc_basic_info_get_from_remote_addr(int fd, VncBasicInfo *info,
+ Error **errp)
{
struct sockaddr_storage sa;
socklen_t salen;
salen = sizeof(sa);
if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
- return NULL;
+ error_setg_errno(errp, errno, "getpeername failed");
+ return;
}
- return vnc_basic_info_get(&sa, salen);
+ vnc_basic_info_get(&sa, salen, info, errp);
}
static const char *vnc_auth_name(VncDisplay *vd) {
@@ -257,13 +260,10 @@ static const char *vnc_auth_name(VncDisplay *vd) {
static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
{
VncServerInfo *info;
- VncBasicInfo *bi = vnc_basic_info_get_from_server_addr(vd->lsock);
- if (!bi) {
- return NULL;
- }
info = g_malloc(sizeof(*info));
- info->base = bi;
+ info->base = g_malloc(sizeof(*info->base));
+ vnc_basic_info_get_from_server_addr(vd->lsock, info->base, NULL);
info->has_auth = true;
info->auth = g_strdup(vnc_auth_name(vd));
return info;
@@ -293,11 +293,15 @@ static void vnc_client_cache_auth(VncState *client)
static void vnc_client_cache_addr(VncState *client)
{
- VncBasicInfo *bi = vnc_basic_info_get_from_remote_addr(client->csock);
-
- if (bi) {
- client->info = g_malloc0(sizeof(*client->info));
- client->info->base = bi;
+ Error *err = NULL;
+ client->info = g_malloc0(sizeof(*client->info));
+ client->info->base = g_malloc0(sizeof(*client->info->base));
+ vnc_basic_info_get_from_remote_addr(client->csock, client->info->base,
+ &err);
+ if (err) {
+ qapi_free_VncClientInfo(client->info);
+ client->info = NULL;
+ error_free(err);
}
}
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 05/29] qapi: Unbox base members
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (3 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 04/29] vnc: hoist allocation of VncBasicInfo to callers Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 06/29] qapi-visit: Remove redundant functions for flat union base Eric Blake
` (23 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: armbru, Michael Roth, Luiz Capitulino, Gerd Hoffmann,
DirtY.iCE.hu, marcandre.lureau
Rather than storing a base class as a pointer to a box, just
store the fields of that base class in the same order, so that
a child struct can be safely cast to its parent. This gives
less malloc overhead, less pointer dereferencing, and even less
generated code.
Without boxing, the corner case of one empty struct having
another empty struct as its base type now requires inserting a
dummy member (previously, the pointer to the base would have
sufficed).
Compare to the earlier commit 1e6c1616a "qapi: Generate a nicer
struct for flat unions".
Signed-off-by: Eric Blake <eblake@redhat.com>
---
hmp.c | 6 +++---
scripts/qapi-types.py | 29 +++++++++++++++--------------
scripts/qapi-visit.py | 9 ++++++---
tests/test-qmp-commands.c | 15 +++++----------
tests/test-qmp-event.c | 8 ++------
tests/test-qmp-input-visitor.c | 4 ++--
tests/test-qmp-output-visitor.c | 12 ++++--------
tests/test-visitor-serialization.c | 14 ++++++--------
ui/spice-core.c | 23 +++++++++++++----------
ui/vnc.c | 20 +++++++++-----------
10 files changed, 65 insertions(+), 75 deletions(-)
diff --git a/hmp.c b/hmp.c
index 849b292..ab8e700 100644
--- a/hmp.c
+++ b/hmp.c
@@ -558,8 +558,8 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
for (client = info->clients; client; client = client->next) {
monitor_printf(mon, "Client:\n");
monitor_printf(mon, " address: %s:%s\n",
- client->value->base->host,
- client->value->base->service);
+ client->value->host,
+ client->value->service);
monitor_printf(mon, " x509_dname: %s\n",
client->value->x509_dname ?
client->value->x509_dname : "none");
@@ -627,7 +627,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
for (chan = info->channels; chan; chan = chan->next) {
monitor_printf(mon, "Channel:\n");
monitor_printf(mon, " address: %s:%s%s\n",
- chan->value->base->host, chan->value->base->port,
+ chan->value->host, chan->value->port,
chan->value->tls ? " [tls]" : "");
monitor_printf(mon, " session: %" PRId64 "\n",
chan->value->connection_id);
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 99bf00a..457f6a7 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -51,8 +51,19 @@ def gen_struct_field(name, typ, optional):
return ret
-def gen_struct_fields(members):
+def gen_struct_fields(members, base, nested=False):
ret = ''
+ if base:
+ if not nested:
+ ret += mcgen('''
+ /* Members inherited from %(c_name)s: */
+''',
+ c_name=base.c_name())
+ ret += gen_struct_fields(base.local_members, base.base, True)
+ if not nested:
+ ret += mcgen('''
+ /* Own members: */
+''')
for memb in members:
ret += gen_struct_field(memb.name, memb.type, memb.optional)
@@ -66,16 +77,13 @@ struct %(c_name)s {
''',
c_name=c_name(name))
- if base:
- ret += gen_struct_field('base', base, False)
-
- ret += gen_struct_fields(members)
+ ret += gen_struct_fields(members, base)
# Make sure that all structs have at least one field; this avoids
# 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 not members:
+ if not (base and base.members) and not members:
ret += mcgen('''
char qapi_dummy_field_for_empty_struct;
''')
@@ -126,14 +134,7 @@ struct %(c_name)s {
''',
c_name=c_name(name))
if base:
- ret += mcgen('''
- /* Members inherited from %(c_name)s: */
-''',
- c_name=c_name(base.name))
- ret += gen_struct_fields(base.members)
- ret += mcgen('''
- /* Own members: */
-''')
+ ret += gen_struct_fields([], base)
else:
ret += mcgen('''
%(c_type)s type;
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 59b46e9..f5dc257 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -62,12 +62,15 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
def gen_visit_struct_fields(name, base, members):
+ if name in struct_fields_seen:
+ return ''
struct_fields_seen.add(name)
ret = ''
if base:
- ret += gen_visit_implicit_struct(base)
+ ret += gen_visit_struct_fields(base.name, base.base,
+ base.local_members)
ret += mcgen('''
@@ -81,12 +84,12 @@ static void visit_type_%(c_name)s_fields(Visitor *m, %(c_name)s **obj, Error **e
if base:
ret += mcgen('''
-visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);
+visit_type_%(c_type)s_fields(m, (%(c_type)s **)obj, &err);
if (err) {
goto out;
}
''',
- c_type=base.c_name(), c_name=c_name('base'))
+ c_type=base.c_name())
for memb in members:
if memb.optional:
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 6a67e73..5181823 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -25,11 +25,9 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
ud1c->string = strdup(ud1a->string);
- ud1c->base = g_new0(UserDefZero, 1);
- ud1c->base->integer = ud1a->base->integer;
+ ud1c->integer = ud1a->integer;
ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
- ud1d->base = g_new0(UserDefZero, 1);
- ud1d->base->integer = has_udb1 ? ud1b->base->integer : 0;
+ ud1d->integer = has_udb1 ? ud1b->integer : 0;
ret = g_new0(UserDefTwo, 1);
ret->string0 = strdup("blah1");
@@ -176,20 +174,17 @@ static void test_dealloc_types(void)
UserDefOneList *ud1list;
ud1test = g_malloc0(sizeof(UserDefOne));
- ud1test->base = g_new0(UserDefZero, 1);
- ud1test->base->integer = 42;
+ ud1test->integer = 42;
ud1test->string = g_strdup("hi there 42");
qapi_free_UserDefOne(ud1test);
ud1a = g_malloc0(sizeof(UserDefOne));
- ud1a->base = g_new0(UserDefZero, 1);
- ud1a->base->integer = 43;
+ ud1a->integer = 43;
ud1a->string = g_strdup("hi there 43");
ud1b = g_malloc0(sizeof(UserDefOne));
- ud1b->base = g_new0(UserDefZero, 1);
- ud1b->base->integer = 44;
+ ud1b->integer = 44;
ud1b->string = g_strdup("hi there 44");
ud1list = g_malloc0(sizeof(UserDefOneList));
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 28f146d..035c65c 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -179,9 +179,7 @@ static void test_event_c(TestEventData *data,
QDict *d, *d_data, *d_b;
UserDefOne b;
- UserDefZero z;
- z.integer = 2;
- b.base = &z;
+ b.integer = 2;
b.string = g_strdup("test1");
b.has_enum1 = false;
@@ -209,11 +207,9 @@ static void test_event_d(TestEventData *data,
{
UserDefOne struct1;
EventStructOne a;
- UserDefZero z;
QDict *d, *d_data, *d_a, *d_struct1;
- z.integer = 2;
- struct1.base = &z;
+ struct1.integer = 2;
struct1.string = g_strdup("test1");
struct1.has_enum1 = true;
struct1.enum1 = ENUM_ONE_VALUE1;
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index da84993..b6deee3 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -262,7 +262,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
check_and_free_str(udp->string0, "string0");
check_and_free_str(udp->dict1->string1, "string1");
- g_assert_cmpint(udp->dict1->dict2->userdef->base->integer, ==, 42);
+ g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
check_and_free_str(udp->dict1->dict2->userdef->string, "string");
check_and_free_str(udp->dict1->dict2->string, "string2");
g_assert(udp->dict1->has_dict3 == false);
@@ -292,7 +292,7 @@ static void test_visitor_in_list(TestInputVisitorData *data,
snprintf(string, sizeof(string), "string%d", i);
g_assert_cmpstr(item->value->string, ==, string);
- g_assert_cmpint(item->value->base->integer, ==, 42 + i);
+ g_assert_cmpint(item->value->integer, ==, 42 + i);
}
qapi_free_UserDefOneList(head);
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index 2162a4a..ab4bc5d 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -250,16 +250,14 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2));
ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1);
ud2->dict1->dict2->userdef->string = g_strdup(string);
- ud2->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- ud2->dict1->dict2->userdef->base->integer = value;
+ ud2->dict1->dict2->userdef->integer = value;
ud2->dict1->dict2->string = g_strdup(strings[2]);
ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3));
ud2->dict1->has_dict3 = true;
ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1);
ud2->dict1->dict3->userdef->string = g_strdup(string);
- ud2->dict1->dict3->userdef->base = g_new0(UserDefZero, 1);
- ud2->dict1->dict3->userdef->base->integer = value;
+ ud2->dict1->dict3->userdef->integer = value;
ud2->dict1->dict3->string = g_strdup(strings[3]);
visit_type_UserDefTwo(data->ov, &ud2, "unused", &err);
@@ -301,8 +299,7 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
const void *unused)
{
EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
- UserDefZero b;
- UserDefOne u = { .base = &b }, *pu = &u;
+ UserDefOne u, *pu = &u;
Error *err;
int i;
@@ -416,8 +413,7 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
p->value->dict1->dict2->userdef->string = g_strdup(string);
- p->value->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- p->value->dict1->dict2->userdef->base->integer = 42;
+ p->value->dict1->dict2->userdef->integer = 42;
p->value->dict1->dict2->string = g_strdup(string);
p->value->dict1->has_dict3 = false;
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index fa86cae..634563b 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -258,15 +258,13 @@ static UserDefTwo *nested_struct_create(void)
udnp->dict1->string1 = strdup("test_string1");
udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
- udnp->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- udnp->dict1->dict2->userdef->base->integer = 42;
+ udnp->dict1->dict2->userdef->integer = 42;
udnp->dict1->dict2->userdef->string = strdup("test_string");
udnp->dict1->dict2->string = strdup("test_string2");
udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
udnp->dict1->has_dict3 = true;
udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
- udnp->dict1->dict3->userdef->base = g_new0(UserDefZero, 1);
- udnp->dict1->dict3->userdef->base->integer = 43;
+ udnp->dict1->dict3->userdef->integer = 43;
udnp->dict1->dict3->userdef->string = strdup("test_string");
udnp->dict1->dict3->string = strdup("test_string3");
return udnp;
@@ -278,15 +276,15 @@ static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
g_assert(udnp2);
g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
- g_assert_cmpint(udnp1->dict1->dict2->userdef->base->integer, ==,
- udnp2->dict1->dict2->userdef->base->integer);
+ g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
+ udnp2->dict1->dict2->userdef->integer);
g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
udnp2->dict1->dict2->userdef->string);
g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
udnp2->dict1->dict2->string);
g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3);
- g_assert_cmpint(udnp1->dict1->dict3->userdef->base->integer, ==,
- udnp2->dict1->dict3->userdef->base->integer);
+ g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
+ udnp2->dict1->dict3->userdef->integer);
g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
udnp2->dict1->dict3->userdef->string);
g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
diff --git a/ui/spice-core.c b/ui/spice-core.c
index bf4fd07..86f4441 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -200,8 +200,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
{
SpiceServerInfo *server = g_malloc0(sizeof(*server));
SpiceChannel *client = g_malloc0(sizeof(*client));
- server->base = g_malloc0(sizeof(*server->base));
- client->base = g_malloc0(sizeof(*client->base));
/*
* Spice server might have called us from spice worker thread
@@ -218,9 +216,11 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
}
if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
- add_addr_info(client->base, (struct sockaddr *)&info->paddr_ext,
+ add_addr_info((SpiceBasicInfo *)client,
+ (struct sockaddr *)&info->paddr_ext,
info->plen_ext);
- add_addr_info(server->base, (struct sockaddr *)&info->laddr_ext,
+ add_addr_info((SpiceBasicInfo *)server,
+ (struct sockaddr *)&info->laddr_ext,
info->llen_ext);
} else {
error_report("spice: %s, extended address is expected",
@@ -229,7 +229,9 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
switch (event) {
case SPICE_CHANNEL_EVENT_CONNECTED:
- qapi_event_send_spice_connected(server->base, client->base, &error_abort);
+ qapi_event_send_spice_connected((SpiceBasicInfo *)server,
+ (SpiceBasicInfo *)client,
+ &error_abort);
break;
case SPICE_CHANNEL_EVENT_INITIALIZED:
if (auth) {
@@ -242,7 +244,9 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
break;
case SPICE_CHANNEL_EVENT_DISCONNECTED:
channel_list_del(info);
- qapi_event_send_spice_disconnected(server->base, client->base, &error_abort);
+ qapi_event_send_spice_disconnected((SpiceBasicInfo *)server,
+ (SpiceBasicInfo *)client,
+ &error_abort);
break;
default:
break;
@@ -378,16 +382,15 @@ static SpiceChannelList *qmp_query_spice_channels(void)
chan = g_malloc0(sizeof(*chan));
chan->value = g_malloc0(sizeof(*chan->value));
- chan->value->base = g_malloc0(sizeof(*chan->value->base));
paddr = (struct sockaddr *)&item->info->paddr_ext;
plen = item->info->plen_ext;
getnameinfo(paddr, plen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST | NI_NUMERICSERV);
- chan->value->base->host = g_strdup(host);
- chan->value->base->port = g_strdup(port);
- chan->value->base->family = inet_netfamily(paddr->sa_family);
+ chan->value->host = g_strdup(host);
+ chan->value->port = g_strdup(port);
+ chan->value->family = inet_netfamily(paddr->sa_family);
chan->value->connection_id = item->info->connection_id;
chan->value->channel_type = item->info->type;
diff --git a/ui/vnc.c b/ui/vnc.c
index 84eab321..45c6ad1 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -262,8 +262,7 @@ static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
VncServerInfo *info;
info = g_malloc(sizeof(*info));
- info->base = g_malloc(sizeof(*info->base));
- vnc_basic_info_get_from_server_addr(vd->lsock, info->base, NULL);
+ vnc_basic_info_get_from_server_addr(vd->lsock, (VncBasicInfo *)info, NULL);
info->has_auth = true;
info->auth = g_strdup(vnc_auth_name(vd));
return info;
@@ -295,8 +294,8 @@ static void vnc_client_cache_addr(VncState *client)
{
Error *err = NULL;
client->info = g_malloc0(sizeof(*client->info));
- client->info->base = g_malloc0(sizeof(*client->info->base));
- vnc_basic_info_get_from_remote_addr(client->csock, client->info->base,
+ vnc_basic_info_get_from_remote_addr(client->csock,
+ (VncBasicInfo *)client->info,
&err);
if (err) {
qapi_free_VncClientInfo(client->info);
@@ -312,7 +311,6 @@ static void vnc_qmp_event(VncState *vs, QAPIEvent event)
if (!vs->info) {
return;
}
- g_assert(vs->info->base);
si = vnc_server_info_get(vs->vd);
if (!si) {
@@ -321,7 +319,8 @@ static void vnc_qmp_event(VncState *vs, QAPIEvent event)
switch (event) {
case QAPI_EVENT_VNC_CONNECTED:
- qapi_event_send_vnc_connected(si, vs->info->base, &error_abort);
+ qapi_event_send_vnc_connected(si, (VncBasicInfo *)vs->info,
+ &error_abort);
break;
case QAPI_EVENT_VNC_INITIALIZED:
qapi_event_send_vnc_initialized(si, vs->info, &error_abort);
@@ -356,11 +355,10 @@ static VncClientInfo *qmp_query_vnc_client(const VncState *client)
}
info = g_malloc0(sizeof(*info));
- info->base = g_malloc0(sizeof(*info->base));
- info->base->host = g_strdup(host);
- info->base->service = g_strdup(serv);
- info->base->family = inet_netfamily(sa.ss_family);
- info->base->websocket = client->websocket;
+ info->host = g_strdup(host);
+ info->service = g_strdup(serv);
+ info->family = inet_netfamily(sa.ss_family);
+ info->websocket = client->websocket;
#ifdef CONFIG_VNC_TLS
if (client->tls.session && client->tls.dname) {
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 06/29] qapi-visit: Remove redundant functions for flat union base
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (4 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 05/29] qapi: Unbox base members Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 07/29] qapi: Test use of 'number' within alternates Eric Blake
` (22 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
The code for visiting the base class of a child struct created
visit_type_Base_fields(); the code for visiting the base class
of a flat union created visit_type_Union_fields(). If the same
type is shared between a struct and a union, the two functions
differed only by whether they visited the discriminator used by
the union. But if the base class always visits all its fields,
then we don't need to revisit the discriminator specially for
a union. By consistently visiting the base class fields under
the name of the base class, we can eliminate some redundant
code.
Now that gen_visit_struct_fields() can potentially collect more
than one function into 'ret', a regular expression searching for
whether a label was used may hit a false positive within the
body of the first function. But using a regex was overkill,
since we can easily determine when we jumped to a label.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-visit.py | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index f5dc257..c3e4c49 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -118,7 +118,7 @@ if (err) {
''')
pop_indent()
- if re.search('^ *goto out;', ret, re.MULTILINE):
+ if base or members:
ret += mcgen('''
out:
@@ -249,8 +249,8 @@ def gen_visit_union(name, base, variants):
ret = ''
if base:
- members = [m for m in base.members if m != variants.tag_member]
- ret += gen_visit_struct_fields(name, None, members)
+ ret += gen_visit_struct_fields(base.name, base.base,
+ base.local_members)
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
@@ -271,18 +271,19 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
''',
c_name=c_name(name), name=name)
- if base:
- ret += mcgen('''
- visit_type_%(c_name)s_fields(m, obj, &err);
- if (err) {
- goto out_obj;
- }
-''',
- c_name=c_name(name))
-
tag_key = variants.tag_member.name
- ret += mcgen('''
+ if base:
+ ret += mcgen('''
+ visit_type_%(c_name)s_fields(m, (%(c_name)s **)obj, &err);
+''',
+ c_name=c_name(base.name))
+ else:
+ ret += mcgen('''
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
+''',
+ c_type=variants.tag_member.type.c_name(),
+ c_name=c_name(tag_key), name=tag_key)
+ ret += mcgen('''
if (err) {
goto out_obj;
}
@@ -291,8 +292,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
}
switch ((*obj)->%(c_name)s) {
''',
- c_type=variants.tag_member.type.c_name(),
- c_name=c_name(tag_key), name=tag_key)
+ c_name=c_name(tag_key))
for var in variants.variants:
# TODO ugly special case for simple union
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 07/29] qapi: Test use of 'number' within alternates
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (5 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 06/29] qapi-visit: Remove redundant functions for flat union base Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 08/29] qapi: Simplify visiting of alternate types Eric Blake
` (21 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Add some testsuite exposure for use of a 'number' as part of
an alternate. The current state of the tree has a few bugs
exposed by this: our input parser depends on the ordering of
how the qapi schema declared the alternate, and the parser
does not accept integers for a 'number' in an alternate even
though it does for numbers outside of an alternate.
Mixing 'int' and 'number' in the same alternate is unusual,
since both are supplied by json-numbers, but there does not
seem to be a technical reason to forbid it given that our
json lexer distinguishes between json-numbers that can be
represented as an int vs. those that cannot.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
tests/qapi-schema/qapi-schema-test.json | 8 ++
tests/qapi-schema/qapi-schema-test.out | 24 ++++++
tests/test-qmp-input-visitor.c | 129 +++++++++++++++++++++++++++++++-
3 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index e855018..14016ab 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -59,6 +59,14 @@
{ 'struct': 'UserDefC',
'data': { 'string1': 'str', 'string2': 'str' } }
+# for testing use of 'number' within alternates
+{ 'alternate': 'AltOne', 'data': { 's': 'str', 'b': 'bool' } }
+{ 'alternate': 'AltTwo', 'data': { 's': 'str', 'n': 'number' } }
+{ 'alternate': 'AltThree', 'data': { 'n': 'number', 's': 'str' } }
+{ 'alternate': 'AltFour', 'data': { 's': 'str', 'i': 'int' } }
+{ 'alternate': 'AltFive', 'data': { 'i': 'int', 'n': 'number' } }
+{ 'alternate': 'AltSix', 'data': { 'n': 'number', 'i': 'int' } }
+
# for testing native lists
{ 'union': 'UserDefNativeListUnion',
'data': { 'integer': ['int'],
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index a9c87a0..895fa94 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -53,6 +53,30 @@ object :obj-user_def_cmd2-arg
object :obj-user_def_cmd3-arg
member a: int optional=False
member b: int optional=True
+alternate AltFive
+ case i: int
+ case n: number
+enum AltFiveKind ['i', 'n']
+alternate AltFour
+ case s: str
+ case i: int
+enum AltFourKind ['s', 'i']
+alternate AltOne
+ case s: str
+ case b: bool
+enum AltOneKind ['s', 'b']
+alternate AltSix
+ case n: number
+ case i: int
+enum AltSixKind ['n', 'i']
+alternate AltThree
+ case n: number
+ case s: str
+enum AltThreeKind ['n', 's']
+alternate AltTwo
+ case s: str
+ case n: number
+enum AltTwoKind ['s', 'n']
event EVENT_A None
event EVENT_B None
event EVENT_C :obj-EVENT_C-arg
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index b6deee3..3ee1a1a 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -368,15 +368,136 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
{
Visitor *v;
Error *err = NULL;
- UserDefAlternate *tmp;
+ UserDefAlternate *tmp = NULL;
v = visitor_input_test_init(data, "42");
- visit_type_UserDefAlternate(v, &tmp, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I);
g_assert_cmpint(tmp->i, ==, 42);
qapi_free_UserDefAlternate(tmp);
+ tmp = NULL;
+
+ v = visitor_input_test_init(data, "'string'");
+
+ visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
+ g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S);
+ g_assert_cmpstr(tmp->s, ==, "string");
+ qapi_free_UserDefAlternate(tmp);
+ tmp = NULL;
+
+ v = visitor_input_test_init(data, "false");
+
+ visit_type_UserDefAlternate(v, &tmp, NULL, &err);
+ g_assert(err);
+ error_free(err);
+ err = NULL;
+ qapi_free_UserDefAlternate(tmp);
+}
+
+static void test_visitor_in_alternate_number(TestInputVisitorData *data,
+ const void *unused)
+{
+ Visitor *v;
+ Error *err = NULL;
+ AltOne *one = NULL;
+ AltTwo *two = NULL;
+ AltThree *three = NULL;
+ AltFour *four = NULL;
+ AltFive *five = NULL;
+ AltSix *six = NULL;
+
+ /* Parsing an int */
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltOne(v, &one, NULL, &err);
+ g_assert(err);
+ qapi_free_AltOne(one);
+ one = NULL;
+
+ /* FIXME: Integers should parse as numbers */
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltTwo(v, &two, NULL, &err);
+ g_assert(err);
+ error_free(err);
+ err = NULL;
+ qapi_free_AltTwo(two);
+ one = NULL;
+
+ /* FIXME: Order of alternate should not affect semantics */
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltThree(v, &three, NULL, &error_abort);
+ g_assert_cmpint(three->type, ==, ALT_THREE_KIND_N);
+ g_assert_cmpfloat(three->n, ==, 42);
+ qapi_free_AltThree(three);
+ one = NULL;
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltFour(v, &four, NULL, &error_abort);
+ g_assert_cmpint(four->type, ==, ALT_FOUR_KIND_I);
+ g_assert_cmpint(four->i, ==, 42);
+ qapi_free_AltFour(four);
+ one = NULL;
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltFive(v, &five, NULL, &error_abort);
+ g_assert_cmpint(five->type, ==, ALT_FIVE_KIND_I);
+ g_assert_cmpint(five->i, ==, 42);
+ qapi_free_AltFive(five);
+ one = NULL;
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltSix(v, &six, NULL, &error_abort);
+ g_assert_cmpint(six->type, ==, ALT_SIX_KIND_I);
+ g_assert_cmpint(six->i, ==, 42);
+ qapi_free_AltSix(six);
+ one = NULL;
+
+ /* Parsing a double */
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltOne(v, &one, NULL, &err);
+ g_assert(err);
+ error_free(err);
+ err = NULL;
+ qapi_free_AltOne(one);
+ one = NULL;
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltTwo(v, &two, NULL, &error_abort);
+ g_assert_cmpint(two->type, ==, ALT_TWO_KIND_N);
+ g_assert_cmpfloat(two->n, ==, 42.5);
+ qapi_free_AltTwo(two);
+ two = NULL;
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltThree(v, &three, NULL, &error_abort);
+ g_assert_cmpint(three->type, ==, ALT_THREE_KIND_N);
+ g_assert_cmpfloat(three->n, ==, 42.5);
+ qapi_free_AltThree(three);
+ three = NULL;
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltFour(v, &four, NULL, &err);
+ g_assert(err);
+ error_free(err);
+ err = NULL;
+ qapi_free_AltFour(four);
+ four = NULL;
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltFive(v, &five, NULL, &error_abort);
+ g_assert_cmpint(five->type, ==, ALT_FIVE_KIND_N);
+ g_assert_cmpfloat(five->n, ==, 42.5);
+ qapi_free_AltFive(five);
+ five = NULL;
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltSix(v, &six, NULL, &error_abort);
+ g_assert_cmpint(six->type, ==, ALT_SIX_KIND_N);
+ g_assert_cmpint(six->n, ==, 42.5);
+ qapi_free_AltSix(six);
+ six = NULL;
}
static void test_native_list_integer_helper(TestInputVisitorData *data,
@@ -720,6 +841,8 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_alternate);
input_visitor_test_add("/visitor/input/errors",
&in_visitor_data, test_visitor_in_errors);
+ input_visitor_test_add("/visitor/input/alternate-number",
+ &in_visitor_data, test_visitor_in_alternate_number);
input_visitor_test_add("/visitor/input/native_list/int",
&in_visitor_data,
test_visitor_in_native_list_int);
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 08/29] qapi: Simplify visiting of alternate types
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (6 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 07/29] qapi: Test use of 'number' within alternates Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 09/29] qapi: Hide tag_name data member of variants Eric Blake
` (20 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Previously, working with alternates required two enums, and
some indirection: for type Foo, we created Foo_qtypes[] which
maps each qtype to a member of FooKind_lookup[], then use
FooKind_lookup[] like we do for other union types.
This has a subtle bug: since the values of FooKind_lookup
start at zero, all entries of Foo_qtypes that were not
explicitly initialized map to the same branch of the union as
the first member of the alternate, rather than triggering a
failure in visit_get_next_type(). Fortunately, the bug
seldom bites; the very next thing the input visitor does is
try to parse the incoming JSON with the wrong parser, which
fails; the output visitor is not used with a C struct in that
state, and the dealloc visitor has nothing to clean up (so
there is no leak).
However, it IS observable in one case: the behavior of an
alternate that contains a 'number' member but no 'int' member
differs according to whether the 'number' was first in the
qapi definition, and when the input being parsed is an integer;
this is because the 'number' parser accepts QTYPE_QINT in
addition to the expected QTYPE_QFLOAT. A later patch will worry
about fixing alternates to parse all inputs that a non-alternate
'number' would accept.
This patch fixes the validation bug by deleting the indirection,
and modifying get_next_type() to directly return a qtype code.
There is no longer a need to generate an implicit FooKind array
associated with the alternate type (since the QMP wire format
never uses the stringized counterparts of the C union member
names). Next, the generated visitor is fixed to properly detect
unexpected qtypes in the switch statement. Things got a bit
tricky with validating QAPISchemaObjectTypeVariants, which now
has three different initialization paths; but I didn't think it
was confusing enough to need to create different sub-classes.
Callers now have to know the QTYPE_* mapping when looking at the
discriminator; but so far, only the testsuite was even using the
C struct of an alternate types. If that gets too confusing, we
could reintroduce FooKind, but initialize it differently than
most generated arrays, as in:
typedef enum FooKind {
FOO_KIND_A = QTYPE_QDICT,
FOO_KIND_B = QTYPE_QINT,
} FooKind;
to create nicer aliases for knowing when to use foo->a or foo->b
when inspecting foo->kind. But without a current client, I
didn't see the point of doing it now.
There is a user-visible side effect to this change, but I
consider it to be an improvement. Previously,
the invalid QMP command:
{"execute":"blockdev-add", "arguments":{"options":
{"driver":"raw", "id":"a", "file":true}}}
failed with:
{"error": {"class": "GenericError",
"desc": "Invalid parameter type for 'file', expected: QDict"}}
Now it fails with:
{"error": {"class": "GenericError",
"desc": "Invalid parameter type for 'file', expected: BlockdevRef"}}
Signed-off-by: Eric Blake <eblake@redhat.com>
---
docs/qapi-code-gen.txt | 3 ---
include/qapi/visitor-impl.h | 2 +-
include/qapi/visitor.h | 2 +-
qapi/qapi-visit-core.c | 4 ++--
qapi/qmp-input-visitor.c | 4 ++--
scripts/qapi-types.py | 44 +++++++---------------------------
scripts/qapi-visit.py | 12 ++++++----
scripts/qapi.py | 24 ++++++++++++-------
tests/qapi-schema/alternate-good.out | 1 -
tests/qapi-schema/qapi-schema-test.out | 8 -------
tests/test-qmp-input-visitor.c | 26 ++++++++++----------
tests/test-qmp-output-visitor.c | 21 ++++++++++++----
12 files changed, 66 insertions(+), 85 deletions(-)
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 8d87e67..3272b24 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -371,9 +371,6 @@ where each branch of the union names a QAPI type. For example:
'data': { 'definition': 'BlockdevOptions',
'reference': 'str' } }
-Just like for a simple union, an implicit C enum 'NameKind' is created
-to enumerate the branches for the alternate 'Name'.
-
Unlike a union, the discriminator string is never passed on the wire
for the Client JSON Protocol. Instead, the value's JSON type serves
as an implicit discriminator, which in turn means that an alternate
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 8c0ba57..7098b93 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -32,7 +32,7 @@ struct Visitor
void (*type_enum)(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
- void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
+ void (*get_next_type)(Visitor *v, qtype_code *type,
const char *name, Error **errp);
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index cfc19a6..f1ac5c4 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -41,7 +41,7 @@ GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
void visit_end_list(Visitor *v, Error **errp);
void visit_optional(Visitor *v, bool *present, const char *name,
Error **errp);
-void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
+void visit_get_next_type(Visitor *v, qtype_code *type,
const char *name, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 59ed506..3f24daa 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -81,11 +81,11 @@ void visit_optional(Visitor *v, bool *present, const char *name,
}
}
-void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
+void visit_get_next_type(Visitor *v, qtype_code *type,
const char *name, Error **errp)
{
if (v->get_next_type) {
- v->get_next_type(v, obj, qtypes, name, errp);
+ v->get_next_type(v, type, name, errp);
}
}
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 5dd9ed5..803ffad 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -208,7 +208,7 @@ static void qmp_input_end_list(Visitor *v, Error **errp)
qmp_input_pop(qiv, errp);
}
-static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
+static void qmp_input_get_next_type(Visitor *v, qtype_code *type,
const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
@@ -218,7 +218,7 @@ static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
return;
}
- *kind = qobjects[qobject_type(qobj)];
+ *type = qobject_type(qobj);
}
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 457f6a7..be6d861 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -95,51 +95,27 @@ struct %(c_name)s {
return ret
-def gen_alternate_qtypes_decl(name):
- return mcgen('''
-
-extern const int %(c_name)s_qtypes[];
-''',
- c_name=c_name(name))
-
-
-def gen_alternate_qtypes(name, variants):
- ret = mcgen('''
-
-const int %(c_name)s_qtypes[QTYPE_MAX] = {
-''',
- c_name=c_name(name))
-
- for var in variants.variants:
- qtype = var.type.alternate_qtype()
- assert qtype
-
- ret += mcgen('''
- [%(qtype)s] = %(enum_const)s,
-''',
- qtype=qtype,
- enum_const=c_enum_const(variants.tag_member.type.name,
- var.name))
-
- ret += mcgen('''
-};
-''')
- return ret
-
-
def gen_union(name, base, variants):
ret = mcgen('''
struct %(c_name)s {
''',
c_name=c_name(name))
+
if base:
ret += gen_struct_fields([], base)
+ tag_name = variants.tag_member.name
+ elif not variants.tag_member:
+ ret += mcgen('''
+ qtype_code type;
+''')
+ tag_name = 'type'
else:
ret += mcgen('''
%(c_type)s type;
''',
c_type=c_name(variants.tag_member.type.name))
+ tag_name = variants.tag_member.name
# FIXME: What purpose does data serve, besides preventing a union that
# has a branch named 'data'? We use it in qapi-visit.py to decide
@@ -153,7 +129,7 @@ struct %(c_name)s {
union { /* union tag is @%(c_name)s */
void *data;
''',
- c_name=c_name(variants.tag_member.name))
+ c_name=c_name(tag_name))
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
@@ -263,9 +239,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
def visit_alternate_type(self, name, info, variants):
self._fwdecl += gen_fwd_object_or_array(name)
- self._fwdefn += gen_alternate_qtypes(name, variants)
self.decl += gen_union(name, None, variants)
- self.decl += gen_alternate_qtypes_decl(name)
self._gen_type_cleanup(name)
# If you link code generated from multiple schemata, you want only one
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index c3e4c49..c7a6624 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -210,7 +210,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if (err) {
goto out;
}
- visit_get_next_type(m, (int*) &(*obj)->type, %(c_name)s_qtypes, name, &err);
+ visit_get_next_type(m, &(*obj)->type, name, &err);
if (err) {
goto out_end;
}
@@ -224,14 +224,14 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
break;
''',
- case=c_enum_const(variants.tag_member.type.name,
- var.name),
+ case=var.type.alternate_qtype(),
c_type=var.type.c_name(),
c_name=c_name(var.name))
ret += mcgen('''
default:
- abort();
+ error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "%(name)s");
}
out_end:
error_propagate(errp, err);
@@ -240,7 +240,8 @@ out_end:
out:
error_propagate(errp, err);
}
-''')
+''',
+ name=name)
return ret
@@ -440,6 +441,7 @@ fdef.write(mcgen('''
fdecl.write(mcgen('''
#include "qapi/visitor.h"
+#include "qapi/qmp/qerror.h"
#include "%(prefix)sqapi-types.h"
''',
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 30b2289..228bc3f 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -967,23 +967,29 @@ class QAPISchemaObjectTypeVariants(object):
for v in variants:
assert isinstance(v, QAPISchemaObjectTypeVariant)
self.tag_name = tag_name
- if tag_name:
+ if tag_name: # flat union
assert not tag_enum
self.tag_member = None
- else:
+ elif tag_enum: # simple union
self.tag_member = QAPISchemaObjectTypeMember('type', tag_enum,
False)
+ else: # alternate
+ self.tag_member = None
self.variants = variants
def check(self, schema, members, seen):
if self.tag_name:
self.tag_member = seen[self.tag_name]
- else:
+ elif self.tag_member:
self.tag_member.check(schema, members, seen)
- assert isinstance(self.tag_member.type, QAPISchemaEnumType)
+ typ = None
+ if self.tag_member:
+ assert isinstance(self.tag_member.type, QAPISchemaEnumType)
+ typ = self.tag_member.type
for v in self.variants:
vseen = dict(seen)
- v.check(schema, self.tag_member.type, vseen)
+ v.check(schema, typ, vseen)
+
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
def __init__(self, name, typ):
@@ -991,7 +997,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
def check(self, schema, tag_type, seen):
QAPISchemaObjectTypeMember.check(self, schema, [], seen)
- assert self.name in tag_type.values
+ if tag_type:
+ assert self.name in tag_type.values
# This function exists to support ugly simple union special cases
# TODO get rid of them, and drop the function
@@ -1007,7 +1014,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 not variants.tag_member
self.variants = variants
def check(self, schema):
@@ -1204,11 +1211,10 @@ class QAPISchema(object):
data = expr['data']
variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()]
- tag_enum = self._make_tag_enum(name, variants)
self._def_entity(
QAPISchemaAlternateType(name, info,
QAPISchemaObjectTypeVariants(None,
- tag_enum,
+ None,
variants)))
self._make_array_type(name) # TODO really needed?
diff --git a/tests/qapi-schema/alternate-good.out b/tests/qapi-schema/alternate-good.out
index 65af727..d211aba 100644
--- a/tests/qapi-schema/alternate-good.out
+++ b/tests/qapi-schema/alternate-good.out
@@ -3,7 +3,6 @@ alternate Alt
case value: int
case string: Enum
case struct: Data
-enum AltKind ['value', 'string', 'struct']
object Data
member number: int optional=True
member name: str optional=True
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 895fa94..0f73e49 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -56,27 +56,21 @@ object :obj-user_def_cmd3-arg
alternate AltFive
case i: int
case n: number
-enum AltFiveKind ['i', 'n']
alternate AltFour
case s: str
case i: int
-enum AltFourKind ['s', 'i']
alternate AltOne
case s: str
case b: bool
-enum AltOneKind ['s', 'b']
alternate AltSix
case n: number
case i: int
-enum AltSixKind ['n', 'i']
alternate AltThree
case n: number
case s: str
-enum AltThreeKind ['n', 's']
alternate AltTwo
case s: str
case n: number
-enum AltTwoKind ['s', 'n']
event EVENT_A None
event EVENT_B None
event EVENT_C :obj-EVENT_C-arg
@@ -97,7 +91,6 @@ alternate UserDefAlternate
case uda: UserDefA
case s: str
case i: int
-enum UserDefAlternateKind ['uda', 's', 'i']
object UserDefB
member intb: int optional=False
object UserDefC
@@ -161,7 +154,6 @@ event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
alternate __org.qemu_x-Alt
case __org.qemu_x-branch: str
case b: __org.qemu_x-Base
-enum __org.qemu_x-AltKind ['__org.qemu_x-branch', 'b']
object __org.qemu_x-Base
member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
enum __org.qemu_x-Enum ['__org.qemu_x-value']
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 3ee1a1a..cd833a4 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -373,7 +373,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
v = visitor_input_test_init(data, "42");
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
- g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I);
+ g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
g_assert_cmpint(tmp->i, ==, 42);
qapi_free_UserDefAlternate(tmp);
tmp = NULL;
@@ -381,7 +381,7 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
v = visitor_input_test_init(data, "'string'");
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
- g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S);
+ g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
g_assert_cmpstr(tmp->s, ==, "string");
qapi_free_UserDefAlternate(tmp);
tmp = NULL;
@@ -424,31 +424,31 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
qapi_free_AltTwo(two);
one = NULL;
- /* FIXME: Order of alternate should not affect semantics */
v = visitor_input_test_init(data, "42");
- visit_type_AltThree(v, &three, NULL, &error_abort);
- g_assert_cmpint(three->type, ==, ALT_THREE_KIND_N);
- g_assert_cmpfloat(three->n, ==, 42);
+ visit_type_AltThree(v, &three, NULL, &err);
+ g_assert(err);
+ error_free(err);
+ err = NULL;
qapi_free_AltThree(three);
one = NULL;
v = visitor_input_test_init(data, "42");
visit_type_AltFour(v, &four, NULL, &error_abort);
- g_assert_cmpint(four->type, ==, ALT_FOUR_KIND_I);
+ g_assert_cmpint(four->type, ==, QTYPE_QINT);
g_assert_cmpint(four->i, ==, 42);
qapi_free_AltFour(four);
one = NULL;
v = visitor_input_test_init(data, "42");
visit_type_AltFive(v, &five, NULL, &error_abort);
- g_assert_cmpint(five->type, ==, ALT_FIVE_KIND_I);
+ g_assert_cmpint(five->type, ==, QTYPE_QINT);
g_assert_cmpint(five->i, ==, 42);
qapi_free_AltFive(five);
one = NULL;
v = visitor_input_test_init(data, "42");
visit_type_AltSix(v, &six, NULL, &error_abort);
- g_assert_cmpint(six->type, ==, ALT_SIX_KIND_I);
+ g_assert_cmpint(six->type, ==, QTYPE_QINT);
g_assert_cmpint(six->i, ==, 42);
qapi_free_AltSix(six);
one = NULL;
@@ -465,14 +465,14 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "42.5");
visit_type_AltTwo(v, &two, NULL, &error_abort);
- g_assert_cmpint(two->type, ==, ALT_TWO_KIND_N);
+ g_assert_cmpint(two->type, ==, QTYPE_QFLOAT);
g_assert_cmpfloat(two->n, ==, 42.5);
qapi_free_AltTwo(two);
two = NULL;
v = visitor_input_test_init(data, "42.5");
visit_type_AltThree(v, &three, NULL, &error_abort);
- g_assert_cmpint(three->type, ==, ALT_THREE_KIND_N);
+ g_assert_cmpint(three->type, ==, QTYPE_QFLOAT);
g_assert_cmpfloat(three->n, ==, 42.5);
qapi_free_AltThree(three);
three = NULL;
@@ -487,14 +487,14 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "42.5");
visit_type_AltFive(v, &five, NULL, &error_abort);
- g_assert_cmpint(five->type, ==, ALT_FIVE_KIND_N);
+ g_assert_cmpint(five->type, ==, QTYPE_QFLOAT);
g_assert_cmpfloat(five->n, ==, 42.5);
qapi_free_AltFive(five);
five = NULL;
v = visitor_input_test_init(data, "42.5");
visit_type_AltSix(v, &six, NULL, &error_abort);
- g_assert_cmpint(six->type, ==, ALT_SIX_KIND_N);
+ g_assert_cmpint(six->type, ==, QTYPE_QFLOAT);
g_assert_cmpint(six->n, ==, 42.5);
qapi_free_AltSix(six);
six = NULL;
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index ab4bc5d..2b5c8d5 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -510,20 +510,31 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
const void *unused)
{
QObject *arg;
- Error *err = NULL;
+ UserDefAlternate *tmp;
- UserDefAlternate *tmp = g_malloc0(sizeof(UserDefAlternate));
- tmp->type = USER_DEF_ALTERNATE_KIND_I;
+ tmp = g_malloc0(sizeof(UserDefAlternate));
+ tmp->type = QTYPE_QINT;
tmp->i = 42;
- visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefAlternate(data->ov, &tmp, NULL, &error_abort);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
qapi_free_UserDefAlternate(tmp);
+
+ tmp = g_malloc0(sizeof(UserDefAlternate));
+ tmp->type = QTYPE_QSTRING;
+ tmp->s = g_strdup("hello");
+
+ visit_type_UserDefAlternate(data->ov, &tmp, NULL, &error_abort);
+ arg = qmp_output_get_qobject(data->qov);
+
+ g_assert(qobject_type(arg) == QTYPE_QSTRING);
+ g_assert_cmpstr(qstring_get_str(qobject_to_qstring(arg)), ==, "hello");
+
+ qapi_free_UserDefAlternate(tmp);
}
static void test_visitor_out_empty(TestOutputVisitorData *data,
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 09/29] qapi: Hide tag_name data member of variants
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (7 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 08/29] qapi: Simplify visiting of alternate types Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 10/29] qapi: Fix alternates that accept 'number' but not 'int' Eric Blake
` (19 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Clean up the only remaining external use of the tag_name field of
QAPISchemaObjectTypeVariants, by explicitly listing the generated
'type' tag for simple unions in the testsuite. Since alternate
types no longer use the tag_member field, we can now mark the
tag_name field as private by adding a leading underscore to
prevent any further use.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi.py | 6 +++---
tests/qapi-schema/qapi-schema-test.out | 2 ++
tests/qapi-schema/test-qapi.py | 4 ++--
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 228bc3f..a0eca74 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -966,7 +966,7 @@ class QAPISchemaObjectTypeVariants(object):
assert tag_enum is None or isinstance(tag_enum, str)
for v in variants:
assert isinstance(v, QAPISchemaObjectTypeVariant)
- self.tag_name = tag_name
+ self._tag_name = tag_name
if tag_name: # flat union
assert not tag_enum
self.tag_member = None
@@ -978,8 +978,8 @@ class QAPISchemaObjectTypeVariants(object):
self.variants = variants
def check(self, schema, members, seen):
- if self.tag_name:
- self.tag_member = seen[self.tag_name]
+ if self._tag_name:
+ self.tag_member = seen[self._tag_name]
elif self.tag_member:
self.tag_member.check(schema, members, seen)
typ = None
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 0f73e49..a44d570 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -109,6 +109,7 @@ object UserDefFlatUnion2
case value2: UserDefB
case value3: UserDefA
object UserDefNativeListUnion
+ tag type
case integer: :obj-intList-wrapper
case s8: :obj-int8List-wrapper
case s16: :obj-int16List-wrapper
@@ -163,6 +164,7 @@ object __org.qemu_x-Struct
object __org.qemu_x-Struct2
member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union1
+ tag type
case __org.qemu_x-branch: :obj-str-wrapper
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
object __org.qemu_x-Union2
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 4602da7..75f8da8 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -45,8 +45,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
@staticmethod
def _print_variants(variants):
if variants:
- if variants.tag_name:
- print ' tag %s' % variants.tag_name
+ if variants.tag_member:
+ print ' tag %s' % variants.tag_member.name
for v in variants.variants:
print ' case %s: %s' % (v.name, v.type.name)
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 10/29] qapi: Fix alternates that accept 'number' but not 'int'
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (8 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 09/29] qapi: Hide tag_name data member of variants Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 11/29] qapi: Don't pass pre-existing error to later call Eric Blake
` (18 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
The QMP input visitor allows integral values to be assigned by
promotion to a QTYPE_QFLOAT. However, when parsing an alternate,
we did not take this into account, such that an alternate that
accepts 'number' but not 'int' would reject integral values.
With this patch, we now have the following desirable table:
alternate has case selected for
'int' 'number' QTYPE_QINT QTYPE_QFLOAT
no no error error
no yes 'number' 'number'
yes no 'int' error
yes yes 'int' 'number'
While it is unlikely that we will ever use 'number' in an
alternate other than in the testsuite, it never hurts to be
more precise in what we allow.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/qapi/visitor-impl.h | 2 +-
include/qapi/visitor.h | 2 +-
qapi/qapi-visit-core.c | 4 ++--
qapi/qmp-input-visitor.c | 4 ++++
scripts/qapi-visit.py | 9 +++++++--
tests/test-qmp-input-visitor.c | 15 ++++++---------
6 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 7098b93..c94e5a1 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -32,7 +32,7 @@ struct Visitor
void (*type_enum)(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
- void (*get_next_type)(Visitor *v, qtype_code *type,
+ void (*get_next_type)(Visitor *v, qtype_code *type, bool promote_int,
const char *name, Error **errp);
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index f1ac5c4..6a93c87 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -41,7 +41,7 @@ GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
void visit_end_list(Visitor *v, Error **errp);
void visit_optional(Visitor *v, bool *present, const char *name,
Error **errp);
-void visit_get_next_type(Visitor *v, qtype_code *type,
+void visit_get_next_type(Visitor *v, qtype_code *type, bool promote_int,
const char *name, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 3f24daa..884fe94 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -81,11 +81,11 @@ void visit_optional(Visitor *v, bool *present, const char *name,
}
}
-void visit_get_next_type(Visitor *v, qtype_code *type,
+void visit_get_next_type(Visitor *v, qtype_code *type, bool promote_int,
const char *name, Error **errp)
{
if (v->get_next_type) {
- v->get_next_type(v, type, name, errp);
+ v->get_next_type(v, type, promote_int, name, errp);
}
}
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 803ffad..5310db5 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -209,6 +209,7 @@ static void qmp_input_end_list(Visitor *v, Error **errp)
}
static void qmp_input_get_next_type(Visitor *v, qtype_code *type,
+ bool promote_int,
const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
@@ -219,6 +220,9 @@ static void qmp_input_get_next_type(Visitor *v, qtype_code *type,
return;
}
*type = qobject_type(qobj);
+ if (promote_int && *type == QTYPE_QINT) {
+ *type = QTYPE_QFLOAT;
+ }
}
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index c7a6624..22d325f 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -200,6 +200,11 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error
def gen_visit_alternate(name, variants):
+ promote_int = 'true'
+ for var in variants.variants:
+ if var.type.alternate_qtype() == 'QTYPE_QINT':
+ promote_int = 'false'
+
ret = mcgen('''
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
@@ -210,13 +215,13 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if (err) {
goto out;
}
- visit_get_next_type(m, &(*obj)->type, name, &err);
+ visit_get_next_type(m, &(*obj)->type, %(promote_int)s, name, &err);
if (err) {
goto out_end;
}
switch ((*obj)->type) {
''',
- c_name=c_name(name))
+ c_name=c_name(name), promote_int=promote_int)
for var in variants.variants:
ret += mcgen('''
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index cd833a4..bba7ab2 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -415,20 +415,17 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
qapi_free_AltOne(one);
one = NULL;
- /* FIXME: Integers should parse as numbers */
v = visitor_input_test_init(data, "42");
- visit_type_AltTwo(v, &two, NULL, &err);
- g_assert(err);
- error_free(err);
- err = NULL;
+ visit_type_AltTwo(v, &two, NULL, &error_abort);
+ g_assert_cmpint(two->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(two->n, ==, 42.0);
qapi_free_AltTwo(two);
one = NULL;
v = visitor_input_test_init(data, "42");
- visit_type_AltThree(v, &three, NULL, &err);
- g_assert(err);
- error_free(err);
- err = NULL;
+ visit_type_AltThree(v, &three, NULL, &error_abort);
+ g_assert_cmpint(three->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(three->n, ==, 42.0);
qapi_free_AltThree(three);
one = NULL;
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 11/29] qapi: Don't pass pre-existing error to later call
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (9 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 10/29] qapi: Fix alternates that accept 'number' but not 'int' Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 12/29] qapi: Use consistent generated code patterns Eric Blake
` (17 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Due to the existing semantics of the error_set() family,
generated sequences in the qapi visitors such as:
visit_start_implicit_struct(m, (void **)obj, sizeof(FOO), &err);
if (!err) {
visit_type_FOO_fields(m, obj, errp);
visit_end_implicit_struct(m, &err);
}
error_propagate(errp, err);
are risky: if visit_type_FOO_fields() sets errp, and then
visit_end_implicit_struct() also encounters an error, the
attempt to overwrite the first error will cause an abort().
Obviously, we weren't triggering this situation (none of the
existing callbacks for visit_end_implicit_struct() currently
try to set an error), but it is better to not even cause the
problem in the first place.
Meanwhile, in spite of the poor documentation of the qapi
visitors, we want to guarantee that if a visit_start_*()
succeeds, then the matching visit_end_*() will be called.
The options are to either propagate and clear a local err
multiple times:
visit_start_implicit_struct(m, (void **)obj, sizeof(FOO), &err);
if (!err) {
visit_type_FOO_fields(m, obj, &err);
if (err) {
error_propagate(errp, err);
err = NULL;
}
visit_end_implicit_struct(m, &err);
}
error_propagate(errp, err);
or, as this patch does, just pass in NULL to ignore further
errors once an error has occurred.
visit_start_implicit_struct(m, (void **)obj, sizeof(FOO), &err);
if (!err) {
visit_type_FOO_fields(m, obj, &err);
visit_end_implicit_struct(m, err ? NULL : &err);
}
error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-visit.py | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 22d325f..5d4fb3a 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -51,8 +51,8 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
if (!err) {
- visit_type_%(c_type)s_fields(m, obj, errp);
- visit_end_implicit_struct(m, &err);
+ visit_type_%(c_type)s_fields(m, obj, &err);
+ visit_end_implicit_struct(m, err ? NULL : &err);
}
error_propagate(errp, err);
}
@@ -146,9 +146,9 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
if (!err) {
if (*obj) {
- visit_type_%(c_name)s_fields(m, obj, errp);
+ visit_type_%(c_name)s_fields(m, obj, &err);
}
- visit_end_struct(m, &err);
+ visit_end_struct(m, err ? NULL : &err);
}
error_propagate(errp, err);
}
@@ -178,9 +178,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
visit_type_%(c_elt_type)s(m, &native_i->value, NULL, &err);
}
- error_propagate(errp, err);
- err = NULL;
- visit_end_list(m, &err);
+ visit_end_list(m, err ? NULL : &err);
out:
error_propagate(errp, err);
}
@@ -239,9 +237,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
"%(name)s");
}
out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_implicit_struct(m, &err);
+ visit_end_implicit_struct(m, err ? NULL : &err);
out:
error_propagate(errp, err);
}
@@ -332,10 +328,8 @@ out_obj:
error_propagate(errp, err);
err = NULL;
visit_end_union(m, !!(*obj)->data, &err);
- error_propagate(errp, err);
- err = NULL;
}
- visit_end_struct(m, &err);
+ visit_end_struct(m, err ? NULL : &err);
out:
error_propagate(errp, err);
}
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 12/29] qapi: Use consistent generated code patterns
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (10 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 11/29] qapi: Don't pass pre-existing error to later call Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 13/29] qapi: Add tests for empty unions Eric Blake
` (16 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
We had a pointless difference in label names, and on whether
the generated code used:
if (*obj) {
stuff;
...
}
vs.
if (!*obj) {
goto out_obj;
}
stuff;
...
Pick a single style, as it will make it easier for later patches
to uniformly apply any updates to generated code.
No change in semantics to the generated code.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-visit.py | 47 ++++++++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 5d4fb3a..d968642 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -215,7 +215,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
}
visit_get_next_type(m, &(*obj)->type, %(promote_int)s, name, &err);
if (err) {
- goto out_end;
+ goto out_obj;
}
switch ((*obj)->type) {
''',
@@ -236,7 +236,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"%(name)s");
}
-out_end:
+out_obj:
visit_end_implicit_struct(m, err ? NULL : &err);
out:
error_propagate(errp, err);
@@ -269,30 +269,32 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if (err) {
goto out;
}
- if (*obj) {
+ if (!*obj) {
+ goto out_obj;
+ }
''',
c_name=c_name(name), name=name)
tag_key = variants.tag_member.name
if base:
ret += mcgen('''
- visit_type_%(c_name)s_fields(m, (%(c_name)s **)obj, &err);
+ visit_type_%(c_name)s_fields(m, (%(c_name)s **)obj, &err);
''',
c_name=c_name(base.name))
else:
ret += mcgen('''
- visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
''',
c_type=variants.tag_member.type.c_name(),
c_name=c_name(tag_key), name=tag_key)
ret += mcgen('''
- if (err) {
- goto out_obj;
- }
- if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
- goto out_obj;
- }
- switch ((*obj)->%(c_name)s) {
+ if (err) {
+ goto out_obj;
+ }
+ if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
+ goto out_obj;
+ }
+ switch ((*obj)->%(c_name)s) {
''',
c_name=c_name(tag_key))
@@ -300,35 +302,34 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
# TODO ugly special case for simple union
simple_union_type = var.simple_union_type()
ret += mcgen('''
- case %(case)s:
+ case %(case)s:
''',
case=c_enum_const(variants.tag_member.type.name,
var.name))
if simple_union_type:
ret += mcgen('''
- visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);
''',
c_type=simple_union_type.c_name(),
c_name=c_name(var.name))
else:
ret += mcgen('''
- visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);
+ visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);
''',
c_type=var.type.c_name(),
c_name=c_name(var.name))
ret += mcgen('''
- break;
+ break;
''')
ret += mcgen('''
- default:
- abort();
- }
-out_obj:
- error_propagate(errp, err);
- err = NULL;
- visit_end_union(m, !!(*obj)->data, &err);
+ default:
+ abort();
}
+out_obj:
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_union(m, !!(*obj)->data, &err);
visit_end_struct(m, err ? NULL : &err);
out:
error_propagate(errp, err);
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 13/29] qapi: Add tests for empty unions
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (11 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 12/29] qapi: Use consistent generated code patterns Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 14/29] qapi: Rework deallocation of partial struct Eric Blake
` (15 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
The documentation claims that alternates are useful for
allowing two types, although nothing enforces this. Meanwhile,
it is silent on whether empty unions are allowed. In practice,
the generated code will compile, in part because we have a
'void *data' branch; but for an empty alternate it always
fails (at least as of my recent fix to use qtypes directly), and
an empty union (whether simple or flat) always causes an abort().
Add some tests to expose the problems, and adjust existing tests
that should be failing for other reasons.
Not tested here: we have a namespace collision, where if the qapi
schema lists 'data' as one of the possible branch names of a
union, then the generated C code fails to compile due to a
duplicate member 'data'.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
tests/Makefile | 1 +
tests/qapi-schema/alternate-empty.err | 0
tests/qapi-schema/alternate-empty.exit | 1 +
tests/qapi-schema/alternate-empty.json | 2 ++
tests/qapi-schema/alternate-empty.out | 3 +++
tests/qapi-schema/alternate-nested.json | 2 +-
tests/qapi-schema/alternate-unknown.json | 2 +-
tests/qapi-schema/flat-union-empty.err | 0
tests/qapi-schema/flat-union-empty.exit | 1 +
tests/qapi-schema/flat-union-empty.json | 4 ++++
tests/qapi-schema/flat-union-empty.out | 7 +++++++
tests/qapi-schema/union-empty.err | 0
tests/qapi-schema/union-empty.exit | 1 +
tests/qapi-schema/union-empty.json | 2 ++
tests/qapi-schema/union-empty.out | 4 ++++
15 files changed, 28 insertions(+), 2 deletions(-)
create mode 100644 tests/qapi-schema/alternate-empty.err
create mode 100644 tests/qapi-schema/alternate-empty.exit
create mode 100644 tests/qapi-schema/alternate-empty.json
create mode 100644 tests/qapi-schema/alternate-empty.out
create mode 100644 tests/qapi-schema/flat-union-empty.err
create mode 100644 tests/qapi-schema/flat-union-empty.exit
create mode 100644 tests/qapi-schema/flat-union-empty.json
create mode 100644 tests/qapi-schema/flat-union-empty.out
create mode 100644 tests/qapi-schema/union-empty.err
create mode 100644 tests/qapi-schema/union-empty.exit
create mode 100644 tests/qapi-schema/union-empty.json
create mode 100644 tests/qapi-schema/union-empty.out
diff --git a/tests/Makefile b/tests/Makefile
index 1d06fa8..d1d647f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -246,6 +246,7 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
unclosed-list.json unclosed-object.json unclosed-string.json \
duplicate-key.json union-invalid-base.json union-bad-branch.json \
union-optional-branch.json union-unknown.json union-max.json \
+ union-empty.json flat-union-empty.json alternate-empty.json \
flat-union-optional-discriminator.json flat-union-no-base.json \
flat-union-invalid-discriminator.json flat-union-inline.json \
flat-union-invalid-branch-key.json flat-union-reverse-define.json \
diff --git a/tests/qapi-schema/alternate-empty.err b/tests/qapi-schema/alternate-empty.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/alternate-empty.exit b/tests/qapi-schema/alternate-empty.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/alternate-empty.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/alternate-empty.json b/tests/qapi-schema/alternate-empty.json
new file mode 100644
index 0000000..db3820f
--- /dev/null
+++ b/tests/qapi-schema/alternate-empty.json
@@ -0,0 +1,2 @@
+# FIXME - alternates should list at least two types to be useful
+{ 'alternate': 'Alt', 'data': { 'i': 'int' } }
diff --git a/tests/qapi-schema/alternate-empty.out b/tests/qapi-schema/alternate-empty.out
new file mode 100644
index 0000000..9b010d8
--- /dev/null
+++ b/tests/qapi-schema/alternate-empty.out
@@ -0,0 +1,3 @@
+object :empty
+alternate Alt
+ case i: int
diff --git a/tests/qapi-schema/alternate-nested.json b/tests/qapi-schema/alternate-nested.json
index c4233b9..8e22186 100644
--- a/tests/qapi-schema/alternate-nested.json
+++ b/tests/qapi-schema/alternate-nested.json
@@ -2,4 +2,4 @@
{ 'alternate': 'Alt1',
'data': { 'name': 'str', 'value': 'int' } }
{ 'alternate': 'Alt2',
- 'data': { 'nested': 'Alt1' } }
+ 'data': { 'nested': 'Alt1', 'b': 'bool' } }
diff --git a/tests/qapi-schema/alternate-unknown.json b/tests/qapi-schema/alternate-unknown.json
index ad5c103..08c80dc 100644
--- a/tests/qapi-schema/alternate-unknown.json
+++ b/tests/qapi-schema/alternate-unknown.json
@@ -1,3 +1,3 @@
# we reject an alternate with unknown type in branch
{ 'alternate': 'Alt',
- 'data': { 'unknown': 'MissingType' } }
+ 'data': { 'unknown': 'MissingType', 'i': 'int' } }
diff --git a/tests/qapi-schema/flat-union-empty.err b/tests/qapi-schema/flat-union-empty.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/flat-union-empty.exit b/tests/qapi-schema/flat-union-empty.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/flat-union-empty.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/flat-union-empty.json b/tests/qapi-schema/flat-union-empty.json
new file mode 100644
index 0000000..67dd297
--- /dev/null
+++ b/tests/qapi-schema/flat-union-empty.json
@@ -0,0 +1,4 @@
+# FIXME - flat unions should not be empty
+{ 'enum': 'Empty', 'data': [ ] }
+{ 'struct': 'Base', 'data': { 'type': 'Empty' } }
+{ 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }
diff --git a/tests/qapi-schema/flat-union-empty.out b/tests/qapi-schema/flat-union-empty.out
new file mode 100644
index 0000000..0e0665a
--- /dev/null
+++ b/tests/qapi-schema/flat-union-empty.out
@@ -0,0 +1,7 @@
+object :empty
+object Base
+ member type: Empty optional=False
+enum Empty []
+object Union
+ base Base
+ tag type
diff --git a/tests/qapi-schema/union-empty.err b/tests/qapi-schema/union-empty.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/union-empty.exit b/tests/qapi-schema/union-empty.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/union-empty.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/union-empty.json b/tests/qapi-schema/union-empty.json
new file mode 100644
index 0000000..1785007
--- /dev/null
+++ b/tests/qapi-schema/union-empty.json
@@ -0,0 +1,2 @@
+# FIXME - unions should not be empty
+{ 'union': 'Union', 'data': { } }
diff --git a/tests/qapi-schema/union-empty.out b/tests/qapi-schema/union-empty.out
new file mode 100644
index 0000000..c5500da
--- /dev/null
+++ b/tests/qapi-schema/union-empty.out
@@ -0,0 +1,4 @@
+object :empty
+object Union
+ tag type
+enum UnionKind []
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 14/29] qapi: Rework deallocation of partial struct
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (12 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 13/29] qapi: Add tests for empty unions Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 15/29] qapi: Avoid use of 'data' member of qapi unions Eric Blake
` (14 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Commit cee2dedb noticed that if you have a partial flat union
(such as if an input parse failed due to a missing
discriminator), calling the dealloc visitor could result in
trying to dereference the NULL pointer. But the fix it proposed
requires the use of a 'data' member in the union, which may or
may not be the same size as other branches of the union
(consider a 32-bit platform where one of the branches is an
int64), so it feels fairly dirty. A better, and much shorter,
fix is to tweak all of the generated visit_type_implicit_FOO()
functions to avoid dereferencing NULL in the first place, to
not visit the fields if the struct pointer itself is not present,
at which point we no longer even need visit_start_union(), and
no one was implementing visit_end_union() callbacks. The change
keeps the contract that any successful use of
visit_start_implicit_struct() will be paired with a matching
visit_end_implicit_struct(), even if intermediate processing is
skipped.
The lack of documentation on the visitor interface is appalling,
but I'm not fixing it here.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/qapi/visitor-impl.h | 2 --
include/qapi/visitor.h | 2 --
qapi/qapi-dealloc-visitor.c | 26 --------------------------
qapi/qapi-visit-core.c | 15 ---------------
scripts/qapi-visit.py | 12 ++++--------
5 files changed, 4 insertions(+), 53 deletions(-)
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index c94e5a1..22539df 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -57,8 +57,6 @@ struct Visitor
void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
/* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
- bool (*start_union)(Visitor *v, bool data_present, Error **errp);
- void (*end_union)(Visitor *v, bool data_present, Error **errp);
};
void input_type_enum(Visitor *v, int *obj, const char * const strings[],
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 6a93c87..d1e853c 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -59,7 +59,5 @@ void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
void visit_type_any(Visitor *v, QObject **obj, const char *name, Error **errp);
-bool visit_start_union(Visitor *v, bool data_present, Error **errp);
-void visit_end_union(Visitor *v, bool data_present, Error **errp);
#endif
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index 737deab..4989f50 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -171,31 +171,6 @@ static void qapi_dealloc_type_enum(Visitor *v, int *obj,
{
}
-/* If there's no data present, the dealloc visitor has nothing to free.
- * Thus, indicate to visitor code that the subsequent union fields can
- * be skipped. This is not an error condition, since the cleanup of the
- * rest of an object can continue unhindered, so leave errp unset in
- * these cases.
- *
- * NOTE: In cases where we're attempting to deallocate an object that
- * may have missing fields, the field indicating the union type may
- * be missing. In such a case, it's possible we don't have enough
- * information to differentiate data_present == false from a case where
- * data *is* present but happens to be a scalar with a value of 0.
- * This is okay, since in the case of the dealloc visitor there's no
- * work that needs to done in either situation.
- *
- * The current inability in QAPI code to more thoroughly verify a union
- * type in such cases will likely need to be addressed if we wish to
- * implement this interface for other types of visitors in the future,
- * however.
- */
-static bool qapi_dealloc_start_union(Visitor *v, bool data_present,
- Error **errp)
-{
- return data_present;
-}
-
Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
{
return &v->visitor;
@@ -226,7 +201,6 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
v->visitor.type_number = qapi_dealloc_type_number;
v->visitor.type_any = qapi_dealloc_type_anything;
v->visitor.type_size = qapi_dealloc_type_size;
- v->visitor.start_union = qapi_dealloc_start_union;
QTAILQ_INIT(&v->stack);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 884fe94..82bfdd0 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -58,21 +58,6 @@ void visit_end_list(Visitor *v, Error **errp)
v->end_list(v, errp);
}
-bool visit_start_union(Visitor *v, bool data_present, Error **errp)
-{
- if (v->start_union) {
- return v->start_union(v, data_present, errp);
- }
- return true;
-}
-
-void visit_end_union(Visitor *v, bool data_present, Error **errp)
-{
- if (v->end_union) {
- v->end_union(v, data_present, errp);
- }
-}
-
void visit_optional(Visitor *v, bool *present, const char *name,
Error **errp)
{
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index d968642..81527ce 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -51,7 +51,9 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
if (!err) {
- visit_type_%(c_type)s_fields(m, obj, &err);
+ if (!obj || *obj) {
+ visit_type_%(c_type)s_fields(m, obj, &err);
+ }
visit_end_implicit_struct(m, err ? NULL : &err);
}
error_propagate(errp, err);
@@ -209,7 +211,7 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
{
Error *err = NULL;
- visit_start_implicit_struct(m, (void**) obj, sizeof(%(c_name)s), &err);
+ visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_name)s), &err);
if (err) {
goto out;
}
@@ -291,9 +293,6 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if (err) {
goto out_obj;
}
- if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
- goto out_obj;
- }
switch ((*obj)->%(c_name)s) {
''',
c_name=c_name(tag_key))
@@ -327,9 +326,6 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
abort();
}
out_obj:
- error_propagate(errp, err);
- err = NULL;
- visit_end_union(m, !!(*obj)->data, &err);
visit_end_struct(m, err ? NULL : &err);
out:
error_propagate(errp, err);
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 15/29] qapi: Avoid use of 'data' member of qapi unions
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (13 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 14/29] qapi: Rework deallocation of partial struct Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 16/29] qapi: Forbid empty unions and useless alternates Eric Blake
` (13 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, open list:Block layer core, armbru, Gerd Hoffmann,
DirtY.iCE.hu, marcandre.lureau
qapi code generators currently create a 'void *data' member as
part of the anonymous union embedded in the C struct corresponding
to a qapi union. However, directly assigning to this member of
the union feels a bit fishy, when we can directly use the rest
of the struct instead.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
blockdev.c | 22 ++++++++++++----------
ui/input.c | 2 +-
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index e4cec0e..0808312 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1052,14 +1052,11 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
}
}
-static void blockdev_do_action(int type, void *data, Error **errp)
+static void blockdev_do_action(TransactionAction *action, Error **errp)
{
- TransactionAction action;
TransactionActionList list;
- action.type = type;
- action.data = data;
- list.value = &action;
+ list.value = action;
list.next = NULL;
qmp_transaction(&list, errp);
}
@@ -1085,8 +1082,11 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
.has_mode = has_mode,
.mode = mode,
};
- blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
- &snapshot, errp);
+ TransactionAction action = {
+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
+ .blockdev_snapshot_sync = &snapshot,
+ };
+ blockdev_do_action(&action, errp);
}
void qmp_blockdev_snapshot_internal_sync(const char *device,
@@ -1097,9 +1097,11 @@ void qmp_blockdev_snapshot_internal_sync(const char *device,
.device = (char *) device,
.name = (char *) name
};
-
- blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
- &snapshot, errp);
+ TransactionAction action = {
+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
+ .blockdev_snapshot_internal_sync = &snapshot,
+ };
+ blockdev_do_action(&action, errp);
}
SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
diff --git a/ui/input.c b/ui/input.c
index fd86571..edd237d 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -452,7 +452,7 @@ InputEvent *qemu_input_event_new_move(InputEventKind kind,
InputMoveEvent *move = g_new0(InputMoveEvent, 1);
evt->type = kind;
- evt->data = move;
+ evt->rel = move; /* also would work as evt->abs */
move->axis = axis;
move->value = value;
return evt;
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 16/29] qapi: Forbid empty unions and useless alternates
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (14 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 15/29] qapi: Avoid use of 'data' member of qapi unions Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 17/29] qapi: Drop useless 'data' member of unions Eric Blake
` (12 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Empty unions serve no purpose, and while we compile with gcc
which permits them, strict C99 forbids them. We could inject
a dummy member (and in fact, we do for empty structs), but while
empty structs make sense in qapi, empty unions don't add any
expressiveness to the QMP language. So prohibit them at parse
time. Update the documentation and testsuite to match.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
docs/qapi-code-gen.txt | 13 +++++++------
scripts/qapi.py | 12 ++++++++++--
tests/qapi-schema/alternate-empty.err | 1 +
tests/qapi-schema/alternate-empty.exit | 2 +-
tests/qapi-schema/alternate-empty.json | 2 +-
tests/qapi-schema/alternate-empty.out | 3 ---
tests/qapi-schema/flat-union-empty.err | 1 +
tests/qapi-schema/flat-union-empty.exit | 2 +-
tests/qapi-schema/flat-union-empty.json | 2 +-
tests/qapi-schema/flat-union-empty.out | 7 -------
tests/qapi-schema/union-empty.err | 1 +
tests/qapi-schema/union-empty.exit | 2 +-
tests/qapi-schema/union-empty.json | 2 +-
tests/qapi-schema/union-empty.out | 4 ----
14 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 3272b24..ff57010 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -182,11 +182,11 @@ prevent incomplete include files.
Usage: { 'struct': STRING, 'data': DICT, '*base': STRUCT-NAME }
-A struct is a dictionary containing a single 'data' key whose
-value is a dictionary. This corresponds to a struct in C or an Object
-in JSON. Each value of the 'data' dictionary must be the name of a
-type, or a one-element array containing a type name. An example of a
-struct is:
+A struct is a dictionary containing a single 'data' key whose value is
+a dictionary; the dictionary may be empty. This corresponds to a
+struct in C or an Object in JSON. Each value of the 'data' dictionary
+must be the name of a type, or a one-element array containing a type
+name. An example of a struct is:
{ 'struct': 'MyType',
'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } }
@@ -277,7 +277,8 @@ Union types are used to let the user choose between several different
variants for an object. There are two flavors: simple (no
discriminator or base), flat (both discriminator and base). A union
type is defined using a data dictionary as explained in the following
-paragraphs.
+paragraphs. The data dictionary for either type of union must not
+be empty.
A simple union type defines a mapping from automatic discriminator
values to data types like in this example:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index a0eca74..475d2c2 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -563,7 +563,10 @@ def check_union(expr, expr_info):
"Discriminator '%s' must be of enumeration "
"type" % discriminator)
- # Check every branch
+ # Check every branch; don't allow an empty union
+ if len(members) == 0:
+ raise QAPIExprError(expr_info,
+ "Union '%s' cannot have empty 'data'" % name)
for (key, value) in members.items():
check_name(expr_info, "Member of union '%s'" % name, key)
@@ -601,7 +604,11 @@ def check_alternate(expr, expr_info):
values = { 'MAX': '(automatic)' }
types_seen = {}
- # Check every branch
+ # Check every branch; require at least two branches
+ if len(members) < 2:
+ raise QAPIExprError(expr_info,
+ "Alternate '%s' should have at least two branches "
+ "in 'data'" % name)
for (key, value) in members.items():
check_name(expr_info, "Member of alternate '%s'" % name, key)
@@ -964,6 +971,7 @@ class QAPISchemaObjectTypeVariants(object):
def __init__(self, tag_name, tag_enum, variants):
assert tag_name is None or isinstance(tag_name, str)
assert tag_enum is None or isinstance(tag_enum, str)
+ assert len(variants) > 0
for v in variants:
assert isinstance(v, QAPISchemaObjectTypeVariant)
self._tag_name = tag_name
diff --git a/tests/qapi-schema/alternate-empty.err b/tests/qapi-schema/alternate-empty.err
index e69de29..bb06c5b 100644
--- a/tests/qapi-schema/alternate-empty.err
+++ b/tests/qapi-schema/alternate-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' should have at least two branches in 'data'
diff --git a/tests/qapi-schema/alternate-empty.exit b/tests/qapi-schema/alternate-empty.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/alternate-empty.exit
+++ b/tests/qapi-schema/alternate-empty.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/alternate-empty.json b/tests/qapi-schema/alternate-empty.json
index db3820f..fff15ba 100644
--- a/tests/qapi-schema/alternate-empty.json
+++ b/tests/qapi-schema/alternate-empty.json
@@ -1,2 +1,2 @@
-# FIXME - alternates should list at least two types to be useful
+# alternates must list at least two types to be useful
{ 'alternate': 'Alt', 'data': { 'i': 'int' } }
diff --git a/tests/qapi-schema/alternate-empty.out b/tests/qapi-schema/alternate-empty.out
index 9b010d8..e69de29 100644
--- a/tests/qapi-schema/alternate-empty.out
+++ b/tests/qapi-schema/alternate-empty.out
@@ -1,3 +0,0 @@
-object :empty
-alternate Alt
- case i: int
diff --git a/tests/qapi-schema/flat-union-empty.err b/tests/qapi-schema/flat-union-empty.err
index e69de29..15754f5 100644
--- a/tests/qapi-schema/flat-union-empty.err
+++ b/tests/qapi-schema/flat-union-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-empty.json:4: Union 'Union' cannot have empty 'data'
diff --git a/tests/qapi-schema/flat-union-empty.exit b/tests/qapi-schema/flat-union-empty.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/flat-union-empty.exit
+++ b/tests/qapi-schema/flat-union-empty.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/flat-union-empty.json b/tests/qapi-schema/flat-union-empty.json
index 67dd297..77f1d9a 100644
--- a/tests/qapi-schema/flat-union-empty.json
+++ b/tests/qapi-schema/flat-union-empty.json
@@ -1,4 +1,4 @@
-# FIXME - flat unions should not be empty
+# flat unions cannot be empty
{ 'enum': 'Empty', 'data': [ ] }
{ 'struct': 'Base', 'data': { 'type': 'Empty' } }
{ 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }
diff --git a/tests/qapi-schema/flat-union-empty.out b/tests/qapi-schema/flat-union-empty.out
index 0e0665a..e69de29 100644
--- a/tests/qapi-schema/flat-union-empty.out
+++ b/tests/qapi-schema/flat-union-empty.out
@@ -1,7 +0,0 @@
-object :empty
-object Base
- member type: Empty optional=False
-enum Empty []
-object Union
- base Base
- tag type
diff --git a/tests/qapi-schema/union-empty.err b/tests/qapi-schema/union-empty.err
index e69de29..12c2022 100644
--- a/tests/qapi-schema/union-empty.err
+++ b/tests/qapi-schema/union-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-empty.json:2: Union 'Union' cannot have empty 'data'
diff --git a/tests/qapi-schema/union-empty.exit b/tests/qapi-schema/union-empty.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/union-empty.exit
+++ b/tests/qapi-schema/union-empty.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/union-empty.json b/tests/qapi-schema/union-empty.json
index 1785007..1f0b13c 100644
--- a/tests/qapi-schema/union-empty.json
+++ b/tests/qapi-schema/union-empty.json
@@ -1,2 +1,2 @@
-# FIXME - unions should not be empty
+# unions cannot be empty
{ 'union': 'Union', 'data': { } }
diff --git a/tests/qapi-schema/union-empty.out b/tests/qapi-schema/union-empty.out
index c5500da..e69de29 100644
--- a/tests/qapi-schema/union-empty.out
+++ b/tests/qapi-schema/union-empty.out
@@ -1,4 +0,0 @@
-object :empty
-object Union
- tag type
-enum UnionKind []
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 17/29] qapi: Drop useless 'data' member of unions
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (15 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 16/29] qapi: Forbid empty unions and useless alternates Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 18/29] qapi: Remove dead visitor code Eric Blake
` (11 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Now that we no longer have any clients of the 'void *data'
member injected into unions, we can drop it. Update the
testsuite to prove that we no longer have a name collision.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-types.py | 9 ---------
tests/qapi-schema/qapi-schema-test.json | 2 +-
tests/qapi-schema/qapi-schema-test.out | 4 ++--
3 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index be6d861..9f3a929 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -117,17 +117,8 @@ struct %(c_name)s {
c_type=c_name(variants.tag_member.type.name))
tag_name = variants.tag_member.name
- # FIXME: What purpose does data serve, besides preventing a union that
- # has a branch named 'data'? We use it in qapi-visit.py to decide
- # whether to bypass the switch statement if visiting the discriminator
- # failed; but since we 0-initialize structs, and cannot tell what
- # branch of the union is in use if the discriminator is invalid, there
- # should not be any data leaks even without a data pointer. Or, if
- # 'data' is merely added to guarantee we don't have an empty union,
- # shouldn't we enforce that at .json parse time?
ret += mcgen('''
union { /* union tag is @%(c_name)s */
- void *data;
''',
c_name=c_name(tag_name))
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 14016ab..a6321ec 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -81,7 +81,7 @@
'number': ['number'],
'boolean': ['bool'],
'string': ['str'],
- 'sizes': ['size'],
+ 'data': ['size'],
'any': ['any'] } }
# testing commands
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index a44d570..b6e423e 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -122,9 +122,9 @@ object UserDefNativeListUnion
case number: :obj-numberList-wrapper
case boolean: :obj-boolList-wrapper
case string: :obj-strList-wrapper
- case sizes: :obj-sizeList-wrapper
+ case data: :obj-sizeList-wrapper
case any: :obj-anyList-wrapper
-enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
+enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'data', 'any']
object UserDefOne
base UserDefZero
member string: str optional=False
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 18/29] qapi: Remove dead visitor code
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (16 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 17/29] qapi: Drop useless 'data' member of unions Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 19/29] qapi: Document visitor interfaces Eric Blake
` (10 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Commit cbc95538 removed unused start_handle() and end_handle(),
but forgot got remove their declarations.
Commit 4e27e819 introduced optional visitor callbacks for all
sorts of int types, but except for type_uint64 and type_size,
none of them have ever been supplied (the generic implementation
based on using type_int then bounds-checking works just fine).
In the interest of simplicity, it's easier to make the visitor
callback interface not have to worry about the other sizes.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/qapi/visitor-impl.h | 16 ++----
include/qapi/visitor.h | 3 -
qapi/qapi-visit-core.c | 131 +++++++++++++++++---------------------------
3 files changed, 56 insertions(+), 94 deletions(-)
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 22539df..df70dd9 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -47,16 +47,12 @@ struct Visitor
void (*optional)(Visitor *v, bool *present, const char *name,
Error **errp);
- void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
- void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
- void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
- void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
- void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp);
- void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp);
- void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp);
- void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
- /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
- void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+ /* visit_type_uint64() falls back to (*type_int)() as needed */
+ void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name,
+ Error **errp);
+ /* visit_type_size() falls back to (*type_uint64)() as needed */
+ void (*type_size)(Visitor *v, uint64_t *obj, const char *name,
+ Error **errp);
};
void input_type_enum(Visitor *v, int *obj, const char * const strings[],
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index d1e853c..5436069 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -27,9 +27,6 @@ typedef struct GenericList
struct GenericList *next;
} GenericList;
-void visit_start_handle(Visitor *v, void **obj, const char *kind,
- const char *name, Error **errp);
-void visit_end_handle(Visitor *v, Error **errp);
void visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
void visit_end_struct(Visitor *v, Error **errp);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 82bfdd0..6d8ea95 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -89,57 +89,48 @@ void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
{
int64_t value;
- if (v->type_uint8) {
- v->type_uint8(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT8_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint8_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT8_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "uint8_t");
+ return;
}
+ *obj = value;
}
-void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name,
+ Error **errp)
{
int64_t value;
- if (v->type_uint16) {
- v->type_uint16(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT16_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint16_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT16_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "uint16_t");
+ return;
}
+ *obj = value;
}
-void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name,
+ Error **errp)
{
int64_t value;
- if (v->type_uint32) {
- v->type_uint32(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT32_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint32_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < 0 || value > UINT32_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "uint32_t");
+ return;
}
+ *obj = value;
}
-void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name,
+ Error **errp)
{
int64_t value;
@@ -156,77 +147,55 @@ void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
{
int64_t value;
- if (v->type_int8) {
- v->type_int8(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT8_MIN || value > INT8_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int8_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT8_MIN || value > INT8_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int8_t");
+ return;
}
+ *obj = value;
}
void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
{
int64_t value;
- if (v->type_int16) {
- v->type_int16(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT16_MIN || value > INT16_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int16_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT16_MIN || value > INT16_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int16_t");
+ return;
}
+ *obj = value;
}
void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
{
int64_t value;
- if (v->type_int32) {
- v->type_int32(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT32_MIN || value > INT32_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int32_t");
- return;
- }
- *obj = value;
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ if (value < INT32_MIN || value > INT32_MAX) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int32_t");
+ return;
}
+ *obj = value;
}
void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
{
- if (v->type_int64) {
- v->type_int64(v, obj, name, errp);
- } else {
- v->type_int(v, obj, name, errp);
- }
+ v->type_int(v, obj, name, errp);
}
void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
{
- int64_t value;
-
if (v->type_size) {
v->type_size(v, obj, name, errp);
- } else if (v->type_uint64) {
- v->type_uint64(v, obj, name, errp);
} else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- *obj = value;
+ visit_type_uint64(v, obj, name, errp);
}
}
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 19/29] qapi: Document visitor interfaces
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (17 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 18/29] qapi: Remove dead visitor code Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 20/29] qapi: Plug leaks in test-qmp-input-visitor Eric Blake
` (9 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, armbru, DirtY.iCE.hu
The visitor interface for mapping between QObject and qapi
has formerly been documented only by reading source code,
making it difficult to propose changes to either
scripts/qapi*.py or to clients without knowing whether those
changes would be safe. This tries to add documentation,
including mentioning when parameters can be NULL, and where
there are still some interface warts that would be nice
to remove.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/qapi/visitor-impl.h | 39 ++++++++-
include/qapi/visitor.h | 192 +++++++++++++++++++++++++++++++++++++++++---
2 files changed, 218 insertions(+), 13 deletions(-)
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index df70dd9..7e8f728 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -15,48 +15,79 @@
#include "qapi/error.h"
#include "qapi/visitor.h"
+/* This file describes the callback interface for implementing a
+ * QObject visitor. For the client interface, see visitor.h. When
+ * implementing the callbacks, it is easiest to declare a struct with
+ * 'Visitor visitor;' as the first member. Semantics for the
+ * callbacks are generally similar to the counterpart public
+ * interface. */
+
struct Visitor
{
- /* Must be set */
+ /* Must be provided to visit structs (the string visitors do not
+ * currently visit structs). */
void (*start_struct)(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
+ /* Must be provided if start_struct is present. */
void (*end_struct)(Visitor *v, Error **errp);
+ /* May be NULL; most useful for input visitors. */
void (*start_implicit_struct)(Visitor *v, void **obj, size_t size,
Error **errp);
+ /* May be NULL */
void (*end_implicit_struct)(Visitor *v, Error **errp);
+ /* Must be set */
void (*start_list)(Visitor *v, const char *name, Error **errp);
+ /* Must be set */
GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
+ /* Must be set */
void (*end_list)(Visitor *v, Error **errp);
+ /* Must be set, although the helpers input_type_enum() and
+ * output_type_enum() can be used. */
void (*type_enum)(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
+ /* May be NULL; most useful for input visitors. */
void (*get_next_type)(Visitor *v, qtype_code *type, bool promote_int,
const char *name, Error **errp);
+ /* Must be set */
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
+ /* Must be set */
void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
+ /* Must be set */
void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
+
+ /* Must be provided to visit numbers (the opts visitor does not
+ * currently visit non-integers). */
void (*type_number)(Visitor *v, double *obj, const char *name,
Error **errp);
+ /* Must be provided to visit arbitrary QTypes (the opts and string
+ * visitors do not currently visit arbitrary types). */
void (*type_any)(Visitor *v, QObject **obj, const char *name,
Error **errp);
- /* May be NULL */
+ /* May be NULL; most useful for input visitors. */
void (*optional)(Visitor *v, bool *present, const char *name,
Error **errp);
- /* visit_type_uint64() falls back to (*type_int)() as needed */
+ /* Only required to visit uint64 differently than (*type_int)(). */
void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name,
Error **errp);
- /* visit_type_size() falls back to (*type_uint64)() as needed */
+ /* Only required to visit sizes differently than (*type_uint64)(). */
void (*type_size)(Visitor *v, uint64_t *obj, const char *name,
Error **errp);
};
+/**
+ * A generic visitor.type_enum suitable for input visitors.
+ */
void input_type_enum(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
+/**
+ * A generic visitor.type_enum suitable for output visitors.
+ */
void output_type_enum(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 5436069..4ac0c3a 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -18,6 +18,17 @@
#include "qapi/error.h"
#include <stdlib.h>
+/* This file describes the client view for visiting a map between
+ * QObjects and another representation (command line options, strings,
+ * or generated QAPI C structs). An input visitor converts from
+ * QObject to another form; an output visitor converts from the other
+ * form back into QObjects. These functions seldom need to be called
+ * directly, but are instead used by code generated by
+ * scripts/qapi-visit.py. For the visitor callback contracts, see
+ * visitor-impl.h. */
+
+/* This struct is layout-compatible with all other *List structs
+ * created by the qapi generator. */
typedef struct GenericList
{
union {
@@ -27,34 +38,197 @@ typedef struct GenericList
struct GenericList *next;
} GenericList;
+/**
+ * Prepare to visit a QDict with C type @kind tied to QDict key @name.
+ * @name will be NULL if this is visited as part of a QList.
+ * The caller then makes a series of visit calls for each key expected
+ * in the dictionary, followed by a call to visit_end_struct(). For an
+ * input visitor, @obj can be NULL to validate that the visit will
+ * succeed; otherwise, *@obj is assigned with an allocation of @size
+ * bytes. For other visitors, *@obj is the object to visit. Set *@errp
+ * on failure.
+ *
+ * FIXME: *@obj can be modified even on error; this can lead to
+ * memory leaks if clients aren't careful.
+ */
void visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
+/**
+ * Complete a struct started earlier.
+ * Must be called after any successful use of visit_start_struct(),
+ * even if intermediate processing was skipped due to errors.
+ */
void visit_end_struct(Visitor *v, Error **errp);
+
+/**
+ * Prepare to visit an implicit struct.
+ * Similar to visit_start_struct(), except that this will visit a
+ * C pointer pointing to @size bytes, and where the QDict fields are
+ * part of the parent object.
+ *
+ * FIXME: *@obj can be modified even on error; this can lead to
+ * memory leaks if clients aren't careful.
+ */
void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
Error **errp);
+/**
+ * Complete an implicit struct started earlier.
+ * Must be called after any successful use of visit_start_implicit_struct(),
+ * even if intermediate processing was skipped due to errors.
+ */
void visit_end_implicit_struct(Visitor *v, Error **errp);
+
+/**
+ * Prepare to visit a QList tied to QDict key @name.
+ * @name will be NULL if this is visited as part of a QList.
+ * After calling this, the elements must be collected until
+ * visit_next_list() returns NULL, then visit_end_list() must be
+ * used to complete the visit.
+ */
void visit_start_list(Visitor *v, const char *name, Error **errp);
+/**
+ * Collect the next list member and append it to *@list.
+ * Start with *@list of NULL, then subsequent iterations should pass
+ * *@list pointing to the previous return value. Must be called in a
+ * loop until a NULL return or error occurs; for each non-NULL return,
+ * the caller must then call the appropriate visit_type_*() for the
+ * element type of the list, with that function's name parameter set
+ * to NULL.
+ */
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
+/**
+ * Complete the list started earlier.
+ * Must be called after any successful use of visit_start_list(),
+ * even if intermediate processing was skipped due to errors.
+ */
void visit_end_list(Visitor *v, Error **errp);
+
+/**
+ * Check if an optional member @name of a QDict needs visiting.
+ * For input visitors, set *@present according to whether the
+ * corresponding visit_type_*() needs calling; for other visitors,
+ * leave *@present unchanged.
+ */
void visit_optional(Visitor *v, bool *present, const char *name,
Error **errp);
+
+/**
+ * Determine the qtype of the item @name in the current QDict visit.
+ * For input visitors, set *@type to the correct qtype of a qapi
+ * alternate type; for other visitors, leave *@type unchanged.
+ * If @promote_int, treat integers as numbers.
+ */
void visit_get_next_type(Visitor *v, qtype_code *type, bool promote_int,
const char *name, Error **errp);
+
+/**
+ * Visit an enum value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * For input visitors, parse a string and set *@obj to the numeric value
+ * of the enum type @kind using @strings as the mapping; for output
+ * visitors, reverse the mapping and visit the output string determined
+ * by *@obj.
+ */
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
const char *kind, const char *name, Error **errp);
+
+/**
+ * Visit an integer value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * For input visitors, set *@obj to the parsed value; for other visitors,
+ * leave *@obj unchanged.
+ */
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
-void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
-void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp);
-void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp);
-void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+/**
+ * Visit a uint8_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to uint8_t range.
+ */
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit a uint16_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to uint16_t range.
+ */
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit a uint32_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to uint32_t range.
+ */
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit a uint64_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to uint64_t range
+ * (that is, ensures it is unsigned).
+ */
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit an int8_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to int8_t range.
+ */
void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp);
-void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp);
-void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp);
-void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp);
-void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+/**
+ * Visit an int16_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to int16_t range.
+ */
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit an uint32_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to int32_t range.
+ */
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit an int64_t value tied to @name in the current QDict visit.
+ * Like visit_type_int(), except clamps the value to int64_t range.
+ */
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name,
+ Error **errp);
+/**
+ * Visit a uint64_t value tied to @name in the current QDict visit.
+ * Like visit_type_uint64(), except that some visitors may choose to
+ * recognize additional suffixes for easily scaling input values.
+ */
+void visit_type_size(Visitor *v, uint64_t *obj, const char *name,
+ Error **errp);
+
+/**
+ * Visit a boolean value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj unchanged.
+ */
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
+
+/**
+ * Visit a string value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * @obj must be non-NULL. Input visitors set *@obj to the parsed string;
+ * while output visitors leave *@obj unchanged, except that a NULL *@obj
+ * must be treated the same as "".
+ *
+ * FIXME: Unfortunately not const-correct for output visitors.
+ */
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
-void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
+
+/**
+ * Visit a number value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj unchanged.
+ */
+void visit_type_number(Visitor *v, double *obj, const char *name,
+ Error **errp);
+
+/**
+ * Visit an arbitrary qtype value tied to @name in the current QDict visit.
+ * @name will be NULL if this is visited as part of a QList.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj unchanged.
+ */
void visit_type_any(Visitor *v, QObject **obj, const char *name, Error **errp);
#endif
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 20/29] qapi: Plug leaks in test-qmp-input-visitor
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (18 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 19/29] qapi: Document visitor interfaces Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 21/29] qapi: Test failure in middle of array parse Eric Blake
` (8 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, armbru, DirtY.iCE.hu
Make valgrind happy with the current state of the test, so that
the next patch can more easily expose a memory leak without it
being drowned by noise.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
tests/test-qmp-input-visitor.c | 34 +++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index bba7ab2..67e4d17 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -98,6 +98,7 @@ static void test_visitor_in_int(TestInputVisitorData *data,
visit_type_int(v, &res, NULL, &err);
g_assert(!err);
g_assert_cmpint(res, ==, value);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_int_overflow(TestInputVisitorData *data,
@@ -116,6 +117,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
visit_type_int(v, &res, NULL, &err);
g_assert(err);
error_free(err);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_bool(TestInputVisitorData *data,
@@ -130,6 +132,7 @@ static void test_visitor_in_bool(TestInputVisitorData *data,
visit_type_bool(v, &res, NULL, &err);
g_assert(!err);
g_assert_cmpint(res, ==, true);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_number(TestInputVisitorData *data,
@@ -144,6 +147,7 @@ static void test_visitor_in_number(TestInputVisitorData *data,
visit_type_number(v, &res, NULL, &err);
g_assert(!err);
g_assert_cmpfloat(res, ==, value);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_string(TestInputVisitorData *data,
@@ -160,6 +164,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
g_assert_cmpstr(res, ==, value);
g_free(res);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_enum(TestInputVisitorData *data,
@@ -237,6 +242,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
g_free(p->string);
g_free(p);
+ visitor_input_teardown(data, NULL);
}
static void check_and_free_str(char *str, const char *cmp)
@@ -271,6 +277,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
g_free(udp->dict1->dict2);
g_free(udp->dict1);
g_free(udp);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_list(TestInputVisitorData *data,
@@ -296,6 +303,7 @@ static void test_visitor_in_list(TestInputVisitorData *data,
}
qapi_free_UserDefOneList(head);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_any(TestInputVisitorData *data,
@@ -317,6 +325,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
g_assert(qint);
g_assert_cmpint(qint_get_int(qint), ==, -42);
qobject_decref(res);
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_any(v, &res, NULL, &err);
@@ -339,6 +348,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
g_assert(qstring);
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
qobject_decref(res);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_union_flat(TestInputVisitorData *data,
@@ -361,6 +371,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
g_assert_cmpint(tmp->integer, ==, 41);
g_assert_cmpint(tmp->value1->boolean, ==, true);
qapi_free_UserDefFlatUnion(tmp);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_alternate(TestInputVisitorData *data,
@@ -371,28 +382,28 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
UserDefAlternate *tmp = NULL;
v = visitor_input_test_init(data, "42");
-
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
g_assert_cmpint(tmp->i, ==, 42);
qapi_free_UserDefAlternate(tmp);
tmp = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "'string'");
-
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
g_assert_cmpstr(tmp->s, ==, "string");
qapi_free_UserDefAlternate(tmp);
tmp = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "false");
-
visit_type_UserDefAlternate(v, &tmp, NULL, &err);
g_assert(err);
error_free(err);
err = NULL;
qapi_free_UserDefAlternate(tmp);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_alternate_number(TestInputVisitorData *data,
@@ -414,6 +425,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert(err);
qapi_free_AltOne(one);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42");
visit_type_AltTwo(v, &two, NULL, &error_abort);
@@ -421,6 +433,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpfloat(two->n, ==, 42.0);
qapi_free_AltTwo(two);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42");
visit_type_AltThree(v, &three, NULL, &error_abort);
@@ -428,6 +441,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpfloat(three->n, ==, 42.0);
qapi_free_AltThree(three);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42");
visit_type_AltFour(v, &four, NULL, &error_abort);
@@ -435,6 +449,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpint(four->i, ==, 42);
qapi_free_AltFour(four);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42");
visit_type_AltFive(v, &five, NULL, &error_abort);
@@ -442,6 +457,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpint(five->i, ==, 42);
qapi_free_AltFive(five);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42");
visit_type_AltSix(v, &six, NULL, &error_abort);
@@ -449,6 +465,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpint(six->i, ==, 42);
qapi_free_AltSix(six);
one = NULL;
+ visitor_input_teardown(data, NULL);
/* Parsing a double */
@@ -459,6 +476,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
err = NULL;
qapi_free_AltOne(one);
one = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5");
visit_type_AltTwo(v, &two, NULL, &error_abort);
@@ -466,6 +484,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpfloat(two->n, ==, 42.5);
qapi_free_AltTwo(two);
two = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5");
visit_type_AltThree(v, &three, NULL, &error_abort);
@@ -473,6 +492,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpfloat(three->n, ==, 42.5);
qapi_free_AltThree(three);
three = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5");
visit_type_AltFour(v, &four, NULL, &err);
@@ -481,6 +501,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
err = NULL;
qapi_free_AltFour(four);
four = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5");
visit_type_AltFive(v, &five, NULL, &error_abort);
@@ -488,6 +509,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpfloat(five->n, ==, 42.5);
qapi_free_AltFive(five);
five = NULL;
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5");
visit_type_AltSix(v, &six, NULL, &error_abort);
@@ -495,6 +517,7 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
g_assert_cmpint(six->n, ==, 42.5);
qapi_free_AltSix(six);
six = NULL;
+ visitor_input_teardown(data, NULL);
}
static void test_native_list_integer_helper(TestInputVisitorData *data,
@@ -595,6 +618,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
qapi_free_UserDefNativeListUnion(cvalue);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_native_list_int(TestInputVisitorData *data,
@@ -694,6 +718,7 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
qapi_free_UserDefNativeListUnion(cvalue);
+ visitor_input_teardown(data, NULL);
}
static void test_visitor_in_native_list_string(TestInputVisitorData *data,
@@ -731,6 +756,7 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
qapi_free_UserDefNativeListUnion(cvalue);
+ visitor_input_teardown(data, NULL);
}
#define DOUBLE_STR_MAX 16
@@ -776,6 +802,7 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
qapi_free_UserDefNativeListUnion(cvalue);
+ visitor_input_teardown(data, NULL);
}
static void input_visitor_test_add(const char *testpath,
@@ -804,6 +831,7 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
error_free(err);
g_free(p->string);
g_free(p);
+ visitor_input_teardown(data, NULL);
}
int main(int argc, char **argv)
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 21/29] qapi: Test failure in middle of array parse
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (19 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 20/29] qapi: Plug leaks in test-qmp-input-visitor Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 22/29] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
` (7 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Our generated list visitors have the same problem as has been
mentioned elsewhere (see commit 2f52e20): they allocate data
even on failure. An upcoming patch will correct things to
provide saner guarantees, but first we need to expose the
behavior in the testsuite to ensure we aren't introducing any
memory usage bugs.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-visit.py | 4 ++++
tests/test-qmp-input-visitor.c | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 81527ce..ac19d9d 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -161,6 +161,10 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
def gen_visit_list(name, element_type):
+ # FIXME: if *obj is NULL on entry, and the first visit_next_list()
+ # assigns to *obj, while a later one fails, we should clean up *obj
+ # rather than leaving it non-NULL. As currently written, the caller must
+ # call qapi_free_FOOList() to avoid a memory leak of the partial FOOList.
return mcgen('''
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 67e4d17..03cad64 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -819,6 +819,7 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
TestStruct *p = NULL;
Error *err = NULL;
Visitor *v;
+ strList *q = NULL;
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
@@ -829,9 +830,21 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
g_assert(p->string == NULL);
error_free(err);
+ err = NULL;
g_free(p->string);
g_free(p);
visitor_input_teardown(data, NULL);
+
+ v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
+ /* FIXME - a failed parse should not leave a partially-allocated
+ * array for us to clean up; this could cause callers to leak
+ * memory. */
+ visit_type_strList(v, &q, NULL, &err);
+ assert(q);
+ assert(err);
+ qapi_free_strList(q);
+ error_free(err);
+ visitor_input_teardown(data, NULL);
}
int main(int argc, char **argv)
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 22/29] qapi: Change visit_type_FOO() to no longer return partial objects
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (20 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 21/29] qapi: Test failure in middle of array parse Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 23/29] qapi: Plumb in 'box' to qapi generator lower levels Eric Blake
` (6 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Returning a partial object on error is an invitation for a careless
caller to leak memory. As no one outside the testsuite was actually
relying on these semantics, it is cleaner to just document and
guarantee that ALL visit_type_FOO() functions do not alter *obj
when an error is encountered during an input visitor.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/qapi/visitor.h | 45 +++++++++++++++++++++++++++++------------
qapi/qapi-visit-core.c | 8 ++++++--
scripts/qapi-visit.py | 46 +++++++++++++++++++++++++++++-------------
tests/test-qmp-commands.c | 15 +++++++-------
tests/test-qmp-input-visitor.c | 29 +++++++++++---------------
5 files changed, 89 insertions(+), 54 deletions(-)
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 4ac0c3a..66c0075 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -27,6 +27,26 @@
* scripts/qapi-visit.py. For the visitor callback contracts, see
* visitor-impl.h. */
+/* All qapi types have a corresponding function with a signature
+ * compatible with this:
+ *
+ * void visit_type_FOO(Visitor *v, void *obj, const char *name, Error **errp);
+ *
+ * where *@obj is itself a pointer or a scalar. (The visit functions for
+ * built-in types are declared here, while the functions for qapi-defined
+ * struct, union, enum, and list types are generated; see qapi-visit.h).
+ * Input visitors populate *@obj on success, and leave it unchanged on
+ * failure.
+ *
+ * Additionally, all qapi structs have a generated function compatible
+ * with this:
+ *
+ * void qapi_free_FOO(void *obj);
+ *
+ * which behaves like free(), even if @obj is NULL or was only partially
+ * allocated before encountering an error.
+ */
+
/* This struct is layout-compatible with all other *List structs
* created by the qapi generator. */
typedef struct GenericList
@@ -46,12 +66,12 @@ typedef struct GenericList
* input visitor, @obj can be NULL to validate that the visit will
* succeed; otherwise, *@obj is assigned with an allocation of @size
* bytes. For other visitors, *@obj is the object to visit. Set *@errp
- * on failure.
- *
- * FIXME: *@obj can be modified even on error; this can lead to
- * memory leaks if clients aren't careful.
+ * on failure. Returns true if *@obj was allocated; if that happens,
+ * and an error occurs any time before the matching visit_end_struct(),
+ * then the caller (usually a visit_type_FOO() function) knows to undo
+ * the allocation before returning control further.
*/
-void visit_start_struct(Visitor *v, void **obj, const char *kind,
+bool visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
/**
* Complete a struct started earlier.
@@ -62,14 +82,11 @@ void visit_end_struct(Visitor *v, Error **errp);
/**
* Prepare to visit an implicit struct.
- * Similar to visit_start_struct(), except that this will visit a
- * C pointer pointing to @size bytes, and where the QDict fields are
- * part of the parent object.
- *
- * FIXME: *@obj can be modified even on error; this can lead to
- * memory leaks if clients aren't careful.
+ * Similar to visit_start_struct(), including return semantics, except
+ * that this will visit a C pointer pointing to @size bytes, and where
+ * the QDict fields are part of the parent object.
*/
-void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
+bool visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
Error **errp);
/**
* Complete an implicit struct started earlier.
@@ -93,7 +110,9 @@ void visit_start_list(Visitor *v, const char *name, Error **errp);
* loop until a NULL return or error occurs; for each non-NULL return,
* the caller must then call the appropriate visit_type_*() for the
* element type of the list, with that function's name parameter set
- * to NULL.
+ * to NULL. If an error occurs, then the caller (usually a
+ * visit_type_FOO() function) knows to undo the list allocat04ion before
+ * returning control further.
*/
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
/**
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 6d8ea95..9cd17f8 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -17,10 +17,12 @@
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
-void visit_start_struct(Visitor *v, void **obj, const char *kind,
+bool visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp)
{
+ bool track_allocation = obj && !*obj;
v->start_struct(v, obj, kind, name, size, errp);
+ return track_allocation && *obj;
}
void visit_end_struct(Visitor *v, Error **errp)
@@ -28,12 +30,14 @@ void visit_end_struct(Visitor *v, Error **errp)
v->end_struct(v, errp);
}
-void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
+bool visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
Error **errp)
{
+ bool track_allocation = obj && !*obj;
if (v->start_implicit_struct) {
v->start_implicit_struct(v, obj, size, errp);
}
+ return track_allocation && *obj;
}
void visit_end_implicit_struct(Visitor *v, Error **errp)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index ac19d9d..9642c24 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -48,14 +48,19 @@ static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **e
static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp)
{
Error *err = NULL;
+ bool allocated;
- visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
+ allocated = visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
if (!err) {
if (!obj || *obj) {
visit_type_%(c_type)s_fields(m, obj, &err);
}
visit_end_implicit_struct(m, err ? NULL : &err);
}
+ if (allocated && err) {
+ g_free(*obj);
+ *obj = NULL;
+ }
error_propagate(errp, err);
}
''',
@@ -135,23 +140,24 @@ out:
def gen_visit_struct(name, base, members):
ret = gen_visit_struct_fields(name, base, members)
- # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
- # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
- # rather than leaving it non-NULL. As currently written, the caller must
- # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
ret += mcgen('''
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
+ bool allocated;
- visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
+ allocated = visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
if (!err) {
if (*obj) {
visit_type_%(c_name)s_fields(m, obj, &err);
}
visit_end_struct(m, err ? NULL : &err);
}
+ if (allocated && err) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
error_propagate(errp, err);
}
''',
@@ -161,16 +167,13 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
def gen_visit_list(name, element_type):
- # FIXME: if *obj is NULL on entry, and the first visit_next_list()
- # assigns to *obj, while a later one fails, we should clean up *obj
- # rather than leaving it non-NULL. As currently written, the caller must
- # call qapi_free_FOOList() to avoid a memory leak of the partial FOOList.
return mcgen('''
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
GenericList *i, **prev;
+ bool allocated = obj && !*obj;
visit_start_list(m, name, &err);
if (err) {
@@ -186,6 +189,10 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
visit_end_list(m, err ? NULL : &err);
out:
+ if (allocated && err) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
error_propagate(errp, err);
}
''',
@@ -214,8 +221,9 @@ def gen_visit_alternate(name, variants):
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
+ bool allocated;
- visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_name)s), &err);
+ allocated = visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_name)s), &err);
if (err) {
goto out;
}
@@ -244,11 +252,15 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
}
out_obj:
visit_end_implicit_struct(m, err ? NULL : &err);
+ if (allocated && err) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}
''',
- name=name)
+ name=name, c_name=c_name(name))
return ret
@@ -270,8 +282,9 @@ def gen_visit_union(name, base, variants):
void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
+ bool allocated;
- visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
+ allocated = visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
if (err) {
goto out;
}
@@ -331,10 +344,15 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
}
out_obj:
visit_end_struct(m, err ? NULL : &err);
+ if (allocated && err) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}
-''')
+''',
+ c_name=c_name(name))
return ret
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 5181823..89a3b47 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -218,15 +218,14 @@ static void test_dealloc_partial(void)
QDECREF(ud2_dict);
}
- /* verify partial success */
- assert(ud2 != NULL);
- assert(ud2->string0 != NULL);
- assert(strcmp(ud2->string0, text) == 0);
- assert(ud2->dict1 == NULL);
-
- /* confirm & release construction error */
- assert(err != NULL);
+ /* verify that visit_type_XXX() cleans up properly on error */
+ assert(err);
error_free(err);
+ assert(!ud2);
+
+ /* Manually create a partial object, leaving ud2->dict1 at NULL */
+ ud2 = g_new0(UserDefTwo, 1);
+ ud2->string0 = g_strdup(text);
/* tear down partial object */
qapi_free_UserDefTwo(ud2);
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 03cad64..2da1b8b 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -201,9 +201,10 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
+ bool allocated;
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- &err);
+ allocated = visit_start_struct(v, (void **)obj, "TestStruct", name,
+ sizeof(TestStruct), &err);
if (err) {
goto out;
}
@@ -218,9 +219,12 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
visit_type_str(v, &(*obj)->string, "string", &err);
out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
+ visit_end_struct(v, err ? NULL : &err);
+ if (allocated && err) {
+ g_free((*obj)->string);
+ g_free(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}
@@ -825,24 +829,15 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
visit_type_TestStruct(v, &p, NULL, &err);
g_assert(err);
- /* FIXME - a failed parse should not leave a partially-allocated p
- * for us to clean up; this could cause callers to leak memory. */
- g_assert(p->string == NULL);
-
+ g_assert(!p);
error_free(err);
err = NULL;
- g_free(p->string);
- g_free(p);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
- /* FIXME - a failed parse should not leave a partially-allocated
- * array for us to clean up; this could cause callers to leak
- * memory. */
visit_type_strList(v, &q, NULL, &err);
- assert(q);
- assert(err);
- qapi_free_strList(q);
+ g_assert(!q);
+ g_assert(err);
error_free(err);
visitor_input_teardown(data, NULL);
}
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 23/29] qapi: Plumb in 'box' to qapi generator lower levels
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (21 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 22/29] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 24/29] qapi: Implement boxed structs for commands/events Eric Blake
` (5 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
A future patch will add support for passing a qapi union
type as the 'data' of a command. But to do that, the user
function for implementing the command, as called by the
generated marshal command, must take the corresponding C
struct as a single boxed pointer, rather than a breakdown
into one parameter per member. This patch adds the
internal plubming of a 'box' flag associated with each
command and event. For this patch, no behavior changes,
other than the testsuite outputting the value of the new
flag (always False for now).
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-commands.py | 93 ++++++++++++++++++---------------
scripts/qapi-event.py | 64 +++++++++++++----------
scripts/qapi-introspect.py | 4 +-
scripts/qapi.py | 52 +++++++++++-------
tests/qapi-schema/args-member-array.out | 2 +-
tests/qapi-schema/event-case.out | 1 +
tests/qapi-schema/ident-with-escape.out | 2 +-
tests/qapi-schema/indented-expr.out | 4 +-
tests/qapi-schema/qapi-schema-test.out | 17 +++---
tests/qapi-schema/returns-int.out | 2 +-
tests/qapi-schema/test-qapi.py | 8 +--
11 files changed, 142 insertions(+), 107 deletions(-)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 810a897..ed4b38f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -16,13 +16,13 @@ from qapi import *
import re
-def gen_command_decl(name, arg_type, ret_type):
+def gen_command_decl(name, arg_type, box, 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, box, 'Error **errp'))
def gen_err_check(err):
@@ -36,15 +36,18 @@ if (%(err)s) {
err=err)
-def gen_call(name, arg_type, ret_type):
+def gen_call(name, arg_type, box, ret_type):
ret = ''
argstr = ''
- if arg_type:
- for memb in arg_type.members:
- if memb.optional:
- argstr += 'has_%s, ' % c_name(memb.name)
- argstr += '%s, ' % c_name(memb.name)
+ if box:
+ assert False # not implemented
+ else:
+ if arg_type:
+ for memb in arg_type.members:
+ if memb.optional:
+ argstr += 'has_%s, ' % c_name(memb.name)
+ argstr += '%s, ' % c_name(memb.name)
lhs = ''
if ret_type:
@@ -67,7 +70,7 @@ qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
return ret
-def gen_marshal_vars(arg_type, ret_type):
+def gen_marshal_vars(arg_type, box, ret_type):
ret = mcgen('''
Error *local_err = NULL;
''')
@@ -87,18 +90,21 @@ QapiDeallocVisitor *md;
Visitor *v;
''')
- for memb in arg_type.members:
- if memb.optional:
- ret += mcgen('''
+ if box:
+ assert False # not implemented
+ else:
+ for memb in arg_type.members:
+ if memb.optional:
+ ret += mcgen('''
bool has_%(c_name)s = false;
''',
- c_name=c_name(memb.name))
- ret += mcgen('''
+ c_name=c_name(memb.name))
+ ret += mcgen('''
%(c_type)s %(c_name)s = %(c_null)s;
''',
- c_name=c_name(memb.name),
- c_type=memb.type.c_type(),
- c_null=memb.type.c_null())
+ c_name=c_name(memb.name),
+ c_type=memb.type.c_type(),
+ c_null=memb.type.c_null())
ret += '\n'
else:
ret += mcgen('''
@@ -110,7 +116,7 @@ bool has_%(c_name)s = false;
return ret
-def gen_marshal_input_visit(arg_type, dealloc=False):
+def gen_marshal_input_visit(arg_type, box, dealloc=False):
ret = ''
if not arg_type:
@@ -133,28 +139,31 @@ v = qapi_dealloc_get_visitor(md);
v = qmp_input_get_visitor(mi);
''')
- for memb in arg_type.members:
- if memb.optional:
- ret += mcgen('''
+ if box:
+ assert False # not implemented
+ else:
+ for memb in arg_type.members:
+ if memb.optional:
+ ret += mcgen('''
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
''',
- c_name=c_name(memb.name), name=memb.name,
- errp=errparg)
- ret += gen_err_check(errarg)
- ret += mcgen('''
+ c_name=c_name(memb.name), name=memb.name,
+ errp=errparg)
+ ret += gen_err_check(errarg)
+ ret += mcgen('''
if (has_%(c_name)s) {
''',
- c_name=c_name(memb.name))
- push_indent()
- ret += mcgen('''
+ c_name=c_name(memb.name))
+ push_indent()
+ ret += mcgen('''
visit_type_%(c_type)s(v, &%(c_name)s, "%(name)s", %(errp)s);
''',
- c_name=c_name(memb.name), name=memb.name,
- c_type=memb.type.c_name(), errp=errparg)
- ret += gen_err_check(errarg)
- if memb.optional:
- pop_indent()
- ret += mcgen('''
+ c_name=c_name(memb.name), name=memb.name,
+ c_type=memb.type.c_name(), errp=errparg)
+ ret += gen_err_check(errarg)
+ if memb.optional:
+ pop_indent()
+ ret += mcgen('''
}
''')
@@ -209,7 +218,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, box, ret_type):
ret = mcgen('''
%(proto)s
@@ -217,9 +226,9 @@ def gen_marshal(name, arg_type, ret_type):
''',
proto=gen_marshal_proto(name))
- ret += gen_marshal_vars(arg_type, ret_type)
- ret += gen_marshal_input_visit(arg_type)
- ret += gen_call(name, arg_type, ret_type)
+ ret += gen_marshal_vars(arg_type, box, ret_type)
+ ret += gen_marshal_input_visit(arg_type, box)
+ ret += gen_call(name, arg_type, box, ret_type)
if re.search('^ *goto out;', ret, re.MULTILINE):
ret += mcgen('''
@@ -229,7 +238,7 @@ out:
ret += mcgen('''
error_propagate(errp, local_err);
''')
- ret += gen_marshal_input_visit(arg_type, dealloc=True)
+ ret += gen_marshal_input_visit(arg_type, box, dealloc=True)
ret += mcgen('''
}
''')
@@ -286,16 +295,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, box):
if not gen:
return
- self.decl += gen_command_decl(name, arg_type, ret_type)
+ self.decl += gen_command_decl(name, arg_type, box, 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, box, 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 d15fad9..c333d05 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -14,21 +14,21 @@
from qapi import *
-def gen_event_send_proto(name, arg_type):
+def gen_event_send_proto(name, arg_type, box):
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, box, 'Error **errp')}
-def gen_event_send_decl(name, arg_type):
+def gen_event_send_decl(name, arg_type, box):
return mcgen('''
%(proto)s;
''',
- proto=gen_event_send_proto(name, arg_type))
+ proto=gen_event_send_proto(name, arg_type, box))
-def gen_event_send(name, arg_type):
+def gen_event_send(name, arg_type, box):
ret = mcgen('''
%(proto)s
@@ -37,7 +37,7 @@ def gen_event_send(name, arg_type):
Error *local_err = NULL;
QMPEventFuncEmit emit;
''',
- proto=gen_event_send_proto(name, arg_type))
+ proto=gen_event_send_proto(name, arg_type, box))
if arg_type and arg_type.members:
ret += mcgen('''
@@ -66,6 +66,12 @@ def gen_event_send(name, arg_type):
v = qmp_output_get_visitor(qov);
g_assert(v);
+''')
+
+ if box:
+ assert False # not implemented
+ else:
+ ret += mcgen('''
/* Fake visit, as if all members are under a structure */
visit_start_struct(v, NULL, "", "%(name)s", 0, &local_err);
if (local_err) {
@@ -73,40 +79,40 @@ def gen_event_send(name, arg_type):
}
''',
- name=name)
+ name=name)
- for memb in arg_type.members:
- if memb.optional:
- ret += mcgen('''
+ for memb in arg_type.members:
+ if memb.optional:
+ ret += mcgen('''
if (has_%(c_name)s) {
''',
- c_name=c_name(memb.name))
- push_indent()
+ c_name=c_name(memb.name))
+ push_indent()
- # Ugly: need to cast away the const
- if memb.type.name == "str":
- cast = '(char **)'
- else:
- cast = ''
+ # Ugly: need to cast away the const
+ if memb.type.name == "str":
+ cast = '(char **)'
+ else:
+ cast = ''
- ret += mcgen('''
+ ret += mcgen('''
visit_type_%(c_type)s(v, %(cast)s&%(c_name)s, "%(name)s", &local_err);
if (local_err) {
goto clean;
}
''',
- cast=cast,
- c_name=c_name(memb.name),
- c_type=memb.type.c_name(),
- name=memb.name)
+ cast=cast,
+ c_name=c_name(memb.name),
+ c_type=memb.type.c_name(),
+ name=memb.name)
- if memb.optional:
- pop_indent()
- ret += mcgen('''
+ if memb.optional:
+ pop_indent()
+ ret += mcgen('''
}
''')
- ret += mcgen('''
+ ret += mcgen('''
visit_end_struct(v, &local_err);
if (local_err) {
@@ -154,9 +160,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, box):
+ self.decl += gen_event_send_decl(name, arg_type, box)
+ self.defn += gen_event_send(name, arg_type, box)
self._event_names.append(name)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index eef5f1d..64069ad 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -151,14 +151,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, box):
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, box):
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.py b/scripts/qapi.py
index 475d2c2..b407779 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -798,10 +798,10 @@ class QAPISchemaVisitor(object):
pass
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
pass
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, box):
pass
@@ -1036,7 +1036,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
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,
+ box):
QAPISchemaEntity.__init__(self, name, info)
assert not arg_type or isinstance(arg_type, str)
assert not ret_type or isinstance(ret_type, str)
@@ -1046,12 +1047,14 @@ class QAPISchemaCommand(QAPISchemaEntity):
self.ret_type = None
self.gen = gen
self.success_response = success_response
+ self.box = box
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
+ if not self.box:
+ assert not self.arg_type.variants
if self._ret_type_name:
self.ret_type = schema.lookup_type(self._ret_type_name)
assert isinstance(self.ret_type, QAPISchemaType)
@@ -1059,24 +1062,26 @@ 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.box)
class QAPISchemaEvent(QAPISchemaEntity):
- def __init__(self, name, info, arg_type):
+ def __init__(self, name, info, arg_type, box):
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.box = box
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
+ if not self.box:
+ assert not self.arg_type.variants
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.box)
class QAPISchema(object):
@@ -1232,22 +1237,24 @@ class QAPISchema(object):
rets = expr.get('returns')
gen = expr.get('gen', True)
success_response = expr.get('success-response', True)
- if isinstance(data, OrderedDict):
+ box = expr.get('box', False)
+ if isinstance(data, dict):
data = self._make_implicit_object_type(name, 'arg',
self._make_members(data))
if isinstance(rets, list):
assert len(rets) == 1
rets = self._make_array_type(rets[0])
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
- success_response))
+ success_response, box))
def _def_event(self, expr, info):
name = expr['event']
data = expr.get('data')
- if isinstance(data, OrderedDict):
+ box = expr.get('box', False)
+ if isinstance(data, dict):
data = self._make_implicit_object_type(name, 'arg',
self._make_members(data))
- self._def_entity(QAPISchemaEvent(name, info, data))
+ self._def_entity(QAPISchemaEvent(name, info, data, box))
def _def_exprs(self):
for expr_elem in self.exprs:
@@ -1471,18 +1478,23 @@ extern const char *const %(c_name)s_lookup[];
c_name=c_name(name))
return ret
-def gen_params(arg_type, extra):
+
+def gen_params(arg_type, box, extra):
if not arg_type:
return extra
- assert not arg_type.variants
ret = ''
sep = ''
- 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_type(is_param=True), c_name(memb.name))
+ if box:
+ assert False # not implemented
+ 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_type(is_param=True),
+ c_name(memb.name))
if extra:
ret += sep + extra
return ret
diff --git a/tests/qapi-schema/args-member-array.out b/tests/qapi-schema/args-member-array.out
index b3b92df..f5dc409 100644
--- a/tests/qapi-schema/args-member-array.out
+++ b/tests/qapi-schema/args-member-array.out
@@ -6,4 +6,4 @@ enum abc ['a', 'b', 'c']
object def
member array: abcList optional=False
command okay :obj-okay-arg -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index cdfd264..97a682a 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,2 +1,3 @@
object :empty
event oops None
+ box=False
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index f4542b1..2381c33 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -2,4 +2,4 @@ object :empty
object :obj-fooA-arg
member bar1: str optional=False
command fooA :obj-fooA-arg -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index 226d300..f5d2695 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,5 +1,5 @@
object :empty
command eins None -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command zwei None -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index b6e423e..6f775e5 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -72,9 +72,13 @@ alternate AltTwo
case s: str
case n: number
event EVENT_A None
+ box=False
event EVENT_B None
+ box=False
event EVENT_C :obj-EVENT_C-arg
+ box=False
event EVENT_D :obj-EVENT_D-arg
+ box=False
enum EnumOne ['value1', 'value2', 'value3']
object EventStructOne
member struct1: UserDefOne optional=False
@@ -152,6 +156,7 @@ object UserDefUnionBase
object UserDefZero
member integer: int optional=False
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+ box=False
alternate __org.qemu_x-Alt
case __org.qemu_x-branch: str
case b: __org.qemu_x-Base
@@ -172,14 +177,14 @@ object __org.qemu_x-Union2
tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union1
- gen=True success_response=True
+ gen=True success_response=True box=False
command guest-sync :obj-guest-sync-arg -> any
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd None -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd1 :obj-user_def_cmd1-arg -> None
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd2 :obj-user_def_cmd2-arg -> UserDefTwo
- gen=True success_response=True
+ gen=True success_response=True box=False
command user_def_cmd3 :obj-user_def_cmd3-arg -> int
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/returns-int.out b/tests/qapi-schema/returns-int.out
index a2da259..911212d 100644
--- a/tests/qapi-schema/returns-int.out
+++ b/tests/qapi-schema/returns-int.out
@@ -1,3 +1,3 @@
object :empty
command guest-get-time None -> int
- gen=True success_response=True
+ gen=True success_response=True box=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 75f8da8..9811103 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -34,13 +34,15 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, box):
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 box=%s' % (gen, success_response,
+ box)
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, box):
print 'event %s %s' % (name, arg_type and arg_type.name)
+ print ' box=%s' % box
@staticmethod
def _print_variants(variants):
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 24/29] qapi: Implement boxed structs for commands/events
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (22 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 23/29] qapi: Plumb in 'box' to qapi generator lower levels Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 25/29] qapi: Support boxed unions Eric Blake
` (4 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Turn on the ability to pass command and event arguments in
a single boxed parameter. This patch merely tests the use
of the feature on structs. With this patch, we still reject
union types, and crash on { 'command':'foo', 'data': {
anonymous...}, 'box':true }; that will be addressed in the
next patch.
While this does not alter any QMP commands, it opens the door
for clients to turn on boxing to receive a single pointer
parameter of the overall struct instead of a series of
parameters for each member of the struct; which will be
useful for commands whose argument struct has lots of members.
The generated code is slightly reorganized for convenience.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
docs/qapi-code-gen.txt | 24 ++++++++++++++++++++++--
scripts/qapi-commands.py | 14 +++++++++++---
scripts/qapi-event.py | 13 +++++++++++--
scripts/qapi.py | 11 ++++++++---
tests/qapi-schema/qapi-schema-test.json | 2 ++
tests/qapi-schema/qapi-schema-test.out | 4 ++++
tests/test-qmp-commands.c | 4 ++++
7 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index ff57010..a12a7f6 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -396,7 +396,7 @@ following example objects:
=== Commands ===
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
- '*returns': TYPE-NAME,
+ '*returns': TYPE-NAME, '*box': true,
'*gen': false, '*success-response': false }
Commands are defined by using a dictionary containing several members,
@@ -447,6 +447,17 @@ which would validate this Client JSON Protocol transaction:
=> { "execute": "my-second-command" }
<= { "return": [ { "value": "one" }, { } ] }
+By default, the generator creates a marshalling function that converts
+an input QDict into a function call implemented by the user, and
+declares a prototype for the user's function which has a parameter for
+each member of the argument struct, including boolean arguments that
+describe whether optional arguments were provided. But if the QAPI
+description includes the key 'box' with the boolean value true, the
+user call prototype will have only a single parameter for the overall
+generated C structure. The 'box' key is required in order to use a
+union as an input argument, since it is not possible to list all
+members of the union as separate parameters.
+
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
@@ -470,7 +481,8 @@ use of this field.
=== Events ===
-Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT }
+Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
+ '*box': 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
@@ -491,6 +503,14 @@ Resulting in this JSON object:
"data": { "b": "test string" },
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+By default, the generator creates a C function that takes as
+parameters each member of the argument struct and turns it into the
+appropriate JSON Client event. But if the QAPI description includes
+the key 'box' with the boolean value true, the event function will
+have only a single parameter for the overall generated C structure.
+The 'box' key is required in order to use a union as the data key,
+since it is not possible to list all members of the union as separate
+parameters.
== Client JSON Protocol introspection ==
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index ed4b38f..2a98cca 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -41,7 +41,7 @@ def gen_call(name, arg_type, box, ret_type):
argstr = ''
if box:
- assert False # not implemented
+ argstr = 'arg, '
else:
if arg_type:
for memb in arg_type.members:
@@ -91,7 +91,10 @@ Visitor *v;
''')
if box:
- assert False # not implemented
+ ret += mcgen('''
+%(c_type)s arg = %(c_null)s;
+''',
+ c_type=arg_type.c_type(), c_null=arg_type.c_null())
else:
for memb in arg_type.members:
if memb.optional:
@@ -140,7 +143,12 @@ v = qmp_input_get_visitor(mi);
''')
if box:
- assert False # not implemented
+ ret += mcgen('''
+visit_type_%(c_name)s(v, &arg, NULL, %(errp)s);
+
+''',
+ c_name=arg_type.c_name(), errp=errparg)
+ ret += gen_err_check(errarg)
else:
for memb in arg_type.members:
if memb.optional:
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index c333d05..89d2e8d 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -40,10 +40,13 @@ def gen_event_send(name, arg_type, box):
proto=gen_event_send_proto(name, arg_type, box))
if arg_type and arg_type.members:
+ if not box:
+ ret += mcgen('''
+ QObject *obj;
+''')
ret += mcgen('''
QmpOutputVisitor *qov;
Visitor *v;
- QObject *obj;
''')
@@ -69,7 +72,13 @@ def gen_event_send(name, arg_type, box):
''')
if box:
- assert False # not implemented
+ ret += mcgen('''
+ visit_type_%(c_name)s(v, &arg, NULL, &local_err);
+ if (local_err) {
+ goto clean;
+ }
+''',
+ c_name=arg_type.c_name(), name=arg_type.name)
else:
ret += mcgen('''
/* Fake visit, as if all members are under a structure */
diff --git a/scripts/qapi.py b/scripts/qapi.py
index b407779..92e9e74 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -679,6 +679,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 == 'box' and value != True:
+ raise QAPIExprError(info,
+ "'%s' of %s '%s' should only use true value"
+ % (key, meta, name))
for key in required:
if not expr.has_key(key):
raise QAPIExprError(info,
@@ -709,10 +713,10 @@ def check_exprs(exprs):
add_struct(expr, info)
elif expr.has_key('command'):
check_keys(expr_elem, 'command', [],
- ['data', 'returns', 'gen', 'success-response'])
+ ['data', 'returns', 'gen', 'success-response', 'box'])
add_name(expr['command'], info, 'command')
elif expr.has_key('event'):
- check_keys(expr_elem, 'event', [], ['data'])
+ check_keys(expr_elem, 'event', [], ['data', 'box'])
add_name(expr['event'], info, 'event')
else:
raise QAPIExprError(expr_elem['info'],
@@ -1485,7 +1489,8 @@ def gen_params(arg_type, box, extra):
ret = ''
sep = ''
if box:
- assert False # not implemented
+ ret += '%s arg' % arg_type.c_type(is_param=True)
+ sep = ', '
else:
assert not arg_type.variants
for memb in arg_type.members:
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index a6321ec..92fc178 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -94,6 +94,7 @@
'returns': 'int' }
# note: command name 'guest-sync' chosen to avoid "cannot use built-in" error
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
+{ 'command': 'boxed', 'box': true, 'data': 'UserDefZero' }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:
@@ -121,6 +122,7 @@
'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
{ 'event': 'EVENT_D',
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
+{ 'event': 'EVENT_E', 'box': true, 'data': 'UserDefZero' }
# test that we correctly compile downstream extensions
{ 'enum': '__org.qemu_x-Enum', 'data': [ '__org.qemu_x-value' ] }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 6f775e5..734cd76 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -79,6 +79,8 @@ event EVENT_C :obj-EVENT_C-arg
box=False
event EVENT_D :obj-EVENT_D-arg
box=False
+event EVENT_E UserDefZero
+ box=True
enum EnumOne ['value1', 'value2', 'value3']
object EventStructOne
member struct1: UserDefOne optional=False
@@ -178,6 +180,8 @@ object __org.qemu_x-Union2
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union1
gen=True success_response=True box=False
+command boxed UserDefZero -> None
+ gen=True success_response=True box=True
command guest-sync :obj-guest-sync-arg -> any
gen=True success_response=True box=False
command user_def_cmd None -> None
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 89a3b47..a190f31 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -54,6 +54,10 @@ QObject *qmp_guest_sync(QObject *arg, Error **errp)
return arg;
}
+void qmp_boxed(UserDefZero *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,
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 25/29] qapi: Support boxed unions
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (23 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 24/29] qapi: Implement boxed structs for commands/events Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 26/29] qapi: Clean up qapi.py per pep8 Eric Blake
` (3 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
This patch completes support for boxed types, by allowing
union types to be used when 'box':true is specified. It also
avoids a python crash when attempting to use boxing on an
anonymous type. While it was possible to support 'box':true
on an empty event, it was easier to just reject missing 'data'
for commands. Add some tests to cover new error messages, as
well as enhancing qapi-schema-test to cover situations that
are now valid.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi.py | 22 +++++++++++++++++-----
tests/Makefile | 5 ++---
tests/qapi-schema/args-bad-box.err | 1 +
tests/qapi-schema/args-bad-box.exit | 1 +
tests/qapi-schema/args-bad-box.json | 2 ++
tests/qapi-schema/args-bad-box.out | 0
tests/qapi-schema/args-box-anon.err | 1 +
tests/qapi-schema/args-box-anon.exit | 1 +
tests/qapi-schema/args-box-anon.json | 2 ++
tests/qapi-schema/args-box-anon.out | 0
tests/qapi-schema/args-box-empty.err | 1 +
tests/qapi-schema/args-box-empty.exit | 1 +
tests/qapi-schema/args-box-empty.json | 2 ++
tests/qapi-schema/args-box-empty.out | 0
tests/qapi-schema/args-union.err | 2 +-
tests/qapi-schema/args-union.json | 3 +--
tests/qapi-schema/qapi-schema-test.json | 3 ++-
tests/qapi-schema/qapi-schema-test.out | 4 +++-
tests/test-qmp-commands.c | 4 ++++
19 files changed, 42 insertions(+), 13 deletions(-)
create mode 100644 tests/qapi-schema/args-bad-box.err
create mode 100644 tests/qapi-schema/args-bad-box.exit
create mode 100644 tests/qapi-schema/args-bad-box.json
create mode 100644 tests/qapi-schema/args-bad-box.out
create mode 100644 tests/qapi-schema/args-box-anon.err
create mode 100644 tests/qapi-schema/args-box-anon.exit
create mode 100644 tests/qapi-schema/args-box-anon.json
create mode 100644 tests/qapi-schema/args-box-anon.out
create mode 100644 tests/qapi-schema/args-box-empty.err
create mode 100644 tests/qapi-schema/args-box-empty.exit
create mode 100644 tests/qapi-schema/args-box-empty.json
create mode 100644 tests/qapi-schema/args-box-empty.out
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 92e9e74..181d40f 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -492,10 +492,18 @@ def check_member_clash(expr_info, base_name, data, source = ""):
def check_command(expr, expr_info):
name = expr['command']
+ box = expr.get('box', False)
+ args_meta = ['struct']
+ if box:
+ args_meta += ['union']
+ if not expr.get('data'):
+ raise QAPIExprError(expr_info,
+ "Use of 'box' requires 'data' for command '%s'"
+ % name)
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 box, allow_optional=True,
+ allow_metas=args_meta)
returns_meta = ['union', 'struct']
if name in returns_whitelist:
returns_meta += ['built-in', 'alternate', 'enum']
@@ -506,13 +514,17 @@ def check_command(expr, expr_info):
def check_event(expr, expr_info):
global events
name = expr['event']
+ box = expr.get('box', False)
+ meta = ['struct']
+ if box:
+ meta += ['union']
if name.upper() == 'MAX':
raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
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 box, allow_optional=True,
+ allow_metas=meta)
def check_union(expr, expr_info):
name = expr['union']
@@ -1488,7 +1500,7 @@ def gen_params(arg_type, box, extra):
return extra
ret = ''
sep = ''
- if box:
+ if box and arg_type.members:
ret += '%s arg' % arg_type.c_type(is_param=True)
sep = ', '
else:
diff --git a/tests/Makefile b/tests/Makefile
index d1d647f..ebc6809 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -229,12 +229,11 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
bad-type-dict.json double-data.json unknown-expr-key.json \
redefined-type.json redefined-command.json redefined-builtin.json \
redefined-event.json command-int.json bad-data.json event-max.json \
- type-bypass-bad-gen.json \
- args-invalid.json \
+ type-bypass-bad-gen.json args-invalid.json args-bad-box.json \
args-array-empty.json args-array-unknown.json args-int.json \
args-unknown.json args-member-unknown.json args-member-array.json \
args-member-array-bad.json args-alternate.json args-union.json \
- args-any.json \
+ args-any.json args-box-anon.json args-box-empty.json \
returns-array-bad.json returns-int.json returns-dict.json \
returns-unknown.json returns-alternate.json returns-whitelist.json \
missing-colon.json missing-comma-list.json missing-comma-object.json \
diff --git a/tests/qapi-schema/args-bad-box.err b/tests/qapi-schema/args-bad-box.err
new file mode 100644
index 0000000..16afe3c
--- /dev/null
+++ b/tests/qapi-schema/args-bad-box.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-bad-box.json:2: 'box' of command 'foo' should only use true value
diff --git a/tests/qapi-schema/args-bad-box.exit b/tests/qapi-schema/args-bad-box.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/args-bad-box.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-bad-box.json b/tests/qapi-schema/args-bad-box.json
new file mode 100644
index 0000000..8d5737a
--- /dev/null
+++ b/tests/qapi-schema/args-bad-box.json
@@ -0,0 +1,2 @@
+# 'box' should only appear with value true
+{ 'command': 'foo', 'box': false }
diff --git a/tests/qapi-schema/args-bad-box.out b/tests/qapi-schema/args-bad-box.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/args-box-anon.err b/tests/qapi-schema/args-box-anon.err
new file mode 100644
index 0000000..11eaefc
--- /dev/null
+++ b/tests/qapi-schema/args-box-anon.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-box-anon.json:2: 'data' for command 'foo' should be a type name
diff --git a/tests/qapi-schema/args-box-anon.exit b/tests/qapi-schema/args-box-anon.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/args-box-anon.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-box-anon.json b/tests/qapi-schema/args-box-anon.json
new file mode 100644
index 0000000..947e3c6
--- /dev/null
+++ b/tests/qapi-schema/args-box-anon.json
@@ -0,0 +1,2 @@
+# 'box' can only be used with named types
+{ 'command': 'foo', 'box': true, 'data': { 'string': 'str' } }
diff --git a/tests/qapi-schema/args-box-anon.out b/tests/qapi-schema/args-box-anon.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/args-box-empty.err b/tests/qapi-schema/args-box-empty.err
new file mode 100644
index 0000000..574c8b5
--- /dev/null
+++ b/tests/qapi-schema/args-box-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-box-empty.json:2: Use of 'box' requires 'data' for command 'foo'
diff --git a/tests/qapi-schema/args-box-empty.exit b/tests/qapi-schema/args-box-empty.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/args-box-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-box-empty.json b/tests/qapi-schema/args-box-empty.json
new file mode 100644
index 0000000..31dca5e
--- /dev/null
+++ b/tests/qapi-schema/args-box-empty.json
@@ -0,0 +1,2 @@
+# 'box' can only be used with named types
+{ 'command': 'foo', 'box': true }
diff --git a/tests/qapi-schema/args-box-empty.out b/tests/qapi-schema/args-box-empty.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err
index 1d693d7..f8ad223 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 7bdcbb7..c0ce091 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 'box':true
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
{ 'command': 'oops', 'data': 'Uni' }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 92fc178..585bc0e 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -95,6 +95,7 @@
# note: command name 'guest-sync' chosen to avoid "cannot use built-in" error
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
{ 'command': 'boxed', 'box': true, 'data': 'UserDefZero' }
+{ 'command': 'boxed2', 'data': 'UserDefNativeListUnion', 'box': true }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:
@@ -115,7 +116,7 @@
{ 'struct': 'EventStructOne',
'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
-{ 'event': 'EVENT_A' }
+{ 'event': 'EVENT_A', 'box': true }
{ 'event': 'EVENT_B',
'data': { } }
{ 'event': 'EVENT_C',
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 734cd76..4127b86 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -72,7 +72,7 @@ alternate AltTwo
case s: str
case n: number
event EVENT_A None
- box=False
+ box=True
event EVENT_B None
box=False
event EVENT_C :obj-EVENT_C-arg
@@ -182,6 +182,8 @@ command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union
gen=True success_response=True box=False
command boxed UserDefZero -> None
gen=True success_response=True box=True
+command boxed2 UserDefNativeListUnion -> None
+ gen=True success_response=True box=True
command guest-sync :obj-guest-sync-arg -> any
gen=True success_response=True box=False
command user_def_cmd None -> None
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index a190f31..886de98 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -58,6 +58,10 @@ void qmp_boxed(UserDefZero *arg, Error **errp)
{
}
+void qmp_boxed2(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,
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 26/29] qapi: Clean up qapi.py per pep8
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (24 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 25/29] qapi: Support boxed unions Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union Eric Blake
` (2 subsequent siblings)
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Roth, marcandre.lureau, armbru, DirtY.iCE.hu
Silence pep8, and make pylint a bit happier. Just style cleanups;
no semantic changes.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi.py | 165 ++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 106 insertions(+), 59 deletions(-)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 181d40f..a38862d 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -71,6 +71,7 @@ all_names = {}
# Parsing the schema into expressions
#
+
def error_path(parent):
res = ""
while parent:
@@ -79,8 +80,10 @@ def error_path(parent):
parent = parent['parent']
return res
+
class QAPISchemaError(Exception):
def __init__(self, schema, msg):
+ Exception.__init__(self)
self.fname = schema.fname
self.msg = msg
self.col = 1
@@ -96,8 +99,10 @@ class QAPISchemaError(Exception):
return error_path(self.info) + \
"%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
+
class QAPIExprError(Exception):
def __init__(self, expr_info, msg):
+ Exception.__init__(self)
self.info = expr_info
self.msg = msg
@@ -105,9 +110,10 @@ class QAPIExprError(Exception):
return error_path(self.info['parent']) + \
"%s:%d: %s" % (self.info['file'], self.info['line'], self.msg)
+
class QAPISchemaParser(object):
- def __init__(self, fp, previously_included = [], incl_info = None):
+ def __init__(self, fp, previously_included=[], incl_info=None):
abs_fname = os.path.abspath(fp.name)
fname = fp.name
self.fname = fname
@@ -122,18 +128,18 @@ class QAPISchemaParser(object):
self.exprs = []
self.accept()
- while self.tok != None:
+ while self.tok is not None:
expr_info = {'file': fname, 'line': self.line,
'parent': self.incl_info}
expr = self.get_expr(False)
if isinstance(expr, dict) and "include" in expr:
if len(expr) != 1:
- raise QAPIExprError(expr_info, "Invalid 'include' directive")
+ raise QAPIExprError(expr_info,
+ "Invalid 'include' directive")
include = expr["include"]
if not isinstance(include, str):
- raise QAPIExprError(expr_info,
- 'Expected a file name (string), got: %s'
- % include)
+ raise QAPIExprError(expr_info, 'Expected a file name '
+ '(string), got: %s' % include)
incl_abs_fname = os.path.join(os.path.dirname(abs_fname),
include)
# catch inclusion cycle
@@ -192,7 +198,7 @@ class QAPISchemaParser(object):
string += '\t'
elif ch == 'u':
value = 0
- for x in range(0, 4):
+ for _ in range(0, 4):
ch = self.src[self.cursor]
self.cursor += 1
if ch not in "0123456789abcdefABCDEF":
@@ -214,7 +220,7 @@ class QAPISchemaParser(object):
string += ch
else:
raise QAPISchemaError(self,
- "Unknown escape \\%s" %ch)
+ "Unknown escape \\%s" % ch)
esc = False
elif ch == "\\":
esc = True
@@ -274,7 +280,7 @@ class QAPISchemaParser(object):
if self.tok == ']':
self.accept()
return expr
- if not self.tok in "{['tfn":
+ if self.tok not in "{['tfn":
raise QAPISchemaError(self, 'Expected "{", "[", "]", string, '
'boolean or "null"')
while True:
@@ -308,15 +314,17 @@ class QAPISchemaParser(object):
# TODO catching name collisions in generated code would be nice
#
+
def find_base_fields(base):
base_struct_define = find_struct(base)
if not base_struct_define:
return None
return base_struct_define['data']
+
# Return the qtype of an alternate branch, or None on error.
def find_alternate_member_qtype(qapi_type):
- if builtin_types.has_key(qapi_type):
+ if qapi_type in builtin_types:
return builtin_types[qapi_type]
elif find_struct(qapi_type):
return "QTYPE_QDICT"
@@ -326,6 +334,7 @@ def find_alternate_member_qtype(qapi_type):
return "QTYPE_QDICT"
return None
+
# Return the discriminator enum define if discriminator is specified as an
# enum type, otherwise return None.
def discriminator_find_enum_define(expr):
@@ -345,11 +354,14 @@ def discriminator_find_enum_define(expr):
return find_enum(discriminator_type)
+
# FIXME should enforce "other than downstream extensions [...], all
# names should begin with a letter".
valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$')
-def check_name(expr_info, source, name, allow_optional = False,
- enum_member = False):
+
+
+def check_name(expr_info, source, name, allow_optional=False,
+ enum_member=False):
global valid_name
membername = name
@@ -370,7 +382,8 @@ def check_name(expr_info, source, name, allow_optional = False,
raise QAPIExprError(expr_info,
"%s uses invalid name '%s'" % (source, name))
-def add_name(name, info, meta, implicit = False):
+
+def add_name(name, info, meta, implicit=False):
global all_names
check_name(info, "'%s'" % meta, name)
# FIXME should reject names that differ only in '_' vs. '.'
@@ -385,12 +398,14 @@ def add_name(name, info, meta, implicit = False):
% (meta, name))
all_names[name] = meta
+
def add_struct(definition, info):
global struct_types
name = definition['struct']
add_name(name, info, 'struct')
struct_types.append(definition)
+
def find_struct(name):
global struct_types
for struct in struct_types:
@@ -398,12 +413,14 @@ def find_struct(name):
return struct
return None
+
def add_union(definition, info):
global union_types
name = definition['union']
add_name(name, info, 'union')
union_types.append(definition)
+
def find_union(name):
global union_types
for union in union_types:
@@ -411,11 +428,13 @@ def find_union(name):
return union
return None
-def add_enum(name, info, enum_values = None, implicit = False):
+
+def add_enum(name, info, enum_values=None, implicit=False):
global enum_types
add_name(name, info, 'enum', implicit)
enum_types.append({"enum_name": name, "enum_values": enum_values})
+
def find_enum(name):
global enum_types
for enum in enum_types:
@@ -423,12 +442,14 @@ def find_enum(name):
return enum
return None
+
def is_enum(name):
- return find_enum(name) != None
+ return find_enum(name) is not None
-def check_type(expr_info, source, value, allow_array = False,
- allow_dict = False, allow_optional = False,
- allow_metas = []):
+
+def check_type(expr_info, source, value, allow_array=False,
+ allow_dict=False, allow_optional=False,
+ allow_metas=[]):
global all_names
if value is None:
@@ -447,7 +468,7 @@ def check_type(expr_info, source, value, allow_array = False,
# Check if type name for value is okay
if isinstance(value, str):
- if not value in all_names:
+ if value not in all_names:
raise QAPIExprError(expr_info,
"%s uses unknown type '%s'"
% (source, value))
@@ -476,7 +497,8 @@ def check_type(expr_info, source, value, allow_array = False,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
-def check_member_clash(expr_info, base_name, data, source = ""):
+
+def check_member_clash(expr_info, base_name, data, source=""):
base = find_struct(base_name)
assert base
base_members = base['data']
@@ -490,6 +512,7 @@ def check_member_clash(expr_info, base_name, data, source = ""):
if base.get('base'):
check_member_clash(expr_info, base['base'], data, source)
+
def check_command(expr, expr_info):
name = expr['command']
box = expr.get('box', False)
@@ -511,6 +534,7 @@ def check_command(expr, expr_info):
expr.get('returns'), allow_array=True,
allow_optional=True, allow_metas=returns_meta)
+
def check_event(expr, expr_info):
global events
name = expr['event']
@@ -526,19 +550,20 @@ def check_event(expr, expr_info):
expr.get('data'), allow_dict=not box, allow_optional=True,
allow_metas=meta)
+
def check_union(expr, expr_info):
name = expr['union']
base = expr.get('base')
discriminator = expr.get('discriminator')
members = expr['data']
- values = { 'MAX': '(automatic)' }
+ values = {'MAX': '(automatic)'}
# Two types of unions, determined by discriminator.
# With no discriminator it is a simple union.
if discriminator is None:
enum_define = None
- allow_metas=['built-in', 'union', 'alternate', 'struct', 'enum']
+ allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
if base is not None:
raise QAPIExprError(expr_info,
"Simple union '%s' must not have a base"
@@ -568,7 +593,7 @@ def check_union(expr, expr_info):
"struct '%s'"
% (discriminator, base))
enum_define = find_enum(discriminator_type)
- allow_metas=['struct']
+ allow_metas = ['struct']
# Do not allow string discriminator
if not enum_define:
raise QAPIExprError(expr_info,
@@ -595,7 +620,7 @@ def check_union(expr, expr_info):
# If the discriminator names an enum type, then all members
# of 'data' must also be members of the enum type.
if enum_define:
- if not key in enum_define['enum_values']:
+ if key not in enum_define['enum_values']:
raise QAPIExprError(expr_info,
"Discriminator value '%s' is not found in "
"enum '%s'" %
@@ -610,10 +635,11 @@ def check_union(expr, expr_info):
% (name, key, values[c_key]))
values[c_key] = key
+
def check_alternate(expr, expr_info):
name = expr['alternate']
members = expr['data']
- values = { 'MAX': '(automatic)' }
+ values = {'MAX': '(automatic)'}
types_seen = {}
# Check every branch; require at least two branches
@@ -645,16 +671,17 @@ def check_alternate(expr, expr_info):
% (name, key, types_seen[qtype]))
types_seen[qtype] = key
+
def check_enum(expr, expr_info):
name = expr['enum']
members = expr.get('data')
- values = { 'MAX': '(automatic)' }
+ values = {'MAX': '(automatic)'}
if not isinstance(members, list):
raise QAPIExprError(expr_info,
"Enum '%s' requires an array for 'data'" % name)
for member in members:
- check_name(expr_info, "Member of enum '%s'" %name, member,
+ check_name(expr_info, "Member of enum '%s'" % name, member,
enum_member=True)
key = camel_to_upper(member)
if key in values:
@@ -663,6 +690,7 @@ def check_enum(expr, expr_info):
% (name, member, values[key]))
values[key] = member
+
def check_struct(expr, expr_info):
name = expr['struct']
members = expr['data']
@@ -674,6 +702,7 @@ def check_struct(expr, expr_info):
if expr.get('base'):
check_member_clash(expr_info, expr['base'], expr['data'])
+
def check_keys(expr_elem, meta, required, optional=[]):
expr = expr_elem['expr']
info = expr_elem['info']
@@ -681,26 +710,27 @@ def check_keys(expr_elem, meta, required, optional=[]):
if not isinstance(name, str):
raise QAPIExprError(info,
"'%s' key must have a string value" % meta)
- required = required + [ meta ]
+ required = required + [meta]
for (key, value) in expr.items():
- if not key in required and not key in optional:
+ if key not in required + optional:
raise QAPIExprError(info,
"Unknown key '%s' in %s '%s'"
% (key, meta, name))
- if (key == 'gen' or key == 'success-response') and value != False:
+ if (key == 'gen' or key == 'success-response') and value is not False:
raise QAPIExprError(info,
"'%s' of %s '%s' should only use false value"
% (key, meta, name))
- if key == 'box' and value != True:
+ if key == 'box' 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 not expr.has_key(key):
+ if key not in expr:
raise QAPIExprError(info,
"Key '%s' is missing from %s '%s'"
% (key, meta, name))
+
def check_exprs(exprs):
global all_names
@@ -710,24 +740,24 @@ def check_exprs(exprs):
for expr_elem in exprs:
expr = expr_elem['expr']
info = expr_elem['info']
- if expr.has_key('enum'):
+ if 'enum' in expr:
check_keys(expr_elem, 'enum', ['data'])
add_enum(expr['enum'], info, expr['data'])
- elif expr.has_key('union'):
+ elif 'union' in expr:
check_keys(expr_elem, 'union', ['data'],
['base', 'discriminator'])
add_union(expr, info)
- elif expr.has_key('alternate'):
+ elif 'alternate' in expr:
check_keys(expr_elem, 'alternate', ['data'])
add_name(expr['alternate'], info, 'alternate')
- elif expr.has_key('struct'):
+ elif 'struct' in expr:
check_keys(expr_elem, 'struct', ['data'], ['base'])
add_struct(expr, info)
- elif expr.has_key('command'):
+ elif 'command' in expr:
check_keys(expr_elem, 'command', [],
['data', 'returns', 'gen', 'success-response', 'box'])
add_name(expr['command'], info, 'command')
- elif expr.has_key('event'):
+ elif 'event' in expr:
check_keys(expr_elem, 'event', [], ['data', 'box'])
add_name(expr['event'], info, 'event')
else:
@@ -737,11 +767,11 @@ def check_exprs(exprs):
# Try again for hidden UnionKind enum
for expr_elem in exprs:
expr = expr_elem['expr']
- if expr.has_key('union'):
+ if 'union' in expr:
if not discriminator_find_enum_define(expr):
add_enum('%sKind' % expr['union'], expr_elem['info'],
implicit=True)
- elif expr.has_key('alternate'):
+ elif 'alternate' in expr:
add_enum('%sKind' % expr['alternate'], expr_elem['info'],
implicit=True)
@@ -750,17 +780,17 @@ def check_exprs(exprs):
expr = expr_elem['expr']
info = expr_elem['info']
- if expr.has_key('enum'):
+ if 'enum' in expr:
check_enum(expr, info)
- elif expr.has_key('union'):
+ elif 'union' in expr:
check_union(expr, info)
- elif expr.has_key('alternate'):
+ elif 'alternate' in expr:
check_alternate(expr, info)
- elif expr.has_key('struct'):
+ elif 'struct' in expr:
check_struct(expr, info)
- elif expr.has_key('command'):
+ elif 'command' in expr:
check_command(expr, info)
- elif expr.has_key('event'):
+ elif 'event' in expr:
check_event(expr, info)
else:
assert False, 'unexpected meta type'
@@ -1320,6 +1350,7 @@ def camel_case(name):
new_name += ch.lower()
return new_name
+
# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
# ENUM24_Name -> ENUM24_NAME
@@ -1336,17 +1367,19 @@ def camel_to_upper(value):
if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
# Case 1: next string is lower
# Case 2: previous string is digit
- if (i < (l - 1) and c_fun_str[i + 1].islower()) or \
- c_fun_str[i - 1].isdigit():
+ next_lower = (i < (l - 1) and c_fun_str[i + 1].islower())
+ if next_lower or c_fun_str[i - 1].isdigit():
new_name += '_'
new_name += c
return new_name.lstrip('_').upper()
+
def c_enum_const(type_name, const_name):
return camel_to_upper(type_name + '_' + const_name)
c_name_trans = string.maketrans('.-', '__')
+
# Map @name to a valid C identifier.
# If @protect, avoid returning certain ticklish identifiers (like
# C keywords) by prepending "q_".
@@ -1359,15 +1392,16 @@ c_name_trans = string.maketrans('.-', '__')
def c_name(name, protect=True):
# ANSI X3J11/88-090, 3.1.1
c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
- 'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
- 'for', 'goto', 'if', 'int', 'long', 'register', 'return',
- 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
- 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'])
+ 'default', 'do', 'double', 'else', 'enum', 'extern',
+ 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
+ 'return', 'short', 'signed', 'sizeof', 'static',
+ 'struct', 'switch', 'typedef', 'union', 'unsigned',
+ 'void', 'volatile', 'while'])
# ISO/IEC 9899:1999, 6.4.1
c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
# ISO/IEC 9899:2011, 6.4.1
- c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn',
- '_Static_assert', '_Thread_local'])
+ c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
+ '_Noreturn', '_Static_assert', '_Thread_local'])
# GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
# excluding _.*
gcc_words = set(['asm', 'typeof'])
@@ -1383,29 +1417,34 @@ def c_name(name, protect=True):
'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
# namespace pollution:
polluted_words = set(['unix', 'errno'])
- if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words):
+ if protect and (name in c89_words | c99_words | c11_words | gcc_words
+ | cpp_words | polluted_words):
return "q_" + name
return name.translate(c_name_trans)
eatspace = '\033EATSPACE.'
pointer_suffix = ' *' + eatspace
+
def genindent(count):
ret = ""
- for i in range(count):
+ for _ in range(count):
ret += " "
return ret
indent_level = 0
+
def push_indent(indent_amount=4):
global indent_level
indent_level += indent_amount
+
def pop_indent(indent_amount=4):
global indent_level
indent_level -= indent_amount
+
# Generate @code with @kwds interpolated.
# Obey indent_level, and strip eatspace.
def cgen(code, **kwds):
@@ -1416,6 +1455,7 @@ def cgen(code, **kwds):
raw = raw[0]
return re.sub(re.escape(eatspace) + ' *', '', raw)
+
def mcgen(code, **kwds):
if code[0] == '\n':
code = code[1:]
@@ -1425,6 +1465,7 @@ def mcgen(code, **kwds):
def guardname(filename):
return c_name(filename, protect=False).upper()
+
def guardstart(name):
return mcgen('''
@@ -1434,6 +1475,7 @@ def guardstart(name):
''',
name=guardname(name))
+
def guardend(name):
return mcgen('''
@@ -1442,6 +1484,7 @@ def guardend(name):
''',
name=guardname(name))
+
def gen_enum_lookup(name, values):
ret = mcgen('''
@@ -1463,6 +1506,7 @@ const char *const %(c_name)s_lookup[] = {
max_index=max_index)
return ret
+
def gen_enum(name, values):
# append automatically generated _MAX value
enum_values = values + ['MAX']
@@ -1520,7 +1564,8 @@ def gen_params(arg_type, box, extra):
# Common command line parsing
#
-def parse_command_line(extra_options = "", extra_long_options = []):
+
+def parse_command_line(extra_options="", extra_long_options=[]):
try:
opts, args = getopt.gnu_getopt(sys.argv[1:],
@@ -1571,6 +1616,7 @@ def parse_command_line(extra_options = "", extra_long_options = []):
# Generate output files with boilerplate
#
+
def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
c_comment, h_comment):
guard = guardname(prefix + h_file)
@@ -1598,7 +1644,7 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
%(comment)s
''',
- comment = c_comment))
+ comment=c_comment))
fdecl.write(mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
@@ -1607,10 +1653,11 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
#define %(guard)s
''',
- comment = h_comment, guard = guard))
+ comment=h_comment, guard=guard))
return (fdef, fdecl)
+
def close_output(fdef, fdecl):
fdecl.write('''
#endif
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (25 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 26/29] qapi: Clean up qapi.py per pep8 Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-17 9:15 ` Wen Congyang
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 28/29] net: Use correct type for bool flag Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 29/29] net: Complete qapi-fication of netdev_add Eric Blake
28 siblings, 1 reply; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
armbru, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, Alexander Graf, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luiz Capitulino, Luigi Rizzo, David Gibson, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
From: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
Except qapi-schema.json, this patch was generated by:
find . -name .git -prune -o -type f \! -name '*~' -print0 | \
xargs -0 sed -i \
-e 's/NetClientOptionsKind/NetClientDriver/g' \
-e 's/NET_CLIENT_OPTIONS_KIND_/NET_CLIENT_DRIVER_/g' \
-e 's/netdev->opts/netdev/g'
Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
Additional changes:
Rebase the patch on top of an earlier change from netdev->kind to
netdev->type, so that tweak no longer needed here.
Rework so that NetdevLegacy doesn't pollute QMP command but is instead
copied piecewise into the new Netdev, which means that NetClientOptions
must still remain in qapi. Since legacy previously always rejected
'hubport', we can now make that explicit by having the two unions be
slightly different; but that means we must manually map between the
two structures.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
hw/arm/musicpal.c | 2 +-
hw/core/qdev-properties-system.c | 2 +-
hw/net/allwinner_emac.c | 2 +-
hw/net/cadence_gem.c | 2 +-
hw/net/dp8393x.c | 2 +-
hw/net/e1000.c | 2 +-
hw/net/eepro100.c | 2 +-
hw/net/etraxfs_eth.c | 2 +-
hw/net/fsl_etsec/etsec.c | 2 +-
hw/net/imx_fec.c | 2 +-
hw/net/lan9118.c | 2 +-
hw/net/lance.c | 2 +-
hw/net/mcf_fec.c | 2 +-
hw/net/milkymist-minimac2.c | 2 +-
hw/net/mipsnet.c | 2 +-
hw/net/ne2000-isa.c | 2 +-
hw/net/ne2000.c | 2 +-
hw/net/opencores_eth.c | 2 +-
hw/net/pcnet-pci.c | 2 +-
hw/net/rocker/rocker_fp.c | 2 +-
hw/net/rtl8139.c | 2 +-
hw/net/smc91c111.c | 2 +-
hw/net/spapr_llan.c | 2 +-
hw/net/stellaris_enet.c | 2 +-
hw/net/vhost_net.c | 18 +++---
hw/net/virtio-net.c | 6 +-
hw/net/vmxnet3.c | 2 +-
hw/net/xen_nic.c | 2 +-
hw/net/xgmac.c | 2 +-
hw/net/xilinx_axienet.c | 2 +-
hw/net/xilinx_ethlite.c | 2 +-
hw/usb/dev-network.c | 2 +-
include/net/net.h | 4 +-
monitor.c | 14 ++---
net/dump.c | 6 +-
net/hub.c | 22 +++----
net/l2tpv3.c | 6 +-
net/net.c | 133 +++++++++++++++++++++++++--------------
net/netmap.c | 4 +-
net/slirp.c | 6 +-
net/socket.c | 8 +--
net/tap-win32.c | 6 +-
net/tap.c | 24 +++----
net/vde.c | 6 +-
net/vhost-user.c | 12 ++--
qapi-schema.json | 57 +++++++++++++----
46 files changed, 230 insertions(+), 162 deletions(-)
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 42f66b3..94bdf5f 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -374,7 +374,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 921e799..249976e 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -229,7 +229,7 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque,
}
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 0407dee..4fdf824 100644
--- a/hw/net/allwinner_emac.c
+++ b/hw/net/allwinner_emac.c
@@ -422,7 +422,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 1127223..9c4773e 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1175,7 +1175,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 ab607e4..fb57900 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -810,7 +810,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 5c6bcd0..06b5a52 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1515,7 +1515,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/eepro100.c b/hw/net/eepro100.c
index 60333b7..28552f7 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1832,7 +1832,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 d600275..f43a170 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -577,7 +577,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 0f5cf44..c936b3b 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -369,7 +369,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 725f3fa..785a3cc 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -651,7 +651,7 @@ static void imx_fec_cleanup(NetClientState *nc)
}
static NetClientInfo net_imx_fec_info = {
- .type = NET_CLIENT_OPTIONS_KIND_NIC,
+ .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.can_receive = imx_fec_can_receive,
.receive = imx_fec_receive,
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 4f0e840..11bfd23 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1305,7 +1305,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 780b39d..7940c05 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -92,7 +92,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 21928f9..5386597 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -506,7 +506,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 5d1cf08..aff0c9f 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -443,7 +443,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 f261011..b9bf03f 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -218,7 +218,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 18b0644..7894fab 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -42,7 +42,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 53c704a..3c5a322 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -694,7 +694,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 3642046..4b6407b 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 b4d60b8..c04c3a2 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -271,7 +271,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 c693ae5..3f82e30 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -166,7 +166,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 fb2c55c..0f1d405 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3415,7 +3415,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 74e06e6..4c85eb5 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -737,7 +737,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,
.receive = smc91c111_receive,
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 1ca5e9c..4ee4b92 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -188,7 +188,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 21a4773..10290fe 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -449,7 +449,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 5c1d11f..5d24c29 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -95,10 +95,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:
@@ -125,7 +125,7 @@ void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
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");
@@ -236,7 +236,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) {
@@ -252,7 +252,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_call(&net->dev, VHOST_NET_SET_BACKEND,
@@ -275,14 +275,14 @@ 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_call(&net->dev, VHOST_NET_SET_BACKEND,
&file);
assert(r >= 0);
}
- } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
+ } else if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
@@ -399,10 +399,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 8d28e45..ee76e29 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -406,7 +406,7 @@ static int peer_attach(VirtIONet *n, int index)
return 0;
}
- if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
+ if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
return 0;
}
@@ -421,7 +421,7 @@ static int peer_detach(VirtIONet *n, int index)
return 0;
}
- if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
+ if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
return 0;
}
@@ -1595,7 +1595,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 04159c8..ae465bd 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1986,7 +1986,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 d7cbfc1..fd2da6a 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -280,7 +280,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 15fb681..ccf8a77 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -370,7 +370,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 d63c423..cc464c9 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -933,7 +933,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 ad6b553..ab555f6 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -214,7 +214,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 7800cee..97b2c2a 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1330,7 +1330,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,
diff --git a/include/net/net.h b/include/net/net.h
index 6a6cbef..c0e00ef 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -59,7 +59,7 @@ typedef int (SetVnetLE)(NetClientState *, bool);
typedef int (SetVnetBE)(NetClientState *, bool);
typedef struct NetClientInfo {
- NetClientOptionsKind type;
+ NetClientDriver type;
size_t size;
NetReceive *receive;
NetReceive *receive_raw;
@@ -104,7 +104,7 @@ typedef struct NICState {
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,
diff --git a/monitor.c b/monitor.c
index e5ee8e4..e2f081e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4224,8 +4224,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]);
}
}
@@ -4425,7 +4425,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;
@@ -4450,7 +4450,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;
@@ -4562,7 +4562,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;
@@ -4579,13 +4579,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/dump.c b/net/dump.c
index a1f99c3..d2c68f8 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -94,7 +94,7 @@ static void dump_cleanup(NetClientState *nc)
}
static NetClientInfo net_dump_info = {
- .type = NET_CLIENT_OPTIONS_KIND_DUMP,
+ .type = NET_CLIENT_DRIVER_DUMP,
.size = sizeof(DumpState),
.receive = dump_receive,
.cleanup = dump_cleanup,
@@ -154,8 +154,8 @@ int net_init_dump(const Netdev *netdev, const char *name,
char def_file[128];
const NetdevDumpOptions *dump;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_DUMP);
- dump = netdev->opts->dump;
+ assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
+ dump = netdev->dump;
assert(peer);
diff --git a/net/hub.c b/net/hub.c
index 047d861..11e6450 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -130,7 +130,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,
@@ -265,10 +265,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;
@@ -285,9 +285,9 @@ int net_init_hubport(const Netdev *netdev, const char *name,
{
const NetdevHubPortOptions *hubport;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT);
+ assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
assert(!peer);
- hubport = netdev->opts->hubport;
+ hubport = netdev->hubport;
net_hub_add_port(hubport->hubid, name);
return 0;
@@ -314,14 +314,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 bdb13fa..aa2c020 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,
@@ -545,8 +545,8 @@ int net_init_l2tpv3(const Netdev *netdev,
s->queue_tail = 0;
s->header_mismatch = false;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3);
- l2tpv3 = netdev->opts->l2tpv3;
+ assert(netdev->type == NET_CLIENT_DRIVER_L2TPV3);
+ l2tpv3 = netdev->l2tpv3;
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
s->ipv6 = l2tpv3->ipv6;
diff --git a/net/net.c b/net/net.c
index 94a3d18..c1d407e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -315,7 +315,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);
@@ -385,18 +385,18 @@ void qemu_del_net_client(NetClientState *nc)
NetClientState *ncs[MAX_QUEUE_NUM];
int queues, i;
- 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);
/* 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;
@@ -452,7 +452,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);
}
@@ -598,7 +598,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();
}
@@ -728,7 +728,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;
@@ -739,7 +739,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;
@@ -820,8 +820,8 @@ static int net_init_nic(const Netdev *netdev, const char *name,
NICInfo *nd;
const NetLegacyNicOptions *nic;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
- nic = netdev->opts->nic;
+ assert(netdev->type == NET_CLIENT_DRIVER_NIC);
+ nic = netdev->nic;
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
@@ -881,39 +881,38 @@ static int net_init_nic(const Netdev *netdev, const char *name,
}
-static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
+static int (* const net_client_init_fun[NET_CLIENT_DRIVER_MAX])(
const 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)
{
- const NetClientOptions *opts;
Netdev legacy = {0};
const Netdev *netdev;
const char *name;
@@ -921,34 +920,72 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
if (is_netdev) {
netdev = object;
- opts = netdev->opts;
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;
+ const NetClientOptions *opts = net->opts;
legacy.id = net->id;
- opts = legacy.opts = net->opts;
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_CLIENT_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_CLIENT_OPTIONS_KIND_NIC:
+ legacy.type = NET_CLIENT_DRIVER_NIC;
+ legacy.nic = opts->nic;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_USER:
+ legacy.type = NET_CLIENT_DRIVER_USER;
+ legacy.user = opts->user;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_TAP:
+ legacy.type = NET_CLIENT_DRIVER_TAP;
+ legacy.tap = opts->tap;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_L2TPV3:
+ legacy.type = NET_CLIENT_DRIVER_L2TPV3;
+ legacy.l2tpv3 = opts->l2tpv3;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_SOCKET:
+ legacy.type = NET_CLIENT_DRIVER_SOCKET;
+ legacy.socket = opts->socket;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_VDE:
+ legacy.type = NET_CLIENT_DRIVER_VDE;
+ legacy.vde = opts->vde;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_DUMP:
+ legacy.type = NET_CLIENT_DRIVER_DUMP;
+ legacy.dump = opts->dump;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_BRIDGE:
+ legacy.type = NET_CLIENT_DRIVER_BRIDGE;
+ legacy.bridge = opts->bridge;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_NETMAP:
+ legacy.type = NET_CLIENT_DRIVER_NETMAP;
+ legacy.netmap = opts->netmap;
+ break;
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
+ legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
+ legacy.vhost_user = opts->vhost_user;
+ 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)");
@@ -956,17 +993,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->nic->has_netdev) {
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
}
}
- if (net_client_init_fun[opts->type](netdev, 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;
}
@@ -1065,7 +1102,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;
}
@@ -1131,7 +1168,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);
}
@@ -1150,7 +1187,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;
@@ -1190,7 +1227,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);
@@ -1203,10 +1240,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);
}
@@ -1220,7 +1257,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) {
@@ -1247,7 +1284,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;
}
@@ -1288,7 +1325,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);
@@ -1320,7 +1357,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);
}
}
diff --git a/net/netmap.c b/net/netmap.c
index a464618..eff9b8c 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -417,7 +417,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,
@@ -439,7 +439,7 @@ int net_init_netmap(const Netdev *netdev,
const char *name, NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
- const NetdevNetmapOptions *netmap_opts = netdev->opts->netmap;
+ const NetdevNetmapOptions *netmap_opts = netdev->netmap;
NetClientState *nc;
NetmapPriv me;
NetmapState *s;
diff --git a/net/slirp.c b/net/slirp.c
index e160b9c..055c9de 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -126,7 +126,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,
@@ -746,8 +746,8 @@ int net_init_slirp(const Netdev *netdev, const char *name,
const NetdevUserOptions *user;
const char **dnssearch;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_USER);
- user = netdev->opts->user;
+ assert(netdev->type == NET_CLIENT_DRIVER_USER);
+ user = netdev->user;
vnet = user->has_net ? g_strdup(user->net) :
user->has_ip ? g_strdup_printf("%s/24", user->ip) :
diff --git a/net/socket.c b/net/socket.c
index 7f949e2..915bed2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -346,7 +346,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,
@@ -429,7 +429,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,
@@ -706,8 +706,8 @@ int net_init_socket(const Netdev *netdev, const char *name,
Error *err = NULL;
const NetdevSocketOptions *sock;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET);
- sock = netdev->opts->socket;
+ assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
+ sock = netdev->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 acce480..32be2a0 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -723,7 +723,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,
@@ -767,8 +767,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
/* FIXME error_setg(errp, ...) on failure */
const NetdevTapOptions *tap;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
- tap = netdev->opts->tap;
+ assert(netdev->type == NET_CLIENT_DRIVER_TAP);
+ tap = netdev->tap;
if (!tap->has_ifname) {
error_report("tap: no interface name");
diff --git a/net/tap.c b/net/tap.c
index aecc759..626dfca 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -221,7 +221,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;
}
@@ -230,7 +230,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;
}
@@ -239,7 +239,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);
}
@@ -248,7 +248,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));
@@ -260,7 +260,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;
@@ -326,14 +326,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,
@@ -565,8 +565,8 @@ int net_init_bridge(const Netdev *netdev, const char *name,
TAPState *s;
int fd, vnet_hdr;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
- bridge = netdev->opts->bridge;
+ assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
+ bridge = netdev->bridge;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
@@ -728,8 +728,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
const char *vhostfdname;
char ifname[128];
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
- tap = netdev->opts->tap;
+ assert(netdev->type == NET_CLIENT_DRIVER_TAP);
+ tap = netdev->tap;
queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
@@ -890,7 +890,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
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 0ac2525..7a6d4f0 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,
@@ -115,8 +115,8 @@ int net_init_vde(const Netdev *netdev, const char *name,
/* FIXME error_setg(errp, ...) on failure */
const NetdevVdeOptions *vde;
- assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_VDE);
- vde = netdev->opts->vde;
+ assert(netdev->type == NET_CLIENT_DRIVER_VDE);
+ vde = netdev->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 8597ec4..fef89ca 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -30,7 +30,7 @@ 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;
}
@@ -75,20 +75,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),
.cleanup = vhost_user_cleanup,
.has_vnet_hdr = vhost_user_has_vnet_hdr,
@@ -229,8 +229,8 @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr;
- assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
- vhost_user_opts = netdev->opts->vhost_user;
+ assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER);
+ vhost_user_opts = netdev->vhost_user;
chr = net_vhost_parse_chardev(vhost_user_opts, errp);
if (!chr) {
diff --git a/qapi-schema.json b/qapi-schema.json
index 8c77220..02ccbb7 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2489,16 +2489,42 @@
'*vhostforce': 'bool' } }
##
-# @NetClientOptions
+# @NetClientDriver
#
-# A discriminated record of network device traits.
+# Available netdev drivers.
+#
+# Since 2.5
+##
+{ 'enum': 'NetClientDriver',
+ 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump',
+ 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
+
+##
+# @NetdevBase
+#
+# Captures the common configuration of a network device.
+#
+# @id: identifier for monitor commands.
+#
+# @type: Specify the driver used for interpreting remaining arguments.
+#
+# Since 1.2
+##
+{ 'struct': 'NetdevBase',
+ 'data': { 'id': 'str', 'type': 'NetClientDriver' } }
+
+##
+# @Netdev
+#
+# Captures the configuration of a network device.
#
# Since 1.2
#
# 'l2tpv3' - since 2.1
-#
##
-{ 'union': 'NetClientOptions',
+{ 'union': 'Netdev',
+ 'base': 'NetdevBase',
+ 'discriminator': 'type',
'data': {
'none': 'NetdevNoneOptions',
'nic': 'NetLegacyNicOptions',
@@ -2536,20 +2562,25 @@
'opts': 'NetClientOptions' } }
##
-# @Netdev
+# @NetClientOptions
#
-# 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': 'NetClientOptions',
'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' } }
##
# @InetSocketAddress
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 28/29] net: Use correct type for bool flag
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (26 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 29/29] net: Complete qapi-fication of netdev_add Eric Blake
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: Jason Wang, armbru, Gerd Hoffmann, Stefan Hajnoczi, DirtY.iCE.hu,
marcandre.lureau
is_netdev is only used as a bool, so make it one.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
hw/usb/dev-network.c | 2 +-
include/net/net.h | 2 +-
net/net.c | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 97b2c2a..174bad4 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1392,7 +1392,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 c0e00ef..8c12eff 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -189,7 +189,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/net/net.c b/net/net.c
index c1d407e..d1ec9aa 100644
--- a/net/net.c
+++ b/net/net.c
@@ -911,7 +911,7 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER_MAX])(
};
-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)
{
Netdev legacy = {0};
const Netdev *netdev;
@@ -1021,7 +1021,7 @@ static void net_visit(Visitor *v, int is_netdev, void **object, 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;
@@ -1083,7 +1083,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);
@@ -1113,7 +1113,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)
@@ -1381,7 +1381,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;
@@ -1395,7 +1395,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;
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [Qemu-devel] [PATCH RFC v4 29/29] net: Complete qapi-fication of netdev_add
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
` (27 preceding siblings ...)
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 28/29] net: Use correct type for bool flag Eric Blake
@ 2015-09-10 4:06 ` Eric Blake
28 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-10 4:06 UTC (permalink / raw)
To: qemu-devel
Cc: marcandre.lureau, Jason Wang, armbru, Stefan Hajnoczi,
DirtY.iCE.hu
We finally have all the required pieces for doing a type-safe
representation of netdev_add as a flat union, where the
discriminator 'type' now selects which additional members may
appear in the "arguments" JSON object sent over QMP, while
making no changes to the set of previously-valid QMP commands
that would work, and without breaking command line parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/net/net.h | 1 -
net/net.c | 25 ++-----------------------
qapi-schema.json | 15 +++------------
qmp-commands.hx | 2 +-
4 files changed, 6 insertions(+), 37 deletions(-)
diff --git a/include/net/net.h b/include/net/net.h
index 8c12eff..475f1e8 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -197,7 +197,6 @@ void net_cleanup(void);
void hmp_host_net_add(Monitor *mon, const QDict *qdict);
void hmp_host_net_remove(Monitor *mon, const QDict *qdict);
void netdev_add(QemuOpts *opts, Error **errp);
-void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp);
int net_hub_id_for_client(NetClientState *nc, int *id);
NetClientState *net_hub_port_find(int hub_id);
diff --git a/net/net.c b/net/net.c
index d1ec9aa..69456b2 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1116,30 +1116,9 @@ void netdev_add(QemuOpts *opts, Error **errp)
net_client_init(opts, true, errp);
}
-void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp)
+void qmp_netdev_add(Netdev *netdev, Error **errp)
{
- Error *local_err = NULL;
- QemuOptsList *opts_list;
- QemuOpts *opts;
-
- opts_list = qemu_find_opts_err("netdev", &local_err);
- if (local_err) {
- goto out;
- }
-
- opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
- if (local_err) {
- goto out;
- }
-
- netdev_add(opts, &local_err);
- if (local_err) {
- qemu_opts_del(opts);
- goto out;
- }
-
-out:
- error_propagate(errp, local_err);
+ net_client_init1(netdev, true, errp);
}
void qmp_netdev_del(const char *id, Error **errp)
diff --git a/qapi-schema.json b/qapi-schema.json
index 02ccbb7..0b1c7ec 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2077,26 +2077,17 @@
#
# Add a network backend.
#
-# @type: the type of network backend. Current valid values are 'user', 'tap',
-# 'vde', 'socket', 'dump' and 'bridge'
+# @type: the type of network backend; determines which additional arguments
+# are valid. See Netdev documentation for more details.
#
# @id: the name of the new network backend
#
-# Additional arguments depend on the type.
-#
-# TODO This command effectively bypasses QAPI completely due to its
-# "additional arguments" business. It shouldn't have been added to
-# the schema in this form. It should be qapified properly, or
-# replaced by a properly qapified command.
-#
# Since: 0.14.0
#
# Returns: Nothing on success
# If @type is not a valid network backend, DeviceNotFound
##
-{ 'command': 'netdev_add',
- 'data': {'type': 'str', 'id': 'str'},
- 'gen': false } # so we can get the additional arguments
+{ 'command': 'netdev_add', 'data': 'Netdev', 'box': true }
##
# @netdev_del:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 66f0300..eecfa86 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -900,7 +900,7 @@ EQMP
{
.name = "netdev_add",
.args_type = "netdev:O",
- .mhandler.cmd_new = qmp_netdev_add,
+ .mhandler.cmd_new = qmp_marshal_netdev_add,
},
SQMP
--
2.4.3
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union Eric Blake
@ 2015-09-17 9:15 ` Wen Congyang
2015-09-17 14:34 ` Eric Blake
0 siblings, 1 reply; 40+ messages in thread
From: Wen Congyang @ 2015-09-17 9:15 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
Luiz Capitulino, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, armbru, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Alexander Graf, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
On 09/10/2015 12:06 PM, Eric Blake wrote:
> From: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
>
> Except qapi-schema.json, this patch was generated by:
>
> find . -name .git -prune -o -type f \! -name '*~' -print0 | \
> xargs -0 sed -i \
> -e 's/NetClientOptionsKind/NetClientDriver/g' \
> -e 's/NET_CLIENT_OPTIONS_KIND_/NET_CLIENT_DRIVER_/g' \
> -e 's/netdev->opts/netdev/g'
>
> Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
> Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
>
> Additional changes:
> Rebase the patch on top of an earlier change from netdev->kind to
> netdev->type, so that tweak no longer needed here.
>
> Rework so that NetdevLegacy doesn't pollute QMP command but is instead
> copied piecewise into the new Netdev, which means that NetClientOptions
> must still remain in qapi. Since legacy previously always rejected
> 'hubport', we can now make that explicit by having the two unions be
> slightly different; but that means we must manually map between the
> two structures.
I apply Markus's v8 patch and this series, make check will fail:
TEST: tests/virtio-net-test... (pid=23648)
/x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev socket,fd=6,id=hs0: Invalid parameter 'fd'
Broken pipe
FAIL
GTester: last random seed: R02Safdc7600ad90fa8d4fb252f86f953784
(pid=23652)
/x86_64/virtio/net/pci/rx_stop_cont: qemu-system-x86_64: -netdev socket,fd=5,id=hs0: Invalid parameter 'fd'
Broken pipe
FAIL
GTester: last random seed: R02S3cde2cc144ab662ff4daf105a799ee50
(pid=23655)
/x86_64/virtio/net/pci/hotplug: OK
FAIL: tests/virtio-net-test
Do I make a mistake when I do rebase?
Thanks
Wen Congyang
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> hw/arm/musicpal.c | 2 +-
> hw/core/qdev-properties-system.c | 2 +-
> hw/net/allwinner_emac.c | 2 +-
> hw/net/cadence_gem.c | 2 +-
> hw/net/dp8393x.c | 2 +-
> hw/net/e1000.c | 2 +-
> hw/net/eepro100.c | 2 +-
> hw/net/etraxfs_eth.c | 2 +-
> hw/net/fsl_etsec/etsec.c | 2 +-
> hw/net/imx_fec.c | 2 +-
> hw/net/lan9118.c | 2 +-
> hw/net/lance.c | 2 +-
> hw/net/mcf_fec.c | 2 +-
> hw/net/milkymist-minimac2.c | 2 +-
> hw/net/mipsnet.c | 2 +-
> hw/net/ne2000-isa.c | 2 +-
> hw/net/ne2000.c | 2 +-
> hw/net/opencores_eth.c | 2 +-
> hw/net/pcnet-pci.c | 2 +-
> hw/net/rocker/rocker_fp.c | 2 +-
> hw/net/rtl8139.c | 2 +-
> hw/net/smc91c111.c | 2 +-
> hw/net/spapr_llan.c | 2 +-
> hw/net/stellaris_enet.c | 2 +-
> hw/net/vhost_net.c | 18 +++---
> hw/net/virtio-net.c | 6 +-
> hw/net/vmxnet3.c | 2 +-
> hw/net/xen_nic.c | 2 +-
> hw/net/xgmac.c | 2 +-
> hw/net/xilinx_axienet.c | 2 +-
> hw/net/xilinx_ethlite.c | 2 +-
> hw/usb/dev-network.c | 2 +-
> include/net/net.h | 4 +-
> monitor.c | 14 ++---
> net/dump.c | 6 +-
> net/hub.c | 22 +++----
> net/l2tpv3.c | 6 +-
> net/net.c | 133 +++++++++++++++++++++++++--------------
> net/netmap.c | 4 +-
> net/slirp.c | 6 +-
> net/socket.c | 8 +--
> net/tap-win32.c | 6 +-
> net/tap.c | 24 +++----
> net/vde.c | 6 +-
> net/vhost-user.c | 12 ++--
> qapi-schema.json | 57 +++++++++++++----
> 46 files changed, 230 insertions(+), 162 deletions(-)
>
> diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
> index 42f66b3..94bdf5f 100644
> --- a/hw/arm/musicpal.c
> +++ b/hw/arm/musicpal.c
> @@ -374,7 +374,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 921e799..249976e 100644
> --- a/hw/core/qdev-properties-system.c
> +++ b/hw/core/qdev-properties-system.c
> @@ -229,7 +229,7 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque,
> }
>
> 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 0407dee..4fdf824 100644
> --- a/hw/net/allwinner_emac.c
> +++ b/hw/net/allwinner_emac.c
> @@ -422,7 +422,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 1127223..9c4773e 100644
> --- a/hw/net/cadence_gem.c
> +++ b/hw/net/cadence_gem.c
> @@ -1175,7 +1175,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 ab607e4..fb57900 100644
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -810,7 +810,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 5c6bcd0..06b5a52 100644
> --- a/hw/net/e1000.c
> +++ b/hw/net/e1000.c
> @@ -1515,7 +1515,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/eepro100.c b/hw/net/eepro100.c
> index 60333b7..28552f7 100644
> --- a/hw/net/eepro100.c
> +++ b/hw/net/eepro100.c
> @@ -1832,7 +1832,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 d600275..f43a170 100644
> --- a/hw/net/etraxfs_eth.c
> +++ b/hw/net/etraxfs_eth.c
> @@ -577,7 +577,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 0f5cf44..c936b3b 100644
> --- a/hw/net/fsl_etsec/etsec.c
> +++ b/hw/net/fsl_etsec/etsec.c
> @@ -369,7 +369,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 725f3fa..785a3cc 100644
> --- a/hw/net/imx_fec.c
> +++ b/hw/net/imx_fec.c
> @@ -651,7 +651,7 @@ static void imx_fec_cleanup(NetClientState *nc)
> }
>
> static NetClientInfo net_imx_fec_info = {
> - .type = NET_CLIENT_OPTIONS_KIND_NIC,
> + .type = NET_CLIENT_DRIVER_NIC,
> .size = sizeof(NICState),
> .can_receive = imx_fec_can_receive,
> .receive = imx_fec_receive,
> diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
> index 4f0e840..11bfd23 100644
> --- a/hw/net/lan9118.c
> +++ b/hw/net/lan9118.c
> @@ -1305,7 +1305,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 780b39d..7940c05 100644
> --- a/hw/net/lance.c
> +++ b/hw/net/lance.c
> @@ -92,7 +92,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 21928f9..5386597 100644
> --- a/hw/net/mcf_fec.c
> +++ b/hw/net/mcf_fec.c
> @@ -506,7 +506,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 5d1cf08..aff0c9f 100644
> --- a/hw/net/milkymist-minimac2.c
> +++ b/hw/net/milkymist-minimac2.c
> @@ -443,7 +443,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 f261011..b9bf03f 100644
> --- a/hw/net/mipsnet.c
> +++ b/hw/net/mipsnet.c
> @@ -218,7 +218,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 18b0644..7894fab 100644
> --- a/hw/net/ne2000-isa.c
> +++ b/hw/net/ne2000-isa.c
> @@ -42,7 +42,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 53c704a..3c5a322 100644
> --- a/hw/net/ne2000.c
> +++ b/hw/net/ne2000.c
> @@ -694,7 +694,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 3642046..4b6407b 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 b4d60b8..c04c3a2 100644
> --- a/hw/net/pcnet-pci.c
> +++ b/hw/net/pcnet-pci.c
> @@ -271,7 +271,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 c693ae5..3f82e30 100644
> --- a/hw/net/rocker/rocker_fp.c
> +++ b/hw/net/rocker/rocker_fp.c
> @@ -166,7 +166,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 fb2c55c..0f1d405 100644
> --- a/hw/net/rtl8139.c
> +++ b/hw/net/rtl8139.c
> @@ -3415,7 +3415,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 74e06e6..4c85eb5 100644
> --- a/hw/net/smc91c111.c
> +++ b/hw/net/smc91c111.c
> @@ -737,7 +737,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,
> .receive = smc91c111_receive,
> diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
> index 1ca5e9c..4ee4b92 100644
> --- a/hw/net/spapr_llan.c
> +++ b/hw/net/spapr_llan.c
> @@ -188,7 +188,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 21a4773..10290fe 100644
> --- a/hw/net/stellaris_enet.c
> +++ b/hw/net/stellaris_enet.c
> @@ -449,7 +449,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 5c1d11f..5d24c29 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -95,10 +95,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:
> @@ -125,7 +125,7 @@ void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
> 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");
> @@ -236,7 +236,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) {
> @@ -252,7 +252,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_call(&net->dev, VHOST_NET_SET_BACKEND,
> @@ -275,14 +275,14 @@ 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_call(&net->dev, VHOST_NET_SET_BACKEND,
> &file);
> assert(r >= 0);
> }
> - } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> + } else if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
> for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> const VhostOps *vhost_ops = net->dev.vhost_ops;
> int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> @@ -399,10 +399,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 8d28e45..ee76e29 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -406,7 +406,7 @@ static int peer_attach(VirtIONet *n, int index)
> return 0;
> }
>
> - if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> + if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
> return 0;
> }
>
> @@ -421,7 +421,7 @@ static int peer_detach(VirtIONet *n, int index)
> return 0;
> }
>
> - if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> + if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
> return 0;
> }
>
> @@ -1595,7 +1595,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 04159c8..ae465bd 100644
> --- a/hw/net/vmxnet3.c
> +++ b/hw/net/vmxnet3.c
> @@ -1986,7 +1986,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 d7cbfc1..fd2da6a 100644
> --- a/hw/net/xen_nic.c
> +++ b/hw/net/xen_nic.c
> @@ -280,7 +280,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 15fb681..ccf8a77 100644
> --- a/hw/net/xgmac.c
> +++ b/hw/net/xgmac.c
> @@ -370,7 +370,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 d63c423..cc464c9 100644
> --- a/hw/net/xilinx_axienet.c
> +++ b/hw/net/xilinx_axienet.c
> @@ -933,7 +933,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 ad6b553..ab555f6 100644
> --- a/hw/net/xilinx_ethlite.c
> +++ b/hw/net/xilinx_ethlite.c
> @@ -214,7 +214,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 7800cee..97b2c2a 100644
> --- a/hw/usb/dev-network.c
> +++ b/hw/usb/dev-network.c
> @@ -1330,7 +1330,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,
> diff --git a/include/net/net.h b/include/net/net.h
> index 6a6cbef..c0e00ef 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -59,7 +59,7 @@ typedef int (SetVnetLE)(NetClientState *, bool);
> typedef int (SetVnetBE)(NetClientState *, bool);
>
> typedef struct NetClientInfo {
> - NetClientOptionsKind type;
> + NetClientDriver type;
> size_t size;
> NetReceive *receive;
> NetReceive *receive_raw;
> @@ -104,7 +104,7 @@ typedef struct NICState {
> 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,
> diff --git a/monitor.c b/monitor.c
> index e5ee8e4..e2f081e 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -4224,8 +4224,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]);
> }
> }
>
> @@ -4425,7 +4425,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;
> @@ -4450,7 +4450,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;
> @@ -4562,7 +4562,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;
> @@ -4579,13 +4579,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/dump.c b/net/dump.c
> index a1f99c3..d2c68f8 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -94,7 +94,7 @@ static void dump_cleanup(NetClientState *nc)
> }
>
> static NetClientInfo net_dump_info = {
> - .type = NET_CLIENT_OPTIONS_KIND_DUMP,
> + .type = NET_CLIENT_DRIVER_DUMP,
> .size = sizeof(DumpState),
> .receive = dump_receive,
> .cleanup = dump_cleanup,
> @@ -154,8 +154,8 @@ int net_init_dump(const Netdev *netdev, const char *name,
> char def_file[128];
> const NetdevDumpOptions *dump;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_DUMP);
> - dump = netdev->opts->dump;
> + assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
> + dump = netdev->dump;
>
> assert(peer);
>
> diff --git a/net/hub.c b/net/hub.c
> index 047d861..11e6450 100644
> --- a/net/hub.c
> +++ b/net/hub.c
> @@ -130,7 +130,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,
> @@ -265,10 +265,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;
> @@ -285,9 +285,9 @@ int net_init_hubport(const Netdev *netdev, const char *name,
> {
> const NetdevHubPortOptions *hubport;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT);
> + assert(netdev->type == NET_CLIENT_DRIVER_HUBPORT);
> assert(!peer);
> - hubport = netdev->opts->hubport;
> + hubport = netdev->hubport;
>
> net_hub_add_port(hubport->hubid, name);
> return 0;
> @@ -314,14 +314,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 bdb13fa..aa2c020 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,
> @@ -545,8 +545,8 @@ int net_init_l2tpv3(const Netdev *netdev,
> s->queue_tail = 0;
> s->header_mismatch = false;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3);
> - l2tpv3 = netdev->opts->l2tpv3;
> + assert(netdev->type == NET_CLIENT_DRIVER_L2TPV3);
> + l2tpv3 = netdev->l2tpv3;
>
> if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
> s->ipv6 = l2tpv3->ipv6;
> diff --git a/net/net.c b/net/net.c
> index 94a3d18..c1d407e 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -315,7 +315,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);
> @@ -385,18 +385,18 @@ void qemu_del_net_client(NetClientState *nc)
> NetClientState *ncs[MAX_QUEUE_NUM];
> int queues, i;
>
> - 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);
>
> /* 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;
> @@ -452,7 +452,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);
> }
> @@ -598,7 +598,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();
> }
> @@ -728,7 +728,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;
> @@ -739,7 +739,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;
> @@ -820,8 +820,8 @@ static int net_init_nic(const Netdev *netdev, const char *name,
> NICInfo *nd;
> const NetLegacyNicOptions *nic;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
> - nic = netdev->opts->nic;
> + assert(netdev->type == NET_CLIENT_DRIVER_NIC);
> + nic = netdev->nic;
>
> idx = nic_get_free_idx();
> if (idx == -1 || nb_nics >= MAX_NICS) {
> @@ -881,39 +881,38 @@ static int net_init_nic(const Netdev *netdev, const char *name,
> }
>
>
> -static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
> +static int (* const net_client_init_fun[NET_CLIENT_DRIVER_MAX])(
> const 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)
> {
> - const NetClientOptions *opts;
> Netdev legacy = {0};
> const Netdev *netdev;
> const char *name;
> @@ -921,34 +920,72 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
>
> if (is_netdev) {
> netdev = object;
> - opts = netdev->opts;
> 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;
> + const NetClientOptions *opts = net->opts;
> legacy.id = net->id;
> - opts = legacy.opts = net->opts;
> 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_CLIENT_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_CLIENT_OPTIONS_KIND_NIC:
> + legacy.type = NET_CLIENT_DRIVER_NIC;
> + legacy.nic = opts->nic;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_USER:
> + legacy.type = NET_CLIENT_DRIVER_USER;
> + legacy.user = opts->user;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_TAP:
> + legacy.type = NET_CLIENT_DRIVER_TAP;
> + legacy.tap = opts->tap;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_L2TPV3:
> + legacy.type = NET_CLIENT_DRIVER_L2TPV3;
> + legacy.l2tpv3 = opts->l2tpv3;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_SOCKET:
> + legacy.type = NET_CLIENT_DRIVER_SOCKET;
> + legacy.socket = opts->socket;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_VDE:
> + legacy.type = NET_CLIENT_DRIVER_VDE;
> + legacy.vde = opts->vde;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_DUMP:
> + legacy.type = NET_CLIENT_DRIVER_DUMP;
> + legacy.dump = opts->dump;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_BRIDGE:
> + legacy.type = NET_CLIENT_DRIVER_BRIDGE;
> + legacy.bridge = opts->bridge;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_NETMAP:
> + legacy.type = NET_CLIENT_DRIVER_NETMAP;
> + legacy.netmap = opts->netmap;
> + break;
> + case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
> + legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
> + legacy.vhost_user = opts->vhost_user;
> + 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)");
> @@ -956,17 +993,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->nic->has_netdev) {
> peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
> }
> }
>
> - if (net_client_init_fun[opts->type](netdev, 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;
> }
> @@ -1065,7 +1102,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;
> }
> @@ -1131,7 +1168,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);
> }
>
> @@ -1150,7 +1187,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;
> @@ -1190,7 +1227,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);
>
> @@ -1203,10 +1240,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);
> }
> @@ -1220,7 +1257,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) {
> @@ -1247,7 +1284,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;
> }
> @@ -1288,7 +1325,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);
> @@ -1320,7 +1357,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);
> }
> }
> diff --git a/net/netmap.c b/net/netmap.c
> index a464618..eff9b8c 100644
> --- a/net/netmap.c
> +++ b/net/netmap.c
> @@ -417,7 +417,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,
> @@ -439,7 +439,7 @@ int net_init_netmap(const Netdev *netdev,
> const char *name, NetClientState *peer, Error **errp)
> {
> /* FIXME error_setg(errp, ...) on failure */
> - const NetdevNetmapOptions *netmap_opts = netdev->opts->netmap;
> + const NetdevNetmapOptions *netmap_opts = netdev->netmap;
> NetClientState *nc;
> NetmapPriv me;
> NetmapState *s;
> diff --git a/net/slirp.c b/net/slirp.c
> index e160b9c..055c9de 100644
> --- a/net/slirp.c
> +++ b/net/slirp.c
> @@ -126,7 +126,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,
> @@ -746,8 +746,8 @@ int net_init_slirp(const Netdev *netdev, const char *name,
> const NetdevUserOptions *user;
> const char **dnssearch;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_USER);
> - user = netdev->opts->user;
> + assert(netdev->type == NET_CLIENT_DRIVER_USER);
> + user = netdev->user;
>
> vnet = user->has_net ? g_strdup(user->net) :
> user->has_ip ? g_strdup_printf("%s/24", user->ip) :
> diff --git a/net/socket.c b/net/socket.c
> index 7f949e2..915bed2 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -346,7 +346,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,
> @@ -429,7 +429,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,
> @@ -706,8 +706,8 @@ int net_init_socket(const Netdev *netdev, const char *name,
> Error *err = NULL;
> const NetdevSocketOptions *sock;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET);
> - sock = netdev->opts->socket;
> + assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
> + sock = netdev->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 acce480..32be2a0 100644
> --- a/net/tap-win32.c
> +++ b/net/tap-win32.c
> @@ -723,7 +723,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,
> @@ -767,8 +767,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
> /* FIXME error_setg(errp, ...) on failure */
> const NetdevTapOptions *tap;
>
> - assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);
> - tap = netdev->opts->tap;
> + assert(netdev->type == NET_CLIENT_DRIVER_TAP);
> + tap = netdev->tap;
>
> if (!tap->has_ifname) {
> error_report("tap: no interface name");
> diff --git a/net/tap.c b/net/tap.c
> index aecc759..626dfca 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -221,7 +221,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;
> }
> @@ -230,7 +230,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;
> }
> @@ -239,7 +239,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);
> }
> @@ -248,7 +248,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));
>
> @@ -260,7 +260,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;
> @@ -326,14 +326,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,
> @@ -565,8 +565,8 @@ int net_init_bridge(const Netdev *netdev, const char *name,
> TAPState *s;
> int fd, vnet_hdr;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
> - bridge = netdev->opts->bridge;
> + assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE);
> + bridge = netdev->bridge;
>
> helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
> br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
> @@ -728,8 +728,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
> const char *vhostfdname;
> char ifname[128];
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
> - tap = netdev->opts->tap;
> + assert(netdev->type == NET_CLIENT_DRIVER_TAP);
> + tap = netdev->tap;
> queues = tap->has_queues ? tap->queues : 1;
> vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
>
> @@ -890,7 +890,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
> 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 0ac2525..7a6d4f0 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,
> @@ -115,8 +115,8 @@ int net_init_vde(const Netdev *netdev, const char *name,
> /* FIXME error_setg(errp, ...) on failure */
> const NetdevVdeOptions *vde;
>
> - assert(netdev->opts->kind == NET_CLIENT_OPTIONS_KIND_VDE);
> - vde = netdev->opts->vde;
> + assert(netdev->type == NET_CLIENT_DRIVER_VDE);
> + vde = netdev->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 8597ec4..fef89ca 100644
> --- a/net/vhost-user.c
> +++ b/net/vhost-user.c
> @@ -30,7 +30,7 @@ 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;
> }
>
> @@ -75,20 +75,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),
> .cleanup = vhost_user_cleanup,
> .has_vnet_hdr = vhost_user_has_vnet_hdr,
> @@ -229,8 +229,8 @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
> const NetdevVhostUserOptions *vhost_user_opts;
> CharDriverState *chr;
>
> - assert(netdev->opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
> - vhost_user_opts = netdev->opts->vhost_user;
> + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER);
> + vhost_user_opts = netdev->vhost_user;
>
> chr = net_vhost_parse_chardev(vhost_user_opts, errp);
> if (!chr) {
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 8c77220..02ccbb7 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2489,16 +2489,42 @@
> '*vhostforce': 'bool' } }
>
> ##
> -# @NetClientOptions
> +# @NetClientDriver
> #
> -# A discriminated record of network device traits.
> +# Available netdev drivers.
> +#
> +# Since 2.5
> +##
> +{ 'enum': 'NetClientDriver',
> + 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump',
> + 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
> +
> +##
> +# @NetdevBase
> +#
> +# Captures the common configuration of a network device.
> +#
> +# @id: identifier for monitor commands.
> +#
> +# @type: Specify the driver used for interpreting remaining arguments.
> +#
> +# Since 1.2
> +##
> +{ 'struct': 'NetdevBase',
> + 'data': { 'id': 'str', 'type': 'NetClientDriver' } }
> +
> +##
> +# @Netdev
> +#
> +# Captures the configuration of a network device.
> #
> # Since 1.2
> #
> # 'l2tpv3' - since 2.1
> -#
> ##
> -{ 'union': 'NetClientOptions',
> +{ 'union': 'Netdev',
> + 'base': 'NetdevBase',
> + 'discriminator': 'type',
> 'data': {
> 'none': 'NetdevNoneOptions',
> 'nic': 'NetLegacyNicOptions',
> @@ -2536,20 +2562,25 @@
> 'opts': 'NetClientOptions' } }
>
> ##
> -# @Netdev
> +# @NetClientOptions
> #
> -# 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': 'NetClientOptions',
> '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' } }
>
> ##
> # @InetSocketAddress
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-17 9:15 ` Wen Congyang
@ 2015-09-17 14:34 ` Eric Blake
2015-09-17 20:11 ` Eric Blake
0 siblings, 1 reply; 40+ messages in thread
From: Eric Blake @ 2015-09-17 14:34 UTC (permalink / raw)
To: Wen Congyang, qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
Luiz Capitulino, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, armbru, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Alexander Graf, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
[-- Attachment #1: Type: text/plain, Size: 1764 bytes --]
On 09/17/2015 03:15 AM, Wen Congyang wrote:
> On 09/10/2015 12:06 PM, Eric Blake wrote:
>> From: Kővágó, Zoltán <dirty.ice.hu@gmail.com>
>>
>> Except qapi-schema.json, this patch was generated by:
>>
>> find . -name .git -prune -o -type f \! -name '*~' -print0 | \
>> xargs -0 sed -i \
>> -e 's/NetClientOptionsKind/NetClientDriver/g' \
>> -e 's/NET_CLIENT_OPTIONS_KIND_/NET_CLIENT_DRIVER_/g' \
>> -e 's/netdev->opts/netdev/g'
>>
>> Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
>> Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
>>
>> Additional changes:
>> Rebase the patch on top of an earlier change from netdev->kind to
>> netdev->type, so that tweak no longer needed here.
>>
>> Rework so that NetdevLegacy doesn't pollute QMP command but is instead
>> copied piecewise into the new Netdev, which means that NetClientOptions
>> must still remain in qapi. Since legacy previously always rejected
>> 'hubport', we can now make that explicit by having the two unions be
>> slightly different; but that means we must manually map between the
>> two structures.
>
> I apply Markus's v8 patch and this series, make check will fail:
> TEST: tests/virtio-net-test... (pid=23648)
> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev socket,fd=6,id=hs0: Invalid parameter 'fd'
Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
to test the rest of the suite. The bug is most likely in my patches,
and will be fixed by the time I post v5, now that you've pointed it out
to me.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-17 14:34 ` Eric Blake
@ 2015-09-17 20:11 ` Eric Blake
2015-09-18 0:52 ` Wen Congyang
2015-09-18 9:03 ` Yang Hongyang
0 siblings, 2 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-17 20:11 UTC (permalink / raw)
To: Wen Congyang, qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
Luiz Capitulino, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, armbru, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Alexander Graf, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
[-- Attachment #1: Type: text/plain, Size: 1063 bytes --]
On 09/17/2015 08:34 AM, Eric Blake wrote:
>>
>> I apply Markus's v8 patch and this series, make check will fail:
>> TEST: tests/virtio-net-test... (pid=23648)
>> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev socket,fd=6,id=hs0: Invalid parameter 'fd'
>
> Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
> to test the rest of the suite. The bug is most likely in my patches,
> and will be fixed by the time I post v5, now that you've pointed it out
> to me.
Fix is simple: add this patch to your build:
https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
I've rebased my git repo accordingly for now, and will post v5 later on
(I'm still working on other improvements, and may reshuffle patches
before actually getting to v5).
git fetch git://repo.or.cz/qemu/ericb.git qapi
http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-17 20:11 ` Eric Blake
@ 2015-09-18 0:52 ` Wen Congyang
2015-09-18 6:56 ` Markus Armbruster
2015-09-18 12:36 ` Eric Blake
2015-09-18 9:03 ` Yang Hongyang
1 sibling, 2 replies; 40+ messages in thread
From: Wen Congyang @ 2015-09-18 0:52 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
Luiz Capitulino, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, armbru, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Alexander Graf, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
On 09/18/2015 04:11 AM, Eric Blake wrote:
> On 09/17/2015 08:34 AM, Eric Blake wrote:
>
>>>
>>> I apply Markus's v8 patch and this series, make check will fail:
>>> TEST: tests/virtio-net-test... (pid=23648)
>>> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev socket,fd=6,id=hs0: Invalid parameter 'fd'
>>
>> Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
>> to test the rest of the suite. The bug is most likely in my patches,
>> and will be fixed by the time I post v5, now that you've pointed it out
>> to me.
>
> Fix is simple: add this patch to your build:
>
> https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
>
> I've rebased my git repo accordingly for now, and will post v5 later on
> (I'm still working on other improvements, and may reshuffle patches
> before actually getting to v5).
>
> git fetch git://repo.or.cz/qemu/ericb.git qapi
> http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
>
OK, I will try it. What is difference between start_struct() and start_implicit_struct()?
Thanks
Wen Congyang
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-18 0:52 ` Wen Congyang
@ 2015-09-18 6:56 ` Markus Armbruster
2015-09-18 8:36 ` Wen Congyang
2015-09-18 12:37 ` Eric Blake
2015-09-18 12:36 ` Eric Blake
1 sibling, 2 replies; 40+ messages in thread
From: Markus Armbruster @ 2015-09-18 6:56 UTC (permalink / raw)
To: Wen Congyang
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, qemu-devel,
Vincenzo Maffione, Luiz Capitulino, Max Filippov, Gerd Hoffmann,
Dmitry Fleytman, Edgar E. Iglesias, Rob Herring, Alexander Graf,
Scott Feldman, dirty.ice.hu, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Peter Crosthwaite, Michael Walle,
open list:sPAPR pseries, Peter Chubb
Wen Congyang <wency@cn.fujitsu.com> writes:
> On 09/18/2015 04:11 AM, Eric Blake wrote:
>> On 09/17/2015 08:34 AM, Eric Blake wrote:
>>
>>>>
>>>> I apply Markus's v8 patch and this series, make check will fail:
>>>> TEST: tests/virtio-net-test... (pid=23648)
>>>> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev
>>>> socket,fd=6,id=hs0: Invalid parameter 'fd'
>>>
>>> Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
>>> to test the rest of the suite. The bug is most likely in my patches,
>>> and will be fixed by the time I post v5, now that you've pointed it out
>>> to me.
>>
>> Fix is simple: add this patch to your build:
>>
>> https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
>>
>> I've rebased my git repo accordingly for now, and will post v5 later on
>> (I'm still working on other improvements, and may reshuffle patches
>> before actually getting to v5).
>>
>> git fetch git://repo.or.cz/qemu/ericb.git qapi
>> http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
>>
>
> OK, I will try it. What is difference between start_struct() and
> start_implicit_struct()?
I hope to be able to answer this question next week, after taking a dive
in the (almost entirely undocumented) visitors code.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-18 6:56 ` Markus Armbruster
@ 2015-09-18 8:36 ` Wen Congyang
2015-09-18 12:37 ` Eric Blake
1 sibling, 0 replies; 40+ messages in thread
From: Wen Congyang @ 2015-09-18 8:36 UTC (permalink / raw)
To: Markus Armbruster
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, qemu-devel,
Vincenzo Maffione, Luiz Capitulino, Max Filippov, Gerd Hoffmann,
Dmitry Fleytman, Edgar E. Iglesias, Rob Herring, Alexander Graf,
Scott Feldman, dirty.ice.hu, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Peter Crosthwaite, Michael Walle,
open list:sPAPR pseries, Peter Chubb
On 09/18/2015 02:56 PM, Markus Armbruster wrote:
> Wen Congyang <wency@cn.fujitsu.com> writes:
>
>> On 09/18/2015 04:11 AM, Eric Blake wrote:
>>> On 09/17/2015 08:34 AM, Eric Blake wrote:
>>>
>>>>>
>>>>> I apply Markus's v8 patch and this series, make check will fail:
>>>>> TEST: tests/virtio-net-test... (pid=23648)
>>>>> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev
>>>>> socket,fd=6,id=hs0: Invalid parameter 'fd'
>>>>
>>>> Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
>>>> to test the rest of the suite. The bug is most likely in my patches,
>>>> and will be fixed by the time I post v5, now that you've pointed it out
>>>> to me.
>>>
>>> Fix is simple: add this patch to your build:
>>>
>>> https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
>>>
>>> I've rebased my git repo accordingly for now, and will post v5 later on
>>> (I'm still working on other improvements, and may reshuffle patches
>>> before actually getting to v5).
>>>
>>> git fetch git://repo.or.cz/qemu/ericb.git qapi
>>> http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
>>>
>>
>> OK, I will try it. What is difference between start_struct() and
>> start_implicit_struct()?
>
> I hope to be able to answer this question next week, after taking a dive
> in the (almost entirely undocumented) visitors code.
> .
>
OK. Supporting NBD driver is hard now. I hope it can be easier in the future.
Thanks
Wen Congyang
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-17 20:11 ` Eric Blake
2015-09-18 0:52 ` Wen Congyang
@ 2015-09-18 9:03 ` Yang Hongyang
2015-09-18 12:29 ` Eric Blake
1 sibling, 1 reply; 40+ messages in thread
From: Yang Hongyang @ 2015-09-18 9:03 UTC (permalink / raw)
To: qemu-devel
On 09/18/2015 04:11 AM, Eric Blake wrote:
> On 09/17/2015 08:34 AM, Eric Blake wrote:
>
>>>
>>> I apply Markus's v8 patch and this series, make check will fail:
>>> TEST: tests/virtio-net-test... (pid=23648)
>>> /x86_64/virtio/net/pci/basic: qemu-system-x86_64: -netdev socket,fd=6,id=hs0: Invalid parameter 'fd'
>>
>> Oh dear. I guess I was focused on 'make check-qapi-schema', and forgot
>> to test the rest of the suite. The bug is most likely in my patches,
>> and will be fixed by the time I post v5, now that you've pointed it out
>> to me.
>
> Fix is simple: add this patch to your build:
>
> https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
>
> I've rebased my git repo accordingly for now, and will post v5 later on
> (I'm still working on other improvements, and may reshuffle patches
> before actually getting to v5).
>
> git fetch git://repo.or.cz/qemu/ericb.git qapi
> http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
I have to add a workaround in my previous netfilter v9 patchset(v10 and later
changed to QOM, so it won't have the problem) to get flat union work. Seems that
you have already fixed it.
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 7ae33b3..1271fab 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -186,6 +186,20 @@ opts_end_struct(Visitor *v, Error **errp)
}
+static void opts_start_implicit_struct(Visitor *v, void **obj,
+ size_t size, Error **errp)
+{
+ if (obj) {
+ *obj = g_malloc0(size);
+ }
+}
+
+
+static void opts_end_implicit_struct(Visitor *v, Error **errp)
+{
+}
+
+
static GQueue *
lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp)
{
@@ -507,6 +521,8 @@ opts_visitor_new(const QemuOpts *opts)
ov->visitor.start_struct = &opts_start_struct;
ov->visitor.end_struct = &opts_end_struct;
+ ov->visitor.start_implicit_struct = &opts_start_implicit_struct;
+ ov->visitor.end_implicit_struct = &opts_end_implicit_struct;
ov->visitor.start_list = &opts_start_list;
ov->visitor.next_list = &opts_next_list;
>
--
Thanks,
Yang.
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-18 9:03 ` Yang Hongyang
@ 2015-09-18 12:29 ` Eric Blake
0 siblings, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-18 12:29 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel, Kővágó, Zoltán
[-- Attachment #1: Type: text/plain, Size: 2010 bytes --]
On 09/18/2015 03:03 AM, Yang Hongyang wrote:
>> Fix is simple: add this patch to your build:
>>
>> https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01650.html
>>
>> I've rebased my git repo accordingly for now, and will post v5 later on
>> (I'm still working on other improvements, and may reshuffle patches
>> before actually getting to v5).
>>
>> git fetch git://repo.or.cz/qemu/ericb.git qapi
>> http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi
>
> I have to add a workaround in my previous netfilter v9 patchset(v10 and
> later
> changed to QOM, so it won't have the problem) to get flat union work.
> Seems that
> you have already fixed it.
Rather, Zoltán found it, and I just realized why it was important. Your
alternative is a bit simpler in implementation, though.
>
> diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
> index 7ae33b3..1271fab 100644
> --- a/qapi/opts-visitor.c
> +++ b/qapi/opts-visitor.c
> @@ -186,6 +186,20 @@ opts_end_struct(Visitor *v, Error **errp)
> }
>
>
> +static void opts_start_implicit_struct(Visitor *v, void **obj,
> + size_t size, Error **errp)
> +{
> + if (obj) {
> + *obj = g_malloc0(size);
> + }
> +}
> +
> +
> +static void opts_end_implicit_struct(Visitor *v, Error **errp)
> +{
> +}
> +
> +
> static GQueue *
> lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp)
> {
> @@ -507,6 +521,8 @@ opts_visitor_new(const QemuOpts *opts)
>
> ov->visitor.start_struct = &opts_start_struct;
> ov->visitor.end_struct = &opts_end_struct;
> + ov->visitor.start_implicit_struct = &opts_start_implicit_struct;
> + ov->visitor.end_implicit_struct = &opts_end_implicit_struct;
>
> ov->visitor.start_list = &opts_start_list;
> ov->visitor.next_list = &opts_next_list;
>
>>
>
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-18 0:52 ` Wen Congyang
2015-09-18 6:56 ` Markus Armbruster
@ 2015-09-18 12:36 ` Eric Blake
1 sibling, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-18 12:36 UTC (permalink / raw)
To: Wen Congyang, qemu-devel
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, Vincenzo Maffione,
Luiz Capitulino, Max Filippov, Gerd Hoffmann, Dmitry Fleytman,
Edgar E. Iglesias, Rob Herring, armbru, Scott Feldman,
Kővágó, Zoltán, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Alexander Graf, Peter Crosthwaite,
Michael Walle, open list:sPAPR pseries, Peter Chubb
[-- Attachment #1: Type: text/plain, Size: 1395 bytes --]
On 09/17/2015 06:52 PM, Wen Congyang wrote:
>>
>
> OK, I will try it. What is difference between start_struct() and start_implicit_struct()?
If you have the following QDict:
{ "a":1, "b":2", "c:3" }
start_struct() corresponds to the {, and end_struct() corresponds to the
}. If the corresponding qapi type is completely inline, then that's all
the more you need:
struct Foo {
int a;
int b;
int c;
};
But oftentimes, we want some sub-structure in our qapi types. So
suppose we want to always parse 'b' and 'c' together, in a reusable
struct, as in:
struct Bar {
int b;
int c;
};
struct Foo {
int a;
Bar *sub;
}
With the above representation, we can do a boxed visit by using only
start_struct()/end_struct(), but it maps to two levels of {} nesting, as in:
{ "a":1, "sub":{ "b":2, "c":3 } }
But sometimes we want the C struct nesting while still keeping the QDict
representation flat. And that's where start_implicit_struct() enters
the picture. It says to start a new C struct while still keeping the
QDict nesting unchanged.
Right now, we use implicit structs for 'base' types and for flat unions,
although some of my pending qapi patches get rid of the use of implicit
structs for base types.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union
2015-09-18 6:56 ` Markus Armbruster
2015-09-18 8:36 ` Wen Congyang
@ 2015-09-18 12:37 ` Eric Blake
1 sibling, 0 replies; 40+ messages in thread
From: Eric Blake @ 2015-09-18 12:37 UTC (permalink / raw)
To: Markus Armbruster, Wen Congyang
Cc: Peter Maydell, Michael S. Tsirkin, Jason Wang, qemu-devel,
Vincenzo Maffione, Luiz Capitulino, Max Filippov, Gerd Hoffmann,
Dmitry Fleytman, Edgar E. Iglesias, Rob Herring, Alexander Graf,
Scott Feldman, dirty.ice.hu, marcandre.lureau, Jiri Pirko,
Alistair Francis, Jan Kiszka, Stefan Hajnoczi, Giuseppe Lettieri,
Luigi Rizzo, David Gibson, Peter Crosthwaite, Michael Walle,
open list:sPAPR pseries, Peter Chubb
[-- Attachment #1: Type: text/plain, Size: 697 bytes --]
On 09/18/2015 12:56 AM, Markus Armbruster wrote:
>> OK, I will try it. What is difference between start_struct() and
>> start_implicit_struct()?
>
> I hope to be able to answer this question next week, after taking a dive
> in the (almost entirely undocumented) visitors code.
It's not quite undocumented any more; some of my pending patches have
started tackling the documentation aspect:
https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg02597.html
as well as cleaning up some of the cruft:
https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg02595.html
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2015-09-18 12:37 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-10 4:06 [Qemu-devel] [PATCH RFC v4 00/29] qapi-ify netdev_add, and other post-introspection cleanups Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 01/29] qapi: Provide nicer array names in introspection Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 02/29] net: use Netdev instead of NetClientOptions in client init Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 03/29] qapi: use 'type' in generated C code to match QMP union wire form Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 04/29] vnc: hoist allocation of VncBasicInfo to callers Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 05/29] qapi: Unbox base members Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 06/29] qapi-visit: Remove redundant functions for flat union base Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 07/29] qapi: Test use of 'number' within alternates Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 08/29] qapi: Simplify visiting of alternate types Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 09/29] qapi: Hide tag_name data member of variants Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 10/29] qapi: Fix alternates that accept 'number' but not 'int' Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 11/29] qapi: Don't pass pre-existing error to later call Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 12/29] qapi: Use consistent generated code patterns Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 13/29] qapi: Add tests for empty unions Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 14/29] qapi: Rework deallocation of partial struct Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 15/29] qapi: Avoid use of 'data' member of qapi unions Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 16/29] qapi: Forbid empty unions and useless alternates Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 17/29] qapi: Drop useless 'data' member of unions Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 18/29] qapi: Remove dead visitor code Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 19/29] qapi: Document visitor interfaces Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 20/29] qapi: Plug leaks in test-qmp-input-visitor Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 21/29] qapi: Test failure in middle of array parse Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 22/29] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 23/29] qapi: Plumb in 'box' to qapi generator lower levels Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 24/29] qapi: Implement boxed structs for commands/events Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 25/29] qapi: Support boxed unions Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 26/29] qapi: Clean up qapi.py per pep8 Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 27/29] qapi: Change Netdev into a flat union Eric Blake
2015-09-17 9:15 ` Wen Congyang
2015-09-17 14:34 ` Eric Blake
2015-09-17 20:11 ` Eric Blake
2015-09-18 0:52 ` Wen Congyang
2015-09-18 6:56 ` Markus Armbruster
2015-09-18 8:36 ` Wen Congyang
2015-09-18 12:37 ` Eric Blake
2015-09-18 12:36 ` Eric Blake
2015-09-18 9:03 ` Yang Hongyang
2015-09-18 12:29 ` Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 28/29] net: Use correct type for bool flag Eric Blake
2015-09-10 4:06 ` [Qemu-devel] [PATCH RFC v4 29/29] net: Complete qapi-fication of netdev_add Eric Blake
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).