From 837c36e7871a74dda78d2ca89d9027b19553a871 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 20 Jul 2012 14:29:24 +0100 Subject: [PATCH 01/19] MAINTAINERS: Replace net maintainer Mark McLoughlin with Stefan Hajnoczi The net subsystem has lacked an active maintainer since 2009. I have built and tested a net-next tree to get the ball rolling again. Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 30ed56dd77..2d219d2ea0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -560,9 +560,10 @@ F: monitor.c Network device layer M: Anthony Liguori -M: Mark McLoughlin +M: Stefan Hajnoczi S: Maintained F: net/ +T: git git://github.com/stefanha/qemu.git net Network Block Device (NBD) M: Paolo Bonzini From d195325b05199038b5907fa791729425b9720d21 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Jul 2012 16:17:04 +0200 Subject: [PATCH 02/19] qapi: fix error propagation Don't overwrite / leak previously set errors. Make traversal cope with missing mandatory sub-structs. Don't try to end a container that could not be started. v1->v2: - unchanged v2->v3: - instead of examining, assert that we never overwrite errors with error_set() - allow visitors to set a NULL struct pointer successfully, so traversal of incomplete objects can continue - check for a NULL "obj" before accessing "(*obj)->has_XXX" (this is not a typo, "obj != NULL" implies "*obj != NULL" here) - fix start_struct / end_struct balance for unions as well Signed-off-by: Paolo Bonzini Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- docs/qapi-code-gen.txt | 2 + error.c | 3 +- error.h | 2 +- qapi/qapi-visit-core.c | 10 +-- scripts/qapi-visit.py | 150 +++++++++++++++++++++------------ tests/test-qmp-input-visitor.c | 22 +++-- 6 files changed, 120 insertions(+), 69 deletions(-) diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index ad11767a2f..cccb11e562 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -220,6 +220,8 @@ Example: #endif mdroth@illuin:~/w/qemu2.git$ +(The actual structure of the visit_type_* functions is a bit more complex +in order to propagate errors correctly and avoid leaking memory). === scripts/qapi-commands.py === diff --git a/error.c b/error.c index a52b7710d2..58f55a012e 100644 --- a/error.c +++ b/error.c @@ -32,6 +32,7 @@ void error_set(Error **errp, const char *fmt, ...) if (errp == NULL) { return; } + assert(*errp == NULL); err = g_malloc0(sizeof(*err)); @@ -132,7 +133,7 @@ bool error_is_type(Error *err, const char *fmt) void error_propagate(Error **dst_err, Error *local_err) { - if (dst_err) { + if (dst_err && !*dst_err) { *dst_err = local_err; } else if (local_err) { error_free(local_err); diff --git a/error.h b/error.h index 45ff6c1ffe..3d9d96def0 100644 --- a/error.h +++ b/error.h @@ -57,7 +57,7 @@ void error_set_field(Error *err, const char *field, const char *value); /** * Propagate an error to an indirect pointer to an error. This function will * always transfer ownership of the error reference and handles the case where - * dst_err is NULL correctly. + * dst_err is NULL correctly. Errors after the first are discarded. */ void error_propagate(Error **dst_err, Error *local_err); diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 705eca90aa..d41595eaa1 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -39,9 +39,8 @@ void visit_start_struct(Visitor *v, void **obj, const char *kind, void visit_end_struct(Visitor *v, Error **errp) { - if (!error_is_set(errp)) { - v->end_struct(v, errp); - } + assert(!error_is_set(errp)); + v->end_struct(v, errp); } void visit_start_list(Visitor *v, const char *name, Error **errp) @@ -62,9 +61,8 @@ GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp) void visit_end_list(Visitor *v, Error **errp) { - if (!error_is_set(errp)) { - v->end_list(v, errp); - } + assert(!error_is_set(errp)); + v->end_list(v, errp); } void visit_start_optional(Visitor *v, bool *present, const char *name, diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 8d4e94a45f..04ef7c41ab 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -17,32 +17,49 @@ import os import getopt import errno -def generate_visit_struct_body(field_prefix, members): - ret = "" +def generate_visit_struct_body(field_prefix, name, members): + ret = mcgen(''' +if (!error_is_set(errp)) { +''') + push_indent() + if len(field_prefix): field_prefix = field_prefix + "." + ret += mcgen(''' +Error **errp = &err; /* from outer scope */ +Error *err = NULL; +visit_start_struct(m, NULL, "", "%(name)s", 0, &err); +''', + name=name) + else: + ret += mcgen(''' +Error *err = NULL; +visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); +''', + name=name) + + ret += mcgen(''' +if (!err) { + if (!obj || *obj) { +''') + + push_indent() + push_indent() for argname, argentry, optional, structured in parse_args(members): if optional: ret += mcgen(''' -visit_start_optional(m, (obj && *obj) ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", errp); -if ((*obj)->%(prefix)shas_%(c_name)s) { +visit_start_optional(m, obj ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", &err); +if (obj && (*obj)->%(prefix)shas_%(c_name)s) { ''', c_prefix=c_var(field_prefix), prefix=field_prefix, c_name=c_var(argname), name=argname) push_indent() if structured: - ret += mcgen(''' -visit_start_struct(m, NULL, "", "%(name)s", 0, errp); -''', - name=argname) - ret += generate_visit_struct_body(field_prefix + argname, argentry) - ret += mcgen(''' -visit_end_struct(m, errp); -''') + ret += generate_visit_struct_body(field_prefix + argname, argname, argentry) else: ret += mcgen(''' -visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", errp); +visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); ''', c_prefix=c_var(field_prefix), prefix=field_prefix, type=type_name(argentry), c_name=c_var(argname), @@ -52,7 +69,25 @@ visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, " pop_indent() ret += mcgen(''' } -visit_end_optional(m, errp); +visit_end_optional(m, &err); +''') + + pop_indent() + ret += mcgen(''' + + error_propagate(errp, err); + err = NULL; +} +''') + + pop_indent() + pop_indent() + ret += mcgen(''' + /* Always call end_struct if start_struct succeeded. */ + visit_end_struct(m, &err); + } + error_propagate(errp, err); +} ''') return ret @@ -61,22 +96,14 @@ def generate_visit_struct(name, members): void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) { - if (error_is_set(errp)) { - return; - } - visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp); - if (obj && !*obj) { - goto end; - } ''', name=name) + push_indent() - ret += generate_visit_struct_body("", members) + ret += generate_visit_struct_body("", name, members) pop_indent() ret += mcgen(''' -end: - visit_end_struct(m, errp); } ''') return ret @@ -87,18 +114,23 @@ def generate_visit_list(name, members): void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp) { GenericList *i, **prev = (GenericList **)obj; + Error *err = NULL; - if (error_is_set(errp)) { - return; + if (!error_is_set(errp)) { + visit_start_list(m, name, &err); + if (!err) { + for (; (i = visit_next_list(m, prev, &err)) != NULL; prev = &i) { + %(name)sList *native_i = (%(name)sList *)i; + visit_type_%(name)s(m, &native_i->value, NULL, &err); + } + error_propagate(errp, err); + err = NULL; + + /* Always call end_list if start_list succeeded. */ + visit_end_list(m, &err); + } + error_propagate(errp, err); } - visit_start_list(m, name, errp); - - for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) { - %(name)sList *native_i = (%(name)sList *)i; - visit_type_%(name)s(m, &native_i->value, NULL, errp); - } - - visit_end_list(m, errp); } ''', name=name) @@ -122,27 +154,23 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** { Error *err = NULL; - if (error_is_set(errp)) { - return; - } - visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); - if (obj && !*obj) { - goto end; - } - visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); - if (err) { - error_propagate(errp, err); - goto end; - } - switch ((*obj)->kind) { + if (!error_is_set(errp)) { + visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); + if (!err) { + if (!obj || *obj) { + visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); + if (!err) { + switch ((*obj)->kind) { ''', name=name) + push_indent() + push_indent() for key in members: ret += mcgen(''' - case %(abbrev)s_KIND_%(enum)s: - visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", errp); - break; + case %(abbrev)s_KIND_%(enum)s: + visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err); + break; ''', abbrev = de_camel_case(name).upper(), enum = c_fun(de_camel_case(key)).upper(), @@ -150,11 +178,25 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** c_name=c_fun(key)) ret += mcgen(''' - default: - abort(); + default: + abort(); + } + } + error_propagate(errp, err); + err = NULL; } -end: - visit_end_struct(m, errp); +''') + pop_indent() + ret += mcgen(''' + /* Always call end_struct if start_struct succeeded. */ + visit_end_struct(m, &err); + } + error_propagate(errp, err); +} +''') + + pop_indent(); + ret += mcgen(''' } ''') diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index c30fdc4e59..8f5a509582 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -151,14 +151,22 @@ typedef struct TestStruct static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp) { - visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), - errp); + Error *err = NULL; + if (!error_is_set(errp)) { + visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), + &err); + if (!err) { + visit_type_int(v, &(*obj)->integer, "integer", &err); + visit_type_bool(v, &(*obj)->boolean, "boolean", &err); + visit_type_str(v, &(*obj)->string, "string", &err); - visit_type_int(v, &(*obj)->integer, "integer", errp); - visit_type_bool(v, &(*obj)->boolean, "boolean", errp); - visit_type_str(v, &(*obj)->string, "string", errp); - - visit_end_struct(v, errp); + /* Always call end_struct if start_struct succeeded. */ + error_propagate(errp, err); + err = NULL; + visit_end_struct(v, &err); + } + error_propagate(errp, err); + } } static void test_visitor_in_struct(TestInputVisitorData *data, From d98150f0522890046b3cc699552a3c94d9645cb6 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:05 +0200 Subject: [PATCH 03/19] qapi: add test case for deallocating traversal of incomplete structure v3: - new patch Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- tests/test-qmp-commands.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index 60cbf019bb..dc3c507f2b 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -3,6 +3,9 @@ #include "test-qmp-commands.h" #include "qapi/qmp-core.h" #include "module.h" +#include "qapi/qmp-input-visitor.h" +#include "tests/test-qapi-types.h" +#include "tests/test-qapi-visit.h" void qmp_user_def_cmd(Error **errp) { @@ -123,6 +126,44 @@ static void test_dealloc_types(void) qapi_free_UserDefOneList(ud1list); } +/* test generated deallocation on an object whose construction was prematurely + * terminated due to an error */ +static void test_dealloc_partial(void) +{ + static const char text[] = "don't leak me"; + + UserDefTwo *ud2 = NULL; + Error *err = NULL; + + /* create partial object */ + { + QDict *ud2_dict; + QmpInputVisitor *qiv; + + ud2_dict = qdict_new(); + qdict_put_obj(ud2_dict, "string", QOBJECT(qstring_from_str(text))); + + qiv = qmp_input_visitor_new(QOBJECT(ud2_dict)); + visit_type_UserDefTwo(qmp_input_get_visitor(qiv), &ud2, NULL, &err); + qmp_input_visitor_cleanup(qiv); + QDECREF(ud2_dict); + } + + /* verify partial success */ + assert(ud2 != NULL); + assert(ud2->string != NULL); + assert(strcmp(ud2->string, text) == 0); + assert(ud2->dict.dict.userdef == NULL); + + /* confirm & release construction error */ + assert(err != NULL); + error_free(err); + + /* tear down partial object */ + qapi_free_UserDefTwo(ud2); +} + + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -131,6 +172,7 @@ int main(int argc, char **argv) g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error); g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io); g_test_add_func("/0.15/dealloc_types", test_dealloc_types); + g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial); module_call_init(MODULE_INIT_QAPI); g_test_run(); From c46f18ce2b6dae531d72f61cf8441110c7936e70 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:06 +0200 Subject: [PATCH 04/19] qapi: generate C types for fixed-width integers (Long line folded using parens: .) Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- scripts/qapi.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/qapi.py b/scripts/qapi.py index e06233666b..1292476a7d 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -159,6 +159,10 @@ def c_type(name): return 'char *' elif name == 'int': return 'int64_t' + elif (name == 'int8' or name == 'int16' or name == 'int32' or + name == 'int64' or name == 'uint8' or name == 'uint16' or + name == 'uint32' or name == 'uint64'): + return name + '_t' elif name == 'bool': return 'bool' elif name == 'number': From 092705d4eb6779060661c8d521d0314e9571773f Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:07 +0200 Subject: [PATCH 05/19] qapi: introduce "size" type v1->v2: - fall back to uint64 rather than int Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- qapi/qapi-visit-core.c | 7 +++++++ qapi/qapi-visit-core.h | 3 +++ scripts/qapi.py | 2 ++ 3 files changed, 12 insertions(+) diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index d41595eaa1..7a82b63766 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -234,6 +234,13 @@ 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) +{ + if (!error_is_set(errp)) { + (v->type_size ? v->type_size : v->type_uint64)(v, obj, name, errp); + } +} + void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) { if (!error_is_set(errp)) { diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h index a19d70c104..60acedac77 100644 --- a/qapi/qapi-visit-core.h +++ b/qapi/qapi-visit-core.h @@ -60,6 +60,8 @@ struct Visitor 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); }; void visit_start_handle(Visitor *v, void **obj, const char *kind, @@ -85,6 +87,7 @@ 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); 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); diff --git a/scripts/qapi.py b/scripts/qapi.py index 1292476a7d..8082af3fcd 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -163,6 +163,8 @@ def c_type(name): name == 'int64' or name == 'uint8' or name == 'uint16' or name == 'uint32' or name == 'uint64'): return name + '_t' + elif name == 'size': + return 'uint64_t' elif name == 'bool': return 'bool' elif name == 'number': From fdb17976fc1b8cff02b52b1054562d220b9208c7 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:08 +0200 Subject: [PATCH 06/19] expose QemuOpt and QemuOpts struct definitions to interested parties The only clients should be the existent "qemu-option.c", and the upcoming "qapi/opts-visitor.c". Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- qemu-option-internal.h | 53 ++++++++++++++++++++++++++++++++++++++++++ qemu-option.c | 24 +------------------ 2 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 qemu-option-internal.h diff --git a/qemu-option-internal.h b/qemu-option-internal.h new file mode 100644 index 0000000000..19fdc1ca85 --- /dev/null +++ b/qemu-option-internal.h @@ -0,0 +1,53 @@ +/* + * Commandline option parsing functions + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2009 Kevin Wolf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef QEMU_OPTIONS_INTERNAL_H +#define QEMU_OPTIONS_INTERNAL_H + +#include "qemu-option.h" + +struct QemuOpt { + const char *name; + const char *str; + + const QemuOptDesc *desc; + union { + bool boolean; + uint64_t uint; + } value; + + QemuOpts *opts; + QTAILQ_ENTRY(QemuOpt) next; +}; + +struct QemuOpts { + char *id; + QemuOptsList *list; + Location loc; + QTAILQ_HEAD(QemuOptHead, QemuOpt) head; + QTAILQ_ENTRY(QemuOpts) next; +}; + +#endif diff --git a/qemu-option.c b/qemu-option.c index bb3886c6b9..8334190c53 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -29,9 +29,9 @@ #include "qemu-common.h" #include "qemu-error.h" #include "qemu-objects.h" -#include "qemu-option.h" #include "error.h" #include "qerror.h" +#include "qemu-option-internal.h" /* * Extracts the name of an option from the parameter string (p points at the @@ -511,28 +511,6 @@ void print_option_help(QEMUOptionParameter *list) /* ------------------------------------------------------------------ */ -struct QemuOpt { - const char *name; - const char *str; - - const QemuOptDesc *desc; - union { - bool boolean; - uint64_t uint; - } value; - - QemuOpts *opts; - QTAILQ_ENTRY(QemuOpt) next; -}; - -struct QemuOpts { - char *id; - QemuOptsList *list; - Location loc; - QTAILQ_HEAD(QemuOptHead, QemuOpt) head; - QTAILQ_ENTRY(QemuOpts) next; -}; - static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name) { QemuOpt *opt; From eb7ee2cbebe4ac9e687d5fb3c104f0220d26cdfc Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:09 +0200 Subject: [PATCH 07/19] qapi: introduce OptsVisitor This visitor supports parsing -option [type=]discriminator[,optarg1=val1][,optarg2=val2][,...] style QemuOpts objects into "native" C structures. After defining the type tree in the qapi schema (see below), a root type traversal with this visitor linked to the underlying QemuOpts object will build the "native" C representation of the option. The type tree in the schema, corresponding to an option with a discriminator, must have the following structure: struct scalar member for non-discriminated optarg 1 [*] list for repeating non-discriminated optarg 2 [*] wrapper struct single scalar member union struct for discriminator case 1 scalar member for optarg 3 [*] list for repeating optarg 4 [*] wrapper struct single scalar member scalar member for optarg 5 [*] struct for discriminator case 2 ... The "type" optarg name is fixed for the discriminator role. Its schema representation is "union of structures", and each discriminator value must correspond to a member name in the union. If the option takes no "type" descriminator, then the type subtree rooted at the union must be absent from the schema (including the union itself). Optarg values can be of scalar types str / bool / integers / size. Members marked with [*] may be defined as optional in the schema, describing an optional optarg. Repeating an optarg is supported; its schema representation must be "list of structure with single mandatory scalar member". If an optarg is not described as repeating in the schema (ie. it is defined as a scalar field instead of a list), its last occurrence will take effect. Ordering between differently named optargs is not preserved. A mandatory list (or an optional one which is reported to be available), corresponding to a repeating optarg, has at least one element after successful parsing. v1->v2: - Update opts_type_size() prototype to uint64_t. - Add opts_type_uint64() for options needing the full uint64_t range. (Internals could be extracted to "cutils.c".) - Allow negative values in opts_type_int(). - Rebase to nested Makefiles. v2->v3: - Factor opts_visitor_insert() out of opts_start_struct() and call it separately for opts_root->id if there's any. - Don't require non-negative values in opts_type_int()'s error message. - g_malloc0() may return NULL for zero-sized requests. Support empty structures by requesting 1 byte for them instead. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- qapi/Makefile.objs | 2 +- qapi/opts-visitor.c | 427 ++++++++++++++++++++++++++++++++++++++++++++ qapi/opts-visitor.h | 31 ++++ 3 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 qapi/opts-visitor.c create mode 100644 qapi/opts-visitor.h diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index d0b0c16b90..5f5846e767 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -1,3 +1,3 @@ qapi-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o qapi-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o -qapi-obj-y += string-input-visitor.o string-output-visitor.o +qapi-obj-y += string-input-visitor.o string-output-visitor.o opts-visitor.o diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c new file mode 100644 index 0000000000..a59d306e46 --- /dev/null +++ b/qapi/opts-visitor.c @@ -0,0 +1,427 @@ +/* + * Options Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Laszlo Ersek + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "opts-visitor.h" +#include "qemu-queue.h" +#include "qemu-option-internal.h" +#include "qapi-visit-impl.h" + + +struct OptsVisitor +{ + Visitor visitor; + + /* Ownership remains with opts_visitor_new()'s caller. */ + const QemuOpts *opts_root; + + unsigned depth; + + /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value + * is a non-empty GQueue, enumerating all QemuOpt occurrences with that + * name. */ + GHashTable *unprocessed_opts; + + /* The list currently being traversed with opts_start_list() / + * opts_next_list(). The list must have a struct element type in the + * schema, with a single mandatory scalar member. */ + GQueue *repeated_opts; + bool repeated_opts_first; + + /* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for + * uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does + * not survive or escape the OptsVisitor object. + */ + QemuOpt *fake_id_opt; +}; + + +static void +destroy_list(gpointer list) +{ + g_queue_free(list); +} + + +static void +opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) +{ + GQueue *list; + + list = g_hash_table_lookup(unprocessed_opts, opt->name); + if (list == NULL) { + list = g_queue_new(); + + /* GHashTable will never try to free the keys -- we supply NULL as + * "key_destroy_func" in opts_start_struct(). Thus cast away key + * const-ness in order to suppress gcc's warning. + */ + g_hash_table_insert(unprocessed_opts, (gpointer)opt->name, list); + } + + /* Similarly, destroy_list() doesn't call g_queue_free_full(). */ + g_queue_push_tail(list, (gpointer)opt); +} + + +static void +opts_start_struct(Visitor *v, void **obj, const char *kind, + const char *name, size_t size, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + + *obj = g_malloc0(size > 0 ? size : 1); + if (ov->depth++ > 0) { + return; + } + + ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal, + NULL, &destroy_list); + QTAILQ_FOREACH(opt, &ov->opts_root->head, next) { + /* ensured by qemu-option.c::opts_do_parse() */ + assert(strcmp(opt->name, "id") != 0); + + opts_visitor_insert(ov->unprocessed_opts, opt); + } + + if (ov->opts_root->id != NULL) { + ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt); + + ov->fake_id_opt->name = "id"; + ov->fake_id_opt->str = ov->opts_root->id; + opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt); + } +} + + +static gboolean +ghr_true(gpointer ign_key, gpointer ign_value, gpointer ign_user_data) +{ + return TRUE; +} + + +static void +opts_end_struct(Visitor *v, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + GQueue *any; + + if (--ov->depth > 0) { + return; + } + + /* we should have processed all (distinct) QemuOpt instances */ + any = g_hash_table_find(ov->unprocessed_opts, &ghr_true, NULL); + if (any) { + const QemuOpt *first; + + first = g_queue_peek_head(any); + error_set(errp, QERR_INVALID_PARAMETER, first->name); + } + g_hash_table_destroy(ov->unprocessed_opts); + ov->unprocessed_opts = NULL; + g_free(ov->fake_id_opt); + ov->fake_id_opt = NULL; +} + + +static GQueue * +lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) +{ + GQueue *list; + + list = g_hash_table_lookup(ov->unprocessed_opts, name); + if (!list) { + error_set(errp, QERR_MISSING_PARAMETER, name); + } + return list; +} + + +static void +opts_start_list(Visitor *v, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + + /* we can't traverse a list in a list */ + assert(ov->repeated_opts == NULL); + ov->repeated_opts = lookup_distinct(ov, name, errp); + ov->repeated_opts_first = (ov->repeated_opts != NULL); +} + + +static GenericList * +opts_next_list(Visitor *v, GenericList **list, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + GenericList **link; + + if (ov->repeated_opts_first) { + ov->repeated_opts_first = false; + link = list; + } else { + const QemuOpt *opt; + + opt = g_queue_pop_head(ov->repeated_opts); + if (g_queue_is_empty(ov->repeated_opts)) { + g_hash_table_remove(ov->unprocessed_opts, opt->name); + return NULL; + } + link = &(*list)->next; + } + + *link = g_malloc0(sizeof **link); + return *link; +} + + +static void +opts_end_list(Visitor *v, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + + ov->repeated_opts = NULL; +} + + +static const QemuOpt * +lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) +{ + if (ov->repeated_opts == NULL) { + GQueue *list; + + /* the last occurrence of any QemuOpt takes effect when queried by name + */ + list = lookup_distinct(ov, name, errp); + return list ? g_queue_peek_tail(list) : NULL; + } + return g_queue_peek_head(ov->repeated_opts); +} + + +static void +processed(OptsVisitor *ov, const char *name) +{ + if (ov->repeated_opts == NULL) { + g_hash_table_remove(ov->unprocessed_opts, name); + } +} + + +static void +opts_type_str(Visitor *v, char **obj, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return; + } + *obj = g_strdup(opt->str ? opt->str : ""); + processed(ov, name); +} + + +/* mimics qemu-option.c::parse_option_bool() */ +static void +opts_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return; + } + + if (opt->str) { + if (strcmp(opt->str, "on") == 0 || + strcmp(opt->str, "yes") == 0 || + strcmp(opt->str, "y") == 0) { + *obj = true; + } else if (strcmp(opt->str, "off") == 0 || + strcmp(opt->str, "no") == 0 || + strcmp(opt->str, "n") == 0) { + *obj = false; + } else { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + "on|yes|y|off|no|n"); + return; + } + } else { + *obj = true; + } + + processed(ov, name); +} + + +static void +opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + const char *str; + long long val; + char *endptr; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return; + } + str = opt->str ? opt->str : ""; + + errno = 0; + val = strtoll(str, &endptr, 0); + if (*str != '\0' && *endptr == '\0' && errno == 0 && INT64_MIN <= val && + val <= INT64_MAX) { + *obj = val; + processed(ov, name); + return; + } + error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, "an int64 value"); +} + + +static void +opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + const char *str; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return; + } + + str = opt->str; + if (str != NULL) { + while (isspace((unsigned char)*str)) { + ++str; + } + + if (*str != '-' && *str != '\0') { + unsigned long long val; + char *endptr; + + /* non-empty, non-negative subject sequence */ + errno = 0; + val = strtoull(str, &endptr, 0); + if (*endptr == '\0' && errno == 0 && val <= UINT64_MAX) { + *obj = val; + processed(ov, name); + return; + } + } + } + error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + "an uint64 value"); +} + + +static void +opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + const QemuOpt *opt; + int64_t val; + char *endptr; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return; + } + + val = strtosz_suffix(opt->str ? opt->str : "", &endptr, + STRTOSZ_DEFSUFFIX_B); + if (val != -1 && *endptr == '\0') { + *obj = val; + processed(ov, name); + return; + } + error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + "a size value representible as a non-negative int64"); +} + + +static void +opts_start_optional(Visitor *v, bool *present, const char *name, + Error **errp) +{ + OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v); + + /* we only support a single mandatory scalar field in a list node */ + assert(ov->repeated_opts == NULL); + *present = (lookup_distinct(ov, name, NULL) != NULL); +} + + +OptsVisitor * +opts_visitor_new(const QemuOpts *opts) +{ + OptsVisitor *ov; + + ov = g_malloc0(sizeof *ov); + + ov->visitor.start_struct = &opts_start_struct; + ov->visitor.end_struct = &opts_end_struct; + + ov->visitor.start_list = &opts_start_list; + ov->visitor.next_list = &opts_next_list; + ov->visitor.end_list = &opts_end_list; + + /* input_type_enum() covers both "normal" enums and union discriminators. + * The union discriminator field is always generated as "type"; it should + * match the "type" QemuOpt child of any QemuOpts. + * + * input_type_enum() will remove the looked-up key from the + * "unprocessed_opts" hash even if the lookup fails, because the removal is + * done earlier in opts_type_str(). This should be harmless. + */ + ov->visitor.type_enum = &input_type_enum; + + ov->visitor.type_int = &opts_type_int; + ov->visitor.type_uint64 = &opts_type_uint64; + ov->visitor.type_size = &opts_type_size; + ov->visitor.type_bool = &opts_type_bool; + ov->visitor.type_str = &opts_type_str; + + /* type_number() is not filled in, but this is not the first visitor to + * skip some mandatory methods... */ + + ov->visitor.start_optional = &opts_start_optional; + + ov->opts_root = opts; + + return ov; +} + + +void +opts_visitor_cleanup(OptsVisitor *ov) +{ + if (ov->unprocessed_opts != NULL) { + g_hash_table_destroy(ov->unprocessed_opts); + } + g_free(ov->fake_id_opt); + memset(ov, '\0', sizeof *ov); +} + + +Visitor * +opts_get_visitor(OptsVisitor *ov) +{ + return &ov->visitor; +} diff --git a/qapi/opts-visitor.h b/qapi/opts-visitor.h new file mode 100644 index 0000000000..ea1a395573 --- /dev/null +++ b/qapi/opts-visitor.h @@ -0,0 +1,31 @@ +/* + * Options Visitor + * + * Copyright Red Hat, Inc. 2012 + * + * Author: Laszlo Ersek + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef OPTS_VISITOR_H +#define OPTS_VISITOR_H + +#include "qapi-visit-core.h" +#include "qemu-option.h" + +typedef struct OptsVisitor OptsVisitor; + +/* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int" + * parser relies on strtoll() instead of strtoull(). Consequences: + * - string representations of negative numbers yield negative values, + * - values below INT64_MIN or LLONG_MIN are rejected, + * - values above INT64_MAX or LLONG_MAX are rejected. + */ +OptsVisitor *opts_visitor_new(const QemuOpts *opts); +void opts_visitor_cleanup(OptsVisitor *nv); +Visitor *opts_get_visitor(OptsVisitor *nv); + +#endif From b80e560bd1c1a69839730130572504c91087bc6c Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:10 +0200 Subject: [PATCH 08/19] qapi schema: remove trailing whitespace Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- qapi-schema.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index a92adb1d5b..d2f8e02dbc 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -343,7 +343,7 @@ # @CPU: the index of the virtual CPU # # @current: this only exists for backwards compatible and should be ignored -# +# # @halted: true if the virtual CPU is in the halt state. Halt usually refers # to a processor specific low power mode. # @@ -686,7 +686,7 @@ # @SpiceInfo # # Information about the SPICE session. -# +# # @enabled: true if the SPICE server is enabled, false otherwise # # @host: #optional The hostname the SPICE server is bound to. This depends on @@ -1297,7 +1297,7 @@ ## { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, - 'returns': 'str' } + 'returns': 'str' } ## # @migrate_cancel @@ -1458,7 +1458,7 @@ # @password: the new password # # @connected: #optional how to handle existing clients when changing the -# password. If nothing is specified, defaults to `keep' +# password. If nothing is specified, defaults to `keep' # `fail' to fail the command if clients are connected # `disconnect' to disconnect existing clients # `keep' to maintain existing clients @@ -1598,7 +1598,7 @@ # If the argument combination is invalid, InvalidParameterCombination # # Since: 1.1 -## +## { 'command': 'block_set_io_throttle', 'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } } From 14aa0c2de045a6c2fcfadf38c04434fd15909455 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:11 +0200 Subject: [PATCH 09/19] qapi schema: add Netdev types NetdevTapOptions::sndbuf and NetdevDumpOptions::len use the new "size" type. v1->v2: - NetLegacy::name is optional - NetLegacyNicOptions::vectors is of type uint32 - NetdevVdeOptions::port and ::mode are of type uint16 - NetLegacy::vlan has type int32 v2->v3: - NetLegacy::id is allowed and takes precedence over NetLegacy::name - replace "@traits" with "@opts" in NetLegacy & Netdev descriptions Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- qapi-schema.json | 278 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index d2f8e02dbc..bc55ed2b6d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1871,6 +1871,284 @@ ## { 'command': 'netdev_del', 'data': {'id': 'str'} } +## +# @NetdevNoneOptions +# +# Use it alone to have zero network devices. +# +# Since 1.2 +## +{ 'type': 'NetdevNoneOptions', + 'data': { } } + +## +# @NetLegacyNicOptions +# +# Create a new Network Interface Card. +# +# @netdev: #optional id of -netdev to connect to +# +# @macaddr: #optional MAC address +# +# @model: #optional device model (e1000, rtl8139, virtio etc.) +# +# @addr: #optional PCI device address +# +# @vectors: #optional number of MSI-x vectors, 0 to disable MSI-X +# +# Since 1.2 +## +{ 'type': 'NetLegacyNicOptions', + 'data': { + '*netdev': 'str', + '*macaddr': 'str', + '*model': 'str', + '*addr': 'str', + '*vectors': 'uint32' } } + +## +# @String +# +# A fat type wrapping 'str', to be embedded in lists. +# +# Since 1.2 +## +{ 'type': 'String', + 'data': { + 'str': 'str' } } + +## +# @NetdevUserOptions +# +# Use the user mode network stack which requires no administrator privilege to +# run. +# +# @hostname: #optional client hostname reported by the builtin DHCP server +# +# @restrict: #optional isolate the guest from the host +# +# @ip: #optional legacy parameter, use net= instead +# +# @net: #optional IP address and optional netmask +# +# @host: #optional guest-visible address of the host +# +# @tftp: #optional root directory of the built-in TFTP server +# +# @bootfile: #optional BOOTP filename, for use with tftp= +# +# @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can +# assign +# +# @dns: #optional guest-visible address of the virtual nameserver +# +# @smb: #optional root directory of the built-in SMB server +# +# @smbserver: #optional IP address of the built-in SMB server +# +# @hostfwd: #optional redirect incoming TCP or UDP host connections to guest +# endpoints +# +# @guestfwd: #optional forward guest TCP connections +# +# Since 1.2 +## +{ 'type': 'NetdevUserOptions', + 'data': { + '*hostname': 'str', + '*restrict': 'bool', + '*ip': 'str', + '*net': 'str', + '*host': 'str', + '*tftp': 'str', + '*bootfile': 'str', + '*dhcpstart': 'str', + '*dns': 'str', + '*smb': 'str', + '*smbserver': 'str', + '*hostfwd': ['String'], + '*guestfwd': ['String'] } } + +## +# @NetdevTapOptions +# +# Connect the host TAP network interface name to the VLAN. +# +# @ifname: #optional interface name +# +# @fd: #optional file descriptor of an already opened tap +# +# @script: #optional script to initialize the interface +# +# @downscript: #optional script to shut down the interface +# +# @helper: #optional command to execute to configure bridge +# +# @sndbuf: #optional send buffer limit. Understands [TGMKkb] suffixes. +# +# @vnet_hdr: #optional enable the IFF_VNET_HDR flag on the tap interface +# +# @vhost: #optional enable vhost-net network accelerator +# +# @vhostfd: #optional file descriptor of an already opened vhost net device +# +# @vhostforce: #optional vhost on for non-MSIX virtio guests +# +# Since 1.2 +## +{ 'type': 'NetdevTapOptions', + 'data': { + '*ifname': 'str', + '*fd': 'str', + '*script': 'str', + '*downscript': 'str', + '*helper': 'str', + '*sndbuf': 'size', + '*vnet_hdr': 'bool', + '*vhost': 'bool', + '*vhostfd': 'str', + '*vhostforce': 'bool' } } + +## +# @NetdevSocketOptions +# +# Connect the VLAN to a remote VLAN in another QEMU virtual machine using a TCP +# socket connection. +# +# @fd: #optional file descriptor of an already opened socket +# +# @listen: #optional port number, and optional hostname, to listen on +# +# @connect: #optional port number, and optional hostname, to connect to +# +# @mcast: #optional UDP multicast address and port number +# +# @localaddr: #optional source address and port for multicast and udp packets +# +# @udp: #optional UDP unicast address and port number +# +# Since 1.2 +## +{ 'type': 'NetdevSocketOptions', + 'data': { + '*fd': 'str', + '*listen': 'str', + '*connect': 'str', + '*mcast': 'str', + '*localaddr': 'str', + '*udp': 'str' } } + +## +# @NetdevVdeOptions +# +# Connect the VLAN to a vde switch running on the host. +# +# @sock: #optional socket path +# +# @port: #optional port number +# +# @group: #optional group owner of socket +# +# @mode: #optional permissions for socket +# +# Since 1.2 +## +{ 'type': 'NetdevVdeOptions', + 'data': { + '*sock': 'str', + '*port': 'uint16', + '*group': 'str', + '*mode': 'uint16' } } + +## +# @NetdevDumpOptions +# +# Dump VLAN network traffic to a file. +# +# @len: #optional per-packet size limit (64k default). Understands [TGMKkb] +# suffixes. +# +# @file: #optional dump file path (default is qemu-vlan0.pcap) +# +# Since 1.2 +## +{ 'type': 'NetdevDumpOptions', + 'data': { + '*len': 'size', + '*file': 'str' } } + +## +# @NetdevBridgeOptions +# +# Connect a host TAP network interface to a host bridge device. +# +# @br: #optional bridge name +# +# @helper: #optional command to execute to configure bridge +# +# Since 1.2 +## +{ 'type': 'NetdevBridgeOptions', + 'data': { + '*br': 'str', + '*helper': 'str' } } + +## +# @NetClientOptions +# +# A discriminated record of network device traits. +# +# Since 1.2 +## +{ 'union': 'NetClientOptions', + 'data': { + 'none': 'NetdevNoneOptions', + 'nic': 'NetLegacyNicOptions', + 'user': 'NetdevUserOptions', + 'tap': 'NetdevTapOptions', + 'socket': 'NetdevSocketOptions', + 'vde': 'NetdevVdeOptions', + 'dump': 'NetdevDumpOptions', + 'bridge': 'NetdevBridgeOptions' } } + +## +# @NetLegacy +# +# Captures the configuration of a network device; legacy. +# +# @vlan: #optional vlan number +# +# @id: #optional identifier for monitor commands +# +# @name: #optional identifier for monitor commands, ignored if @id is present +# +# @opts: device type specific properties (legacy) +# +# Since 1.2 +## +{ 'type': 'NetLegacy', + 'data': { + '*vlan': 'int32', + '*id': 'str', + '*name': 'str', + 'opts': 'NetClientOptions' } } + +## +# @Netdev +# +# Captures the configuration of a network device. +# +# @id: identifier for monitor commands. +# +# @opts: device type specific properties +# +# Since 1.2 +## +{ 'type': 'Netdev', + 'data': { + 'id': 'str', + 'opts': 'NetClientOptions' } } + ## # @getfd: # From 2be64a68ed05c65fc510dc450a1eb1823edf9330 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:12 +0200 Subject: [PATCH 10/19] hw, net: "net_client_type" -> "NetClientOptionsKind" (qapi-generated) NET_CLIENT_TYPE_ -> NET_CLIENT_OPTIONS_KIND_ Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- hw/cadence_gem.c | 2 +- hw/dp8393x.c | 2 +- hw/e1000.c | 2 +- hw/eepro100.c | 2 +- hw/etraxfs_eth.c | 2 +- hw/lan9118.c | 2 +- hw/lance.c | 2 +- hw/mcf_fec.c | 2 +- hw/milkymist-minimac2.c | 2 +- hw/mipsnet.c | 2 +- hw/musicpal.c | 2 +- hw/ne2000-isa.c | 2 +- hw/ne2000.c | 2 +- hw/opencores_eth.c | 2 +- hw/pcnet-pci.c | 2 +- hw/rtl8139.c | 2 +- hw/smc91c111.c | 2 +- hw/spapr_llan.c | 2 +- hw/stellaris_enet.c | 2 +- hw/usb/dev-network.c | 2 +- hw/vhost_net.c | 2 +- hw/virtio-net.c | 10 ++++----- hw/xen_nic.c | 2 +- hw/xgmac.c | 2 +- hw/xilinx_axienet.c | 2 +- hw/xilinx_ethlite.c | 2 +- net.c | 50 ++++++++++++++++++++--------------------- net.h | 16 ++----------- net/dump.c | 2 +- net/slirp.c | 2 +- net/socket.c | 4 ++-- net/tap-win32.c | 2 +- net/tap.c | 16 ++++++------- net/vde.c | 2 +- 34 files changed, 71 insertions(+), 83 deletions(-) diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c index 87143caf2d..a0f51dea80 100644 --- a/hw/cadence_gem.c +++ b/hw/cadence_gem.c @@ -1161,7 +1161,7 @@ static void gem_set_link(VLANClientState *nc) } static NetClientInfo net_gem_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = gem_can_receive, .receive = gem_receive, diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 017d0742ae..756d6301b0 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -872,7 +872,7 @@ static void nic_cleanup(VLANClientState *nc) } static NetClientInfo net_dp83932_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = nic_can_receive, .receive = nic_receive, diff --git a/hw/e1000.c b/hw/e1000.c index 4573f1301e..ad242981cc 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -1206,7 +1206,7 @@ pci_e1000_uninit(PCIDevice *dev) } static NetClientInfo net_e1000_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = e1000_can_receive, .receive = e1000_receive, diff --git a/hw/eepro100.c b/hw/eepro100.c index 6279ae36ec..f343685dbd 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1845,7 +1845,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev) } static NetClientInfo net_eepro100_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = nic_can_receive, .receive = nic_receive, diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 16a0637a4a..45fb40ce76 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -579,7 +579,7 @@ static void eth_cleanup(VLANClientState *nc) } static NetClientInfo net_etraxfs_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = eth_can_receive, .receive = eth_receive, diff --git a/hw/lan9118.c b/hw/lan9118.c index 7b4fe87fca..40fb7654f4 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -1310,7 +1310,7 @@ static void lan9118_cleanup(VLANClientState *nc) } static NetClientInfo net_lan9118_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = lan9118_can_receive, .receive = lan9118_receive, diff --git a/hw/lance.c b/hw/lance.c index ce3d46c17b..91c0e16237 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -93,7 +93,7 @@ static void lance_cleanup(VLANClientState *nc) } static NetClientInfo net_lance_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = pcnet_can_receive, .receive = pcnet_receive, diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index ae37bef0f0..4ab4ff583d 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -450,7 +450,7 @@ static void mcf_fec_cleanup(VLANClientState *nc) } static NetClientInfo net_mcf_fec_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = mcf_fec_can_receive, .receive = mcf_fec_receive, diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index 70bf336add..3924b8343d 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -448,7 +448,7 @@ static void milkymist_minimac2_reset(DeviceState *d) } static NetClientInfo net_milkymist_minimac2_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = minimac2_can_rx, .receive = minimac2_rx, diff --git a/hw/mipsnet.c b/hw/mipsnet.c index 31072463f4..3385be7683 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -217,7 +217,7 @@ static void mipsnet_cleanup(VLANClientState *nc) } static NetClientInfo net_mipsnet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = mipsnet_can_receive, .receive = mipsnet_receive, diff --git a/hw/musicpal.c b/hw/musicpal.c index f14f20d689..448897f82c 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -374,7 +374,7 @@ static void eth_cleanup(VLANClientState *nc) } static NetClientInfo net_mv88w8618_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = eth_can_receive, .receive = eth_receive, diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index a4a783ab89..99ed965eac 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -44,7 +44,7 @@ static void isa_ne2000_cleanup(VLANClientState *nc) } static NetClientInfo net_ne2000_isa_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = ne2000_can_receive, .receive = ne2000_receive, diff --git a/hw/ne2000.c b/hw/ne2000.c index d02e60c4a6..760ed2972a 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -711,7 +711,7 @@ static void ne2000_cleanup(VLANClientState *nc) } static NetClientInfo net_ne2000_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = ne2000_can_receive, .receive = ne2000_receive, diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index 350f73173a..f4498d413d 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -467,7 +467,7 @@ static void open_eth_cleanup(VLANClientState *nc) } static NetClientInfo net_open_eth_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = open_eth_can_receive, .receive = open_eth_receive, diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 34d73aaea1..931fedd913 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -284,7 +284,7 @@ static int pci_pcnet_uninit(PCIDevice *dev) } static NetClientInfo net_pci_pcnet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = pcnet_can_receive, .receive = pcnet_receive, diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 436b015c64..82fe235417 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -3455,7 +3455,7 @@ static int pci_rtl8139_uninit(PCIDevice *dev) } static NetClientInfo net_rtl8139_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = rtl8139_can_receive, .receive = rtl8139_receive, diff --git a/hw/smc91c111.c b/hw/smc91c111.c index 1a5213fa56..451ede0588 100644 --- a/hw/smc91c111.c +++ b/hw/smc91c111.c @@ -736,7 +736,7 @@ static void smc91c111_cleanup(VLANClientState *nc) } static NetClientInfo net_smc91c111_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = smc91c111_can_receive, .receive = smc91c111_receive, diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index d26fe9fea3..d54f933d3a 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -176,7 +176,7 @@ static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf, } static NetClientInfo net_spapr_vlan_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = spapr_vlan_can_receive, .receive = spapr_vlan_receive, diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index fbe99cb4a9..b593cd0ed9 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -393,7 +393,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc) } static NetClientInfo net_stellaris_enet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = stellaris_enet_can_receive, .receive = stellaris_enet_receive, diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 5d2f0982c9..f40c349fc3 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1313,7 +1313,7 @@ static void usb_net_handle_destroy(USBDevice *dev) } static NetClientInfo net_usbnet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = usbnet_can_receive, .receive = usbnet_receive, diff --git a/hw/vhost_net.c b/hw/vhost_net.c index f672e9dafd..75f8211046 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -83,7 +83,7 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features) static int vhost_net_get_fd(VLANClientState *backend) { switch (backend->info->type) { - case NET_CLIENT_TYPE_TAP: + case NET_CLIENT_OPTIONS_KIND_TAP: return tap_get_fd(backend); default: fprintf(stderr, "vhost-net requires tap backend\n"); diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 533aa3d0f3..df204999bc 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -108,7 +108,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status) if (!n->nic->nc.peer) { return; } - if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) { + if (n->nic->nc.peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) { return; } @@ -205,7 +205,7 @@ static int peer_has_vnet_hdr(VirtIONet *n) if (!n->nic->nc.peer) return 0; - if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) + if (n->nic->nc.peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) return 0; n->has_vnet_hdr = tap_has_vnet_hdr(n->nic->nc.peer); @@ -249,7 +249,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) } if (!n->nic->nc.peer || - n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) { + n->nic->nc.peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) { return features; } if (!tap_get_vhost_net(n->nic->nc.peer)) { @@ -288,7 +288,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) (features >> VIRTIO_NET_F_GUEST_UFO) & 1); } if (!n->nic->nc.peer || - n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) { + n->nic->nc.peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) { return; } if (!tap_get_vhost_net(n->nic->nc.peer)) { @@ -988,7 +988,7 @@ static void virtio_net_cleanup(VLANClientState *nc) } static NetClientInfo net_virtio_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = virtio_net_can_receive, .receive = virtio_net_receive, diff --git a/hw/xen_nic.c b/hw/xen_nic.c index 98db9bb8f6..593a572119 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -301,7 +301,7 @@ static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz /* ------------------------------------------------------------- */ static NetClientInfo net_xen_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = net_rx_ok, .receive = net_rx_packet, diff --git a/hw/xgmac.c b/hw/xgmac.c index dd4bdc46f5..e539681d83 100644 --- a/hw/xgmac.c +++ b/hw/xgmac.c @@ -371,7 +371,7 @@ static void eth_cleanup(VLANClientState *nc) } static NetClientInfo net_xgmac_enet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = eth_can_rx, .receive = eth_rx, diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index 2e8d8a59ba..e948505849 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -832,7 +832,7 @@ axienet_stream_push(void *opaque, uint8_t *buf, size_t size, uint32_t *hdr) } static NetClientInfo net_xilinx_enet_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = eth_can_rx, .receive = eth_rx, diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index affbb8bfff..9006322855 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -202,7 +202,7 @@ static void eth_cleanup(VLANClientState *nc) } static NetClientInfo net_xilinx_ethlite_info = { - .type = NET_CLIENT_TYPE_NIC, + .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), .can_receive = eth_can_rx, .receive = eth_rx, diff --git a/net.c b/net.c index abf0fd0a0d..c46695f6b5 100644 --- a/net.c +++ b/net.c @@ -239,7 +239,7 @@ NICState *qemu_new_nic(NetClientInfo *info, VLANClientState *nc; NICState *nic; - assert(info->type == NET_CLIENT_TYPE_NIC); + assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); assert(info->size >= sizeof(NICState)); nc = qemu_new_net_client(info, conf->vlan, conf->peer, model, name); @@ -282,7 +282,7 @@ static void qemu_free_vlan_client(VLANClientState *vc) void qemu_del_vlan_client(VLANClientState *vc) { /* If there is a peer NIC, delete and cleanup client, but do not free. */ - if (!vc->vlan && vc->peer && vc->peer->info->type == NET_CLIENT_TYPE_NIC) { + if (!vc->vlan && vc->peer && vc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { NICState *nic = DO_UPCAST(NICState, nc, vc->peer); if (nic->peer_deleted) { return; @@ -298,7 +298,7 @@ void qemu_del_vlan_client(VLANClientState *vc) } /* If this is a peer NIC and peer has already been deleted, free it now. */ - if (!vc->vlan && vc->peer && vc->info->type == NET_CLIENT_TYPE_NIC) { + if (!vc->vlan && vc->peer && vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { NICState *nic = DO_UPCAST(NICState, nc, vc); if (nic->peer_deleted) { qemu_free_vlan_client(vc->peer); @@ -341,14 +341,14 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) VLANState *vlan; QTAILQ_FOREACH(nc, &non_vlan_clients, next) { - if (nc->info->type == NET_CLIENT_TYPE_NIC) { + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { func(DO_UPCAST(NICState, nc, nc), opaque); } } QTAILQ_FOREACH(vlan, &vlans, next) { QTAILQ_FOREACH(nc, &vlan->clients, next) { - if (nc->info->type == NET_CLIENT_TYPE_NIC) { + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { func(DO_UPCAST(NICState, nc, nc), opaque); } } @@ -664,7 +664,7 @@ VLANClientState *qemu_find_netdev(const char *id) VLANClientState *vc; QTAILQ_FOREACH(vc, &non_vlan_clients, next) { - if (vc->info->type == NET_CLIENT_TYPE_NIC) + if (vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) continue; if (!strcmp(vc->name, id)) { return vc; @@ -828,15 +828,15 @@ static const struct { const char *type; net_client_init_func init; QemuOptDesc desc[NET_MAX_DESC]; -} net_client_types[NET_CLIENT_TYPE_MAX] = { - [NET_CLIENT_TYPE_NONE] = { +} net_client_types[NET_CLIENT_OPTIONS_KIND_MAX] = { + [NET_CLIENT_OPTIONS_KIND_NONE] = { .type = "none", .desc = { NET_COMMON_PARAMS_DESC, { /* end of list */ } }, }, - [NET_CLIENT_TYPE_NIC] = { + [NET_CLIENT_OPTIONS_KIND_NIC] = { .type = "nic", .init = net_init_nic, .desc = { @@ -867,7 +867,7 @@ static const struct { }, }, #ifdef CONFIG_SLIRP - [NET_CLIENT_TYPE_USER] = { + [NET_CLIENT_OPTIONS_KIND_USER] = { .type = "user", .init = net_init_slirp, .desc = { @@ -929,7 +929,7 @@ static const struct { }, }, #endif - [NET_CLIENT_TYPE_TAP] = { + [NET_CLIENT_OPTIONS_KIND_TAP] = { .type = "tap", .init = net_init_tap, .desc = { @@ -983,7 +983,7 @@ static const struct { { /* end of list */ } }, }, - [NET_CLIENT_TYPE_SOCKET] = { + [NET_CLIENT_OPTIONS_KIND_SOCKET] = { .type = "socket", .init = net_init_socket, .desc = { @@ -1017,7 +1017,7 @@ static const struct { }, }, #ifdef CONFIG_VDE - [NET_CLIENT_TYPE_VDE] = { + [NET_CLIENT_OPTIONS_KIND_VDE] = { .type = "vde", .init = net_init_vde, .desc = { @@ -1043,7 +1043,7 @@ static const struct { }, }, #endif - [NET_CLIENT_TYPE_DUMP] = { + [NET_CLIENT_OPTIONS_KIND_DUMP] = { .type = "dump", .init = net_init_dump, .desc = { @@ -1061,7 +1061,7 @@ static const struct { }, }, #ifdef CONFIG_NET_BRIDGE - [NET_CLIENT_TYPE_BRIDGE] = { + [NET_CLIENT_OPTIONS_KIND_BRIDGE] = { .type = "bridge", .init = net_init_bridge, .desc = { @@ -1129,7 +1129,7 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) name = qemu_opt_get(opts, "name"); } - for (i = 0; i < NET_CLIENT_TYPE_MAX; i++) { + for (i = 0; i < NET_CLIENT_OPTIONS_KIND_MAX; i++) { if (net_client_types[i].type != NULL && !strcmp(net_client_types[i].type, type)) { Error *local_err = NULL; @@ -1293,7 +1293,7 @@ void do_info_network(Monitor *mon) { VLANState *vlan; VLANClientState *vc, *peer; - net_client_type type; + NetClientOptionsKind type; QTAILQ_FOREACH(vlan, &vlans, next) { monitor_printf(mon, "VLAN %d devices:\n", vlan->id); @@ -1307,11 +1307,11 @@ void do_info_network(Monitor *mon) QTAILQ_FOREACH(vc, &non_vlan_clients, next) { peer = vc->peer; type = vc->info->type; - if (!peer || type == NET_CLIENT_TYPE_NIC) { + if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) { monitor_printf(mon, " "); print_net_client(mon, vc); } /* else it's a netdev connected to a NIC, printed with the NIC */ - if (peer && type == NET_CLIENT_TYPE_NIC) { + if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) { monitor_printf(mon, " \\ "); print_net_client(mon, peer); } @@ -1399,13 +1399,13 @@ void net_check_clients(void) QTAILQ_FOREACH(vc, &vlan->clients, next) { switch (vc->info->type) { - case NET_CLIENT_TYPE_NIC: + case NET_CLIENT_OPTIONS_KIND_NIC: has_nic = 1; break; - case NET_CLIENT_TYPE_USER: - case NET_CLIENT_TYPE_TAP: - case NET_CLIENT_TYPE_SOCKET: - case NET_CLIENT_TYPE_VDE: + case NET_CLIENT_OPTIONS_KIND_USER: + case NET_CLIENT_OPTIONS_KIND_TAP: + case NET_CLIENT_OPTIONS_KIND_SOCKET: + case NET_CLIENT_OPTIONS_KIND_VDE: has_host_dev = 1; break; default: ; @@ -1421,7 +1421,7 @@ void net_check_clients(void) QTAILQ_FOREACH(vc, &non_vlan_clients, next) { if (!vc->peer) { fprintf(stderr, "Warning: %s %s has no peer\n", - vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev", + vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? "nic" : "netdev", vc->name); } } diff --git a/net.h b/net.h index bdc2a0602d..b0b8c7ab6b 100644 --- a/net.h +++ b/net.h @@ -7,6 +7,7 @@ #include "qemu-option.h" #include "net/queue.h" #include "vmstate.h" +#include "qapi-types.h" struct MACAddr { uint8_t a[6]; @@ -29,19 +30,6 @@ typedef struct NICConf { /* VLANs support */ -typedef enum { - NET_CLIENT_TYPE_NONE, - NET_CLIENT_TYPE_NIC, - NET_CLIENT_TYPE_USER, - NET_CLIENT_TYPE_TAP, - NET_CLIENT_TYPE_SOCKET, - NET_CLIENT_TYPE_VDE, - NET_CLIENT_TYPE_DUMP, - NET_CLIENT_TYPE_BRIDGE, - - NET_CLIENT_TYPE_MAX -} net_client_type; - typedef void (NetPoll)(VLANClientState *, bool enable); typedef int (NetCanReceive)(VLANClientState *); typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t); @@ -50,7 +38,7 @@ typedef void (NetCleanup) (VLANClientState *); typedef void (LinkStatusChanged)(VLANClientState *); typedef struct NetClientInfo { - net_client_type type; + NetClientOptionsKind type; size_t size; NetReceive *receive; NetReceive *receive_raw; diff --git a/net/dump.c b/net/dump.c index f835c51187..2124b9a081 100644 --- a/net/dump.c +++ b/net/dump.c @@ -93,7 +93,7 @@ static void dump_cleanup(VLANClientState *nc) } static NetClientInfo net_dump_info = { - .type = NET_CLIENT_TYPE_DUMP, + .type = NET_CLIENT_OPTIONS_KIND_DUMP, .size = sizeof(DumpState), .receive = dump_receive, .cleanup = dump_cleanup, diff --git a/net/slirp.c b/net/slirp.c index b82eab0a07..1f63d50ed7 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -129,7 +129,7 @@ static void net_slirp_cleanup(VLANClientState *nc) } static NetClientInfo net_slirp_info = { - .type = NET_CLIENT_TYPE_USER, + .type = NET_CLIENT_OPTIONS_KIND_USER, .size = sizeof(SlirpState), .receive = net_slirp_receive, .cleanup = net_slirp_cleanup, diff --git a/net/socket.c b/net/socket.c index fcd0a3c162..30536efbaf 100644 --- a/net/socket.c +++ b/net/socket.c @@ -239,7 +239,7 @@ static void net_socket_cleanup(VLANClientState *nc) } static NetClientInfo net_dgram_socket_info = { - .type = NET_CLIENT_TYPE_SOCKET, + .type = NET_CLIENT_OPTIONS_KIND_SOCKET, .size = sizeof(NetSocketState), .receive = net_socket_receive_dgram, .cleanup = net_socket_cleanup, @@ -317,7 +317,7 @@ static void net_socket_connect(void *opaque) } static NetClientInfo net_socket_info = { - .type = NET_CLIENT_TYPE_SOCKET, + .type = NET_CLIENT_OPTIONS_KIND_SOCKET, .size = sizeof(NetSocketState), .receive = net_socket_receive, .cleanup = net_socket_cleanup, diff --git a/net/tap-win32.c b/net/tap-win32.c index a801a553c4..f7b6129131 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -667,7 +667,7 @@ static void tap_win32_send(void *opaque) } static NetClientInfo net_tap_win32_info = { - .type = NET_CLIENT_TYPE_TAP, + .type = NET_CLIENT_OPTIONS_KIND_TAP, .size = sizeof(TAPState), .receive = tap_receive, .cleanup = tap_cleanup, diff --git a/net/tap.c b/net/tap.c index 17e91355ce..9131ef5564 100644 --- a/net/tap.c +++ b/net/tap.c @@ -218,7 +218,7 @@ int tap_has_ufo(VLANClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return s->has_ufo; } @@ -227,7 +227,7 @@ int tap_has_vnet_hdr(VLANClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return !!s->host_vnet_hdr_len; } @@ -236,7 +236,7 @@ int tap_has_vnet_hdr_len(VLANClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return tap_probe_vnet_hdr_len(s->fd, len); } @@ -245,7 +245,7 @@ void tap_set_vnet_hdr_len(VLANClientState *nc, int len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) || len == sizeof(struct virtio_net_hdr)); @@ -259,7 +259,7 @@ void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) using_vnet_hdr = using_vnet_hdr != 0; - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); assert(!!s->host_vnet_hdr_len == using_vnet_hdr); s->using_vnet_hdr = using_vnet_hdr; @@ -306,14 +306,14 @@ static void tap_poll(VLANClientState *nc, bool enable) int tap_get_fd(VLANClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return s->fd; } /* fd support */ static NetClientInfo net_tap_info = { - .type = NET_CLIENT_TYPE_TAP, + .type = NET_CLIENT_OPTIONS_KIND_TAP, .size = sizeof(TAPState), .receive = tap_receive, .receive_raw = tap_receive_raw, @@ -711,6 +711,6 @@ int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan) VHostNetState *tap_get_vhost_net(VLANClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type == NET_CLIENT_TYPE_TAP); + assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return s->vhost_net; } diff --git a/net/vde.c b/net/vde.c index 6b9d45294a..0e8bf23222 100644 --- a/net/vde.c +++ b/net/vde.c @@ -69,7 +69,7 @@ static void vde_cleanup(VLANClientState *nc) } static NetClientInfo net_vde_info = { - .type = NET_CLIENT_TYPE_VDE, + .type = NET_CLIENT_OPTIONS_KIND_VDE, .size = sizeof(VDEState), .receive = vde_receive, .cleanup = vde_cleanup, From 6687b79d636cd60ed9adb1177d0d946b58fa7717 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:13 +0200 Subject: [PATCH 11/19] convert net_client_init() to OptsVisitor The net_client_init() prototype is kept intact. Based on "is_netdev", the QemuOpts-rooted QemuOpt-list is parsed as a Netdev or a NetLegacy. The original meat of net_client_init() is moved to and simplified in net_client_init1(): Fields not common between -net and -netdev are clearly separated. Getting the name for the init functions is cleaner: Netdev::id is mandatory, and all init functions handle a NULL NetLegacy::name. NetLegacy::vlan explicitly depends on -net (see below). Verifying the "type=" option for -netdev can be turned into a switch. Format validation with qemu_opts_validate() can be removed because the visitor covers it. Relatedly, the "net_client_types" array is reduced to an array of init functions that can be directly indexed by opts->kind. (Help text is available in the schema JSON.) The outermost negation in the condition around qemu_find_vlan() was flattened, because it expresses the dependent code's requirements more clearly. VLAN lookup is avoided if there's no init function to pass the VLAN to. Whenever the value of type=... is needed, we substitute NetClientOptionsKind_lookup[kind]. The individual init functions are not converted yet, thus the original QemuOpts instance is passed transparently. v1->v2: - NetLegacy::name is optional. Tracked it through all init functions: they all handle a NULL name. Updated commit message accordingly. v2->v3: - NetLegacy::id is allowed and takes precedence over NetLegacy::name. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net.c | 445 +++++++++++------------------------------------- net/dump.c | 3 +- net/dump.h | 4 +- net/slirp.c | 3 +- net/slirp.h | 4 +- net/socket.c | 3 +- net/socket.h | 4 +- net/tap-win32.c | 3 +- net/tap.c | 6 +- net/tap.h | 7 +- net/vde.c | 3 +- net/vde.h | 4 +- 12 files changed, 135 insertions(+), 354 deletions(-) diff --git a/net.c b/net.c index c46695f6b5..af544b2479 100644 --- a/net.c +++ b/net.c @@ -37,6 +37,9 @@ #include "qmp-commands.h" #include "hw/qdev.h" #include "iov.h" +#include "qapi-visit.h" +#include "qapi/opts-visitor.h" +#include "qapi/qapi-dealloc-visitor.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) @@ -745,7 +748,8 @@ int net_handle_fd_param(Monitor *mon, const char *param) return fd; } -static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan) +static int net_init_nic(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { int idx; NICInfo *nd; @@ -802,371 +806,130 @@ static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan) return idx; } -#define NET_COMMON_PARAMS_DESC \ - { \ - .name = "type", \ - .type = QEMU_OPT_STRING, \ - .help = "net client type (nic, tap etc.)", \ - }, { \ - .name = "vlan", \ - .type = QEMU_OPT_NUMBER, \ - .help = "vlan number", \ - }, { \ - .name = "name", \ - .type = QEMU_OPT_STRING, \ - .help = "identifier for monitor commands", \ - } -typedef int (*net_client_init_func)(QemuOpts *opts, - const char *name, - VLANState *vlan); - -/* magic number, but compiler will warn if too small */ -#define NET_MAX_DESC 20 - -static const struct { - const char *type; - net_client_init_func init; - QemuOptDesc desc[NET_MAX_DESC]; -} net_client_types[NET_CLIENT_OPTIONS_KIND_MAX] = { - [NET_CLIENT_OPTIONS_KIND_NONE] = { - .type = "none", - .desc = { - NET_COMMON_PARAMS_DESC, - { /* end of list */ } - }, - }, - [NET_CLIENT_OPTIONS_KIND_NIC] = { - .type = "nic", - .init = net_init_nic, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "netdev", - .type = QEMU_OPT_STRING, - .help = "id of -netdev to connect to", - }, - { - .name = "macaddr", - .type = QEMU_OPT_STRING, - .help = "MAC address", - }, { - .name = "model", - .type = QEMU_OPT_STRING, - .help = "device model (e1000, rtl8139, virtio etc.)", - }, { - .name = "addr", - .type = QEMU_OPT_STRING, - .help = "PCI device address", - }, { - .name = "vectors", - .type = QEMU_OPT_NUMBER, - .help = "number of MSI-x vectors, 0 to disable MSI-X", - }, - { /* end of list */ } - }, - }, +static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])( + QemuOpts *old_opts, + const NetClientOptions *new_opts, + const char *name, + VLANState *vlan) = { + [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, #ifdef CONFIG_SLIRP - [NET_CLIENT_OPTIONS_KIND_USER] = { - .type = "user", - .init = net_init_slirp, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "hostname", - .type = QEMU_OPT_STRING, - .help = "client hostname reported by the builtin DHCP server", - }, { - .name = "restrict", - .type = QEMU_OPT_STRING, - .help = "isolate the guest from the host (y|yes|n|no)", - }, { - .name = "ip", - .type = QEMU_OPT_STRING, - .help = "legacy parameter, use net= instead", - }, { - .name = "net", - .type = QEMU_OPT_STRING, - .help = "IP address and optional netmask", - }, { - .name = "host", - .type = QEMU_OPT_STRING, - .help = "guest-visible address of the host", - }, { - .name = "tftp", - .type = QEMU_OPT_STRING, - .help = "root directory of the built-in TFTP server", - }, { - .name = "bootfile", - .type = QEMU_OPT_STRING, - .help = "BOOTP filename, for use with tftp=", - }, { - .name = "dhcpstart", - .type = QEMU_OPT_STRING, - .help = "the first of the 16 IPs the built-in DHCP server can assign", - }, { - .name = "dns", - .type = QEMU_OPT_STRING, - .help = "guest-visible address of the virtual nameserver", - }, { - .name = "smb", - .type = QEMU_OPT_STRING, - .help = "root directory of the built-in SMB server", - }, { - .name = "smbserver", - .type = QEMU_OPT_STRING, - .help = "IP address of the built-in SMB server", - }, { - .name = "hostfwd", - .type = QEMU_OPT_STRING, - .help = "guest port number to forward incoming TCP or UDP connections", - }, { - .name = "guestfwd", - .type = QEMU_OPT_STRING, - .help = "IP address and port to forward guest TCP connections", - }, - { /* end of list */ } - }, - }, + [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, #endif - [NET_CLIENT_OPTIONS_KIND_TAP] = { - .type = "tap", - .init = net_init_tap, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "ifname", - .type = QEMU_OPT_STRING, - .help = "interface name", - }, -#ifndef _WIN32 - { - .name = "fd", - .type = QEMU_OPT_STRING, - .help = "file descriptor of an already opened tap", - }, { - .name = "script", - .type = QEMU_OPT_STRING, - .help = "script to initialize the interface", - }, { - .name = "downscript", - .type = QEMU_OPT_STRING, - .help = "script to shut down the interface", - }, { -#ifdef CONFIG_NET_BRIDGE - .name = "helper", - .type = QEMU_OPT_STRING, - .help = "command to execute to configure bridge", - }, { -#endif - .name = "sndbuf", - .type = QEMU_OPT_SIZE, - .help = "send buffer limit" - }, { - .name = "vnet_hdr", - .type = QEMU_OPT_BOOL, - .help = "enable the IFF_VNET_HDR flag on the tap interface" - }, { - .name = "vhost", - .type = QEMU_OPT_BOOL, - .help = "enable vhost-net network accelerator", - }, { - .name = "vhostfd", - .type = QEMU_OPT_STRING, - .help = "file descriptor of an already opened vhost net device", - }, { - .name = "vhostforce", - .type = QEMU_OPT_BOOL, - .help = "force vhost on for non-MSIX virtio guests", - }, -#endif /* _WIN32 */ - { /* end of list */ } - }, - }, - [NET_CLIENT_OPTIONS_KIND_SOCKET] = { - .type = "socket", - .init = net_init_socket, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "fd", - .type = QEMU_OPT_STRING, - .help = "file descriptor of an already opened socket", - }, { - .name = "listen", - .type = QEMU_OPT_STRING, - .help = "port number, and optional hostname, to listen on", - }, { - .name = "connect", - .type = QEMU_OPT_STRING, - .help = "port number, and optional hostname, to connect to", - }, { - .name = "mcast", - .type = QEMU_OPT_STRING, - .help = "UDP multicast address and port number", - }, { - .name = "localaddr", - .type = QEMU_OPT_STRING, - .help = "source address and port for multicast and udp packets", - }, { - .name = "udp", - .type = QEMU_OPT_STRING, - .help = "UDP unicast address and port number", - }, - { /* end of list */ } - }, - }, + [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, + [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, #ifdef CONFIG_VDE - [NET_CLIENT_OPTIONS_KIND_VDE] = { - .type = "vde", - .init = net_init_vde, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "sock", - .type = QEMU_OPT_STRING, - .help = "socket path", - }, { - .name = "port", - .type = QEMU_OPT_NUMBER, - .help = "port number", - }, { - .name = "group", - .type = QEMU_OPT_STRING, - .help = "group owner of socket", - }, { - .name = "mode", - .type = QEMU_OPT_NUMBER, - .help = "permissions for socket", - }, - { /* end of list */ } - }, - }, + [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, #endif - [NET_CLIENT_OPTIONS_KIND_DUMP] = { - .type = "dump", - .init = net_init_dump, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "len", - .type = QEMU_OPT_SIZE, - .help = "per-packet size limit (64k default)", - }, { - .name = "file", - .type = QEMU_OPT_STRING, - .help = "dump file path (default is qemu-vlan0.pcap)", - }, - { /* end of list */ } - }, - }, + [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, #ifdef CONFIG_NET_BRIDGE - [NET_CLIENT_OPTIONS_KIND_BRIDGE] = { - .type = "bridge", - .init = net_init_bridge, - .desc = { - NET_COMMON_PARAMS_DESC, - { - .name = "br", - .type = QEMU_OPT_STRING, - .help = "bridge name", - }, { - .name = "helper", - .type = QEMU_OPT_STRING, - .help = "command to execute to configure bridge", - }, - { /* end of list */ } - }, - }, -#endif /* CONFIG_NET_BRIDGE */ + [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, +#endif }; -int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) -{ - const char *name; - const char *type; - int i; - type = qemu_opt_get(opts, "type"); - if (!type) { - error_set(errp, QERR_MISSING_PARAMETER, "type"); - return -1; - } +static int net_client_init1(const void *object, int is_netdev, + QemuOpts *old_opts, Error **errp) +{ + union { + const Netdev *netdev; + const NetLegacy *net; + } u; + const NetClientOptions *opts; + const char *name; if (is_netdev) { - if (strcmp(type, "tap") != 0 && -#ifdef CONFIG_NET_BRIDGE - strcmp(type, "bridge") != 0 && -#endif + u.netdev = object; + opts = u.netdev->opts; + name = u.netdev->id; + + switch (opts->kind) { #ifdef CONFIG_SLIRP - strcmp(type, "user") != 0 && + case NET_CLIENT_OPTIONS_KIND_USER: #endif + case NET_CLIENT_OPTIONS_KIND_TAP: + case NET_CLIENT_OPTIONS_KIND_SOCKET: #ifdef CONFIG_VDE - strcmp(type, "vde") != 0 && + case NET_CLIENT_OPTIONS_KIND_VDE: #endif - strcmp(type, "socket") != 0) { +#ifdef CONFIG_NET_BRIDGE + case NET_CLIENT_OPTIONS_KIND_BRIDGE: +#endif + break; + + default: error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a netdev backend type"); return -1; } + } else { + u.net = object; + opts = u.net->opts; + /* missing optional values have been initialized to "all bits zero" */ + name = u.net->has_id ? u.net->id : u.net->name; + } - if (qemu_opt_get(opts, "vlan")) { - error_set(errp, QERR_INVALID_PARAMETER, "vlan"); - return -1; + if (net_client_init_fun[opts->kind]) { + VLANState *vlan = NULL; + + /* Do not add to a vlan if it's a -netdev or a nic with a netdev= + * parameter. */ + if (!is_netdev && + (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC || + !opts->nic->has_netdev)) { + vlan = qemu_find_vlan(u.net->has_vlan ? u.net->vlan : 0, true); } - if (qemu_opt_get(opts, "name")) { - error_set(errp, QERR_INVALID_PARAMETER, "name"); - return -1; - } - if (!qemu_opts_id(opts)) { - error_set(errp, QERR_MISSING_PARAMETER, "id"); + + if (net_client_init_fun[opts->kind](old_opts, opts, name, vlan) < 0) { + /* TODO push error reporting into init() methods */ + error_set(errp, QERR_DEVICE_INIT_FAILED, + NetClientOptionsKind_lookup[opts->kind]); return -1; } } - - name = qemu_opts_id(opts); - if (!name) { - name = qemu_opt_get(opts, "name"); - } - - for (i = 0; i < NET_CLIENT_OPTIONS_KIND_MAX; i++) { - if (net_client_types[i].type != NULL && - !strcmp(net_client_types[i].type, type)) { - Error *local_err = NULL; - VLANState *vlan = NULL; - int ret; - - qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - return -1; - } - - /* Do not add to a vlan if it's a -netdev or a nic with a - * netdev= parameter. */ - if (!(is_netdev || - (strcmp(type, "nic") == 0 && qemu_opt_get(opts, "netdev")))) { - vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1); - } - - ret = 0; - if (net_client_types[i].init) { - ret = net_client_types[i].init(opts, name, vlan); - if (ret < 0) { - /* TODO push error reporting into init() methods */ - error_set(errp, QERR_DEVICE_INIT_FAILED, type); - return -1; - } - } - return ret; - } - } - - error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type", - "a network client type"); - return -1; + return 0; } + +static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp) +{ + if (is_netdev) { + visit_type_Netdev(v, (Netdev **)object, NULL, errp); + } else { + visit_type_NetLegacy(v, (NetLegacy **)object, NULL, errp); + } +} + + +int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) +{ + void *object = NULL; + Error *err = NULL; + int ret = -1; + + { + OptsVisitor *ov = opts_visitor_new(opts); + + net_visit(opts_get_visitor(ov), is_netdev, &object, &err); + opts_visitor_cleanup(ov); + } + + if (!err) { + ret = net_client_init1(object, is_netdev, opts, &err); + } + + if (object) { + QapiDeallocVisitor *dv = qapi_dealloc_visitor_new(); + + net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL); + qapi_dealloc_visitor_cleanup(dv); + } + + error_propagate(errp, err); + return ret; +} + + static int net_host_check_device(const char *device) { int i; @@ -1286,7 +1049,7 @@ void qmp_netdev_del(const char *id, Error **errp) static void print_net_client(Monitor *mon, VLANClientState *vc) { monitor_printf(mon, "%s: type=%s,%s\n", vc->name, - net_client_types[vc->info->type].type, vc->info_str); + NetClientOptionsKind_lookup[vc->info->type], vc->info_str); } void do_info_network(Monitor *mon) diff --git a/net/dump.c b/net/dump.c index 2124b9a081..27e95280e3 100644 --- a/net/dump.c +++ b/net/dump.c @@ -144,7 +144,8 @@ static int net_dump_init(VLANState *vlan, const char *device, return 0; } -int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_dump(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { int len; const char *file; diff --git a/net/dump.h b/net/dump.h index 2b5d9ba644..85ac00be2c 100644 --- a/net/dump.h +++ b/net/dump.h @@ -26,7 +26,9 @@ #include "net.h" #include "qemu-common.h" +#include "qapi-types.h" -int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_dump(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); #endif /* QEMU_NET_DUMP_H */ diff --git a/net/slirp.c b/net/slirp.c index 1f63d50ed7..1243d43926 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -708,7 +708,8 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa return 0; } -int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_slirp(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { struct slirp_config_str *config; const char *vhost; diff --git a/net/slirp.h b/net/slirp.h index 53fe95dc12..ef13a65e9c 100644 --- a/net/slirp.h +++ b/net/slirp.h @@ -27,10 +27,12 @@ #include "qemu-common.h" #include "qdict.h" #include "qemu-option.h" +#include "qapi-types.h" #ifdef CONFIG_SLIRP -int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_slirp(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); diff --git a/net/socket.c b/net/socket.c index 30536efbaf..563447d02e 100644 --- a/net/socket.c +++ b/net/socket.c @@ -586,7 +586,8 @@ static int net_socket_udp_init(VLANState *vlan, return 0; } -int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_socket(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { if (qemu_opt_get(opts, "fd")) { int fd; diff --git a/net/socket.h b/net/socket.h index e1fe959412..e44d26ea9e 100644 --- a/net/socket.h +++ b/net/socket.h @@ -26,7 +26,9 @@ #include "net.h" #include "qemu-common.h" +#include "qapi-types.h" -int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_socket(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); #endif /* QEMU_NET_SOCKET_H */ diff --git a/net/tap-win32.c b/net/tap-win32.c index f7b6129131..b738f45bd6 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -699,7 +699,8 @@ static int tap_win32_init(VLANState *vlan, const char *model, return 0; } -int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { const char *ifname; diff --git a/net/tap.c b/net/tap.c index 9131ef5564..0fc856c0b4 100644 --- a/net/tap.c +++ b/net/tap.c @@ -513,7 +513,8 @@ static int net_bridge_run_helper(const char *helper, const char *bridge) return -1; } -int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { TAPState *s; int fd, vnet_hdr; @@ -583,7 +584,8 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr) return fd; } -int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { TAPState *s; int fd, vnet_hdr = 0; diff --git a/net/tap.h b/net/tap.h index b2a9450aab..44e31cefa9 100644 --- a/net/tap.h +++ b/net/tap.h @@ -28,11 +28,13 @@ #include "qemu-common.h" #include "qemu-option.h" +#include "qapi-types.h" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); @@ -57,6 +59,7 @@ int tap_get_fd(VLANClientState *vc); struct vhost_net; struct vhost_net *tap_get_vhost_net(VLANClientState *vc); -int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); #endif /* QEMU_NET_TAP_H */ diff --git a/net/vde.c b/net/vde.c index 0e8bf23222..8e60f68800 100644 --- a/net/vde.c +++ b/net/vde.c @@ -110,7 +110,8 @@ static int net_vde_init(VLANState *vlan, const char *model, return 0; } -int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan) +int net_init_vde(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan) { const char *sock; const char *group; diff --git a/net/vde.h b/net/vde.h index 732e5756f6..5fc17f980e 100644 --- a/net/vde.h +++ b/net/vde.h @@ -26,10 +26,12 @@ #include "qemu-common.h" #include "qemu-option.h" +#include "qapi-types.h" #ifdef CONFIG_VDE -int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan); +int net_init_vde(QemuOpts *opts, const NetClientOptions *new_opts, + const char *name, VLANState *vlan); #endif /* CONFIG_VDE */ From 2456f36f18c29ccc343fc676ef1af32e26cd7c88 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:14 +0200 Subject: [PATCH 12/19] convert net_init_nic() to NetClientOptions v1->v2: - NetLegacyNicOptions::vectors is of type uint32 Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/net.c b/net.c index af544b2479..a62e9025c1 100644 --- a/net.c +++ b/net.c @@ -748,12 +748,15 @@ int net_handle_fd_param(Monitor *mon, const char *param) return fd; } -static int net_init_nic(QemuOpts *opts, const NetClientOptions *new_opts, +static int net_init_nic(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { int idx; NICInfo *nd; - const char *netdev; + const NetLegacyNicOptions *nic; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC); + nic = opts->nic; idx = nic_get_free_idx(); if (idx == -1 || nb_nics >= MAX_NICS) { @@ -765,10 +768,10 @@ static int net_init_nic(QemuOpts *opts, const NetClientOptions *new_opts, memset(nd, 0, sizeof(*nd)); - if ((netdev = qemu_opt_get(opts, "netdev"))) { - nd->netdev = qemu_find_netdev(netdev); + if (nic->has_netdev) { + nd->netdev = qemu_find_netdev(nic->netdev); if (!nd->netdev) { - error_report("netdev '%s' not found", netdev); + error_report("netdev '%s' not found", nic->netdev); return -1; } } else { @@ -778,26 +781,28 @@ static int net_init_nic(QemuOpts *opts, const NetClientOptions *new_opts, if (name) { nd->name = g_strdup(name); } - if (qemu_opt_get(opts, "model")) { - nd->model = g_strdup(qemu_opt_get(opts, "model")); + if (nic->has_model) { + nd->model = g_strdup(nic->model); } - if (qemu_opt_get(opts, "addr")) { - nd->devaddr = g_strdup(qemu_opt_get(opts, "addr")); + if (nic->has_addr) { + nd->devaddr = g_strdup(nic->addr); } - if (qemu_opt_get(opts, "macaddr") && - net_parse_macaddr(nd->macaddr.a, qemu_opt_get(opts, "macaddr")) < 0) { + if (nic->has_macaddr && + net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) { error_report("invalid syntax for ethernet address"); return -1; } qemu_macaddr_default_if_unset(&nd->macaddr); - nd->nvectors = qemu_opt_get_number(opts, "vectors", - DEV_NVECTORS_UNSPECIFIED); - if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - (nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) { - error_report("invalid # of vectors: %d", nd->nvectors); - return -1; + if (nic->has_vectors) { + if (nic->vectors > 0x7ffffff) { + error_report("invalid # of vectors: %"PRIu32, nic->vectors); + return -1; + } + nd->nvectors = nic->vectors; + } else { + nd->nvectors = DEV_NVECTORS_UNSPECIFIED; } nd->used = 1; From 848040d1748e6d3871c319960ecfafce29f410a3 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:15 +0200 Subject: [PATCH 13/19] convert net_init_dump() to NetClientOptions v1->v2: - NetdevDumpOptions::len is of type 'size', whose C type was changed to uint64_t. Adapt the printf() format specifier macro. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/dump.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/net/dump.c b/net/dump.c index 27e95280e3..f3d2fa9875 100644 --- a/net/dump.c +++ b/net/dump.c @@ -144,22 +144,35 @@ static int net_dump_init(VLANState *vlan, const char *device, return 0; } -int net_init_dump(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_dump(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { int len; const char *file; char def_file[128]; + const NetdevDumpOptions *dump; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP); + dump = opts->dump; assert(vlan); - file = qemu_opt_get(opts, "file"); - if (!file) { + if (dump->has_file) { + file = dump->file; + } else { snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id); file = def_file; } - len = qemu_opt_get_size(opts, "len", 65536); + if (dump->has_len) { + if (dump->len > INT_MAX) { + error_report("invalid length: %"PRIu64, dump->len); + return -1; + } + len = dump->len; + } else { + len = 65536; + } return net_dump_init(vlan, "dump", name, file, len); } From 094f15c5c80a835dbe69afa8534909c681d35856 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:16 +0200 Subject: [PATCH 14/19] convert net_init_slirp() to NetClientOptions Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/slirp.c | 95 +++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 69 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 1243d43926..44b059f233 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -686,89 +686,46 @@ void do_info_usernet(Monitor *mon) } } -static int net_init_slirp_configs(const char *name, const char *value, void *opaque) +static void +net_init_slirp_configs(const StringList *fwd, int flags) { - struct slirp_config_str *config; + while (fwd) { + struct slirp_config_str *config; - if (strcmp(name, "hostfwd") != 0 && strcmp(name, "guestfwd") != 0) { - return 0; + config = g_malloc0(sizeof(*config)); + pstrcpy(config->str, sizeof(config->str), fwd->value->str); + config->flags = flags; + config->next = slirp_configs; + slirp_configs = config; + + fwd = fwd->next; } - - config = g_malloc0(sizeof(*config)); - - pstrcpy(config->str, sizeof(config->str), value); - - if (!strcmp(name, "hostfwd")) { - config->flags = SLIRP_CFG_HOSTFWD; - } - - config->next = slirp_configs; - slirp_configs = config; - - return 0; } -int net_init_slirp(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_slirp(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { struct slirp_config_str *config; - const char *vhost; - const char *vhostname; - const char *vdhcp_start; - const char *vnamesrv; - const char *tftp_export; - const char *bootfile; - const char *smb_export; - const char *vsmbsrv; - const char *restrict_opt; - char *vnet = NULL; - int restricted = 0; + char *vnet; int ret; + const NetdevUserOptions *user; - vhost = qemu_opt_get(opts, "host"); - vhostname = qemu_opt_get(opts, "hostname"); - vdhcp_start = qemu_opt_get(opts, "dhcpstart"); - vnamesrv = qemu_opt_get(opts, "dns"); - tftp_export = qemu_opt_get(opts, "tftp"); - bootfile = qemu_opt_get(opts, "bootfile"); - smb_export = qemu_opt_get(opts, "smb"); - vsmbsrv = qemu_opt_get(opts, "smbserver"); + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_USER); + user = opts->user; - restrict_opt = qemu_opt_get(opts, "restrict"); - if (restrict_opt) { - if (!strcmp(restrict_opt, "on") || - !strcmp(restrict_opt, "yes") || !strcmp(restrict_opt, "y")) { - restricted = 1; - } else if (strcmp(restrict_opt, "off") && - strcmp(restrict_opt, "no") && strcmp(restrict_opt, "n")) { - error_report("invalid option: 'restrict=%s'", restrict_opt); - return -1; - } - } + vnet = user->has_net ? g_strdup(user->net) : + user->has_ip ? g_strdup_printf("%s/24", user->ip) : + NULL; - if (qemu_opt_get(opts, "ip")) { - const char *ip = qemu_opt_get(opts, "ip"); - int l = strlen(ip) + strlen("/24") + 1; + /* all optional fields are initialized to "all bits zero" */ - vnet = g_malloc(l); + net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD); + net_init_slirp_configs(user->guestfwd, 0); - /* emulate legacy ip= parameter */ - pstrcpy(vnet, l, ip); - pstrcat(vnet, l, "/24"); - } - - if (qemu_opt_get(opts, "net")) { - if (vnet) { - g_free(vnet); - } - vnet = g_strdup(qemu_opt_get(opts, "net")); - } - - qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0); - - ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost, - vhostname, tftp_export, bootfile, vdhcp_start, - vnamesrv, smb_export, vsmbsrv); + ret = net_slirp_init(vlan, "user", name, user->restrict, vnet, user->host, + user->hostname, user->tftp, user->bootfile, + user->dhcpstart, user->dns, user->smb, + user->smbserver); while (slirp_configs) { config = slirp_configs; From bef8e8fe07e80821992f61d3775c6ac3766eee48 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:17 +0200 Subject: [PATCH 15/19] convert net_init_socket() to NetClientOptions I "reverse engineered" the following permissions between the -socket sub-options: fd listen connect mcast udp | localaddr fd x . . . . | . listen . x . . . | . connect . . x . . | . mcast . . . x . | x udp . . . . x | x -------------------------------------------+ localaddr . . . x x x I transformed the code accordingly. The real fix would be to embed "fd", "listen", "connect", "mcast" and "udp" in a separate union. However OptsVisitor's enum parser only supports the type=XXX QemuOpt instance as union discriminator. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/socket.c | 125 +++++++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 79 deletions(-) diff --git a/net/socket.c b/net/socket.c index 563447d02e..e3cba20cd9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -586,101 +586,68 @@ static int net_socket_udp_init(VLANState *vlan, return 0; } -int net_init_socket(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_socket(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { - if (qemu_opt_get(opts, "fd")) { + const NetdevSocketOptions *sock; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET); + sock = opts->socket; + + if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast + + sock->has_udp != 1) { + error_report("exactly one of fd=, listen=, connect=, mcast= or udp=" + " is required"); + return -1; + } + + if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) { + error_report("localaddr= is only valid with mcast= or udp="); + return -1; + } + + if (sock->has_fd) { int fd; - if (qemu_opt_get(opts, "listen") || - qemu_opt_get(opts, "connect") || - qemu_opt_get(opts, "mcast") || - qemu_opt_get(opts, "localaddr")) { - error_report("listen=, connect=, mcast= and localaddr= is invalid with fd="); + fd = net_handle_fd_param(cur_mon, sock->fd); + if (fd == -1 || !net_socket_fd_init(vlan, "socket", name, fd, 1)) { return -1; } + return 0; + } - fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd")); - if (fd == -1) { + if (sock->has_listen) { + if (net_socket_listen_init(vlan, "socket", name, sock->listen) == -1) { return -1; } + return 0; + } - if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) { + if (sock->has_connect) { + if (net_socket_connect_init(vlan, "socket", name, sock->connect) == + -1) { return -1; } - } else if (qemu_opt_get(opts, "listen")) { - const char *listen; + return 0; + } - if (qemu_opt_get(opts, "fd") || - qemu_opt_get(opts, "connect") || - qemu_opt_get(opts, "mcast") || - qemu_opt_get(opts, "localaddr")) { - error_report("fd=, connect=, mcast= and localaddr= is invalid with listen="); + if (sock->has_mcast) { + /* if sock->localaddr is missing, it has been initialized to "all bits + * zero" */ + if (net_socket_mcast_init(vlan, "socket", name, sock->mcast, + sock->localaddr) == -1) { return -1; } + return 0; + } - listen = qemu_opt_get(opts, "listen"); - - if (net_socket_listen_init(vlan, "socket", name, listen) == -1) { - return -1; - } - } else if (qemu_opt_get(opts, "connect")) { - const char *connect; - - if (qemu_opt_get(opts, "fd") || - qemu_opt_get(opts, "listen") || - qemu_opt_get(opts, "mcast") || - qemu_opt_get(opts, "localaddr")) { - error_report("fd=, listen=, mcast= and localaddr= is invalid with connect="); - return -1; - } - - connect = qemu_opt_get(opts, "connect"); - - if (net_socket_connect_init(vlan, "socket", name, connect) == -1) { - return -1; - } - } else if (qemu_opt_get(opts, "mcast")) { - const char *mcast, *localaddr; - - if (qemu_opt_get(opts, "fd") || - qemu_opt_get(opts, "connect") || - qemu_opt_get(opts, "listen")) { - error_report("fd=, connect= and listen= is invalid with mcast="); - return -1; - } - - mcast = qemu_opt_get(opts, "mcast"); - localaddr = qemu_opt_get(opts, "localaddr"); - - if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { - return -1; - } - } else if (qemu_opt_get(opts, "udp")) { - const char *udp, *localaddr; - - if (qemu_opt_get(opts, "fd") || - qemu_opt_get(opts, "connect") || - qemu_opt_get(opts, "listen") || - qemu_opt_get(opts, "mcast")) { - error_report("fd=, connect=, listen=" - " and mcast= is invalid with udp="); - return -1; - } - - udp = qemu_opt_get(opts, "udp"); - localaddr = qemu_opt_get(opts, "localaddr"); - if (localaddr == NULL) { - error_report("localaddr= is mandatory with udp="); - return -1; - } - - if (net_socket_udp_init(vlan, "udp", name, udp, localaddr) == -1) { - return -1; - } - } else { - error_report("-socket requires fd=, listen=," - " connect=, mcast= or udp="); + assert(sock->has_udp); + if (!sock->has_localaddr) { + error_report("localaddr= is mandatory with udp="); + return -1; + } + if (net_socket_udp_init(vlan, "udp", name, sock->udp, sock->localaddr) == + -1) { return -1; } return 0; From 4a917c39aed9ad7f648c435204a6586c4ca3f2f2 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:18 +0200 Subject: [PATCH 16/19] convert net_init_vde() to NetClientOptions v1->v2: - NetdevVdeOptions::port and ::mode are of type uint16. Remove superfluous range checks. Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/vde.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/net/vde.c b/net/vde.c index 8e60f68800..703888c503 100644 --- a/net/vde.c +++ b/net/vde.c @@ -110,20 +110,17 @@ static int net_vde_init(VLANState *vlan, const char *model, return 0; } -int net_init_vde(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_vde(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { - const char *sock; - const char *group; - int port, mode; + const NetdevVdeOptions *vde; - sock = qemu_opt_get(opts, "sock"); - group = qemu_opt_get(opts, "group"); + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VDE); + vde = opts->vde; - port = qemu_opt_get_number(opts, "port", 0); - mode = qemu_opt_get_number(opts, "mode", 0700); - - if (net_vde_init(vlan, "vde", name, sock, port, group, mode) == -1) { + /* missing optional values have been initialized to "all bits zero" */ + if (net_vde_init(vlan, "vde", name, vde->sock, vde->port, vde->group, + vde->has_mode ? vde->mode : 0700) == -1) { return -1; } From 08c573a8d14893518df412c68541aae5b7091982 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:19 +0200 Subject: [PATCH 17/19] convert net_init_tap() to NetClientOptions Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/tap-aix.c | 2 +- net/tap-bsd.c | 2 +- net/tap-haiku.c | 2 +- net/tap-linux.c | 9 ++-- net/tap-solaris.c | 2 +- net/tap-win32.c | 11 ++--- net/tap.c | 111 ++++++++++++++++++++++------------------------ net/tap.h | 2 +- 8 files changed, 71 insertions(+), 70 deletions(-) diff --git a/net/tap-aix.c b/net/tap-aix.c index e19aaba110..f27c17729e 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -31,7 +31,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required return -1; } -int tap_set_sndbuf(int fd, QemuOpts *opts) +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { return 0; } diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 937a94b11f..a3b717dd1c 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -117,7 +117,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required return fd; } -int tap_set_sndbuf(int fd, QemuOpts *opts) +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { return 0; } diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 91dda8ebc0..34739d1562 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -31,7 +31,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required return -1; } -int tap_set_sndbuf(int fd, QemuOpts *opts) +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { return 0; } diff --git a/net/tap-linux.c b/net/tap-linux.c index 41d581b734..c6521bec34 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -98,16 +98,19 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required */ #define TAP_DEFAULT_SNDBUF 0 -int tap_set_sndbuf(int fd, QemuOpts *opts) +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { int sndbuf; - sndbuf = qemu_opt_get_size(opts, "sndbuf", TAP_DEFAULT_SNDBUF); + sndbuf = !tap->has_sndbuf ? TAP_DEFAULT_SNDBUF : + tap->sndbuf > INT_MAX ? INT_MAX : + tap->sndbuf; + if (!sndbuf) { sndbuf = INT_MAX; } - if (ioctl(fd, TUNSETSNDBUF, &sndbuf) == -1 && qemu_opt_get(opts, "sndbuf")) { + if (ioctl(fd, TUNSETSNDBUF, &sndbuf) == -1 && tap->has_sndbuf) { error_report("TUNSETSNDBUF ioctl failed: %s", strerror(errno)); return -1; } diff --git a/net/tap-solaris.c b/net/tap-solaris.c index cf764634ef..5d6ac42f24 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -197,7 +197,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required return fd; } -int tap_set_sndbuf(int fd, QemuOpts *opts) +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { return 0; } diff --git a/net/tap-win32.c b/net/tap-win32.c index b738f45bd6..b6099cd847 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -699,19 +699,20 @@ static int tap_win32_init(VLANState *vlan, const char *model, return 0; } -int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_tap(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { - const char *ifname; + const NetdevTapOptions *tap; - ifname = qemu_opt_get(opts, "ifname"); + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); + tap = opts->tap; - if (!ifname) { + if (!tap->has_ifname) { error_report("tap: no interface name"); return -1; } - if (tap_win32_init(vlan, "tap", name, ifname) == -1) { + if (tap_win32_init(vlan, "tap", name, tap->ifname) == -1) { return -1; } diff --git a/net/tap.c b/net/tap.c index 0fc856c0b4..c5563c0b4e 100644 --- a/net/tap.c +++ b/net/tap.c @@ -548,29 +548,32 @@ int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, return 0; } -static int net_tap_init(QemuOpts *opts, int *vnet_hdr) +static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, + const char *setup_script, char *ifname, + size_t ifname_sz) { int fd, vnet_hdr_required; - char ifname[128] = {0,}; - const char *setup_script; - if (qemu_opt_get(opts, "ifname")) { - pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname")); + if (tap->has_ifname) { + pstrcpy(ifname, ifname_sz, tap->ifname); + } else { + assert(ifname_sz > 0); + ifname[0] = '\0'; } - *vnet_hdr = qemu_opt_get_bool(opts, "vnet_hdr", 1); - if (qemu_opt_get(opts, "vnet_hdr")) { + if (tap->has_vnet_hdr) { + *vnet_hdr = tap->vnet_hdr; vnet_hdr_required = *vnet_hdr; } else { + *vnet_hdr = 1; vnet_hdr_required = 0; } - TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr, vnet_hdr_required)); + TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required)); if (fd < 0) { return -1; } - setup_script = qemu_opt_get(opts, "script"); if (setup_script && setup_script[0] != '\0' && strcmp(setup_script, "no") != 0 && @@ -579,30 +582,34 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr) return -1; } - qemu_opt_set(opts, "ifname", ifname); - return fd; } -int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_tap(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { - TAPState *s; + const NetdevTapOptions *tap; + int fd, vnet_hdr = 0; const char *model; + TAPState *s; - if (qemu_opt_get(opts, "fd")) { - if (qemu_opt_get(opts, "ifname") || - qemu_opt_get(opts, "script") || - qemu_opt_get(opts, "downscript") || - qemu_opt_get(opts, "vnet_hdr") || - qemu_opt_get(opts, "helper")) { + /* for the no-fd, no-helper case */ + const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ + char ifname[128]; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); + tap = opts->tap; + + if (tap->has_fd) { + if (tap->has_ifname || tap->has_script || tap->has_downscript || + tap->has_vnet_hdr || tap->has_helper) { error_report("ifname=, script=, downscript=, vnet_hdr=, " "and helper= are invalid with fd="); return -1; } - fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd")); + fd = net_handle_fd_param(cur_mon, tap->fd); if (fd == -1) { return -1; } @@ -613,18 +620,15 @@ int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, model = "tap"; - } else if (qemu_opt_get(opts, "helper")) { - if (qemu_opt_get(opts, "ifname") || - qemu_opt_get(opts, "script") || - qemu_opt_get(opts, "downscript") || - qemu_opt_get(opts, "vnet_hdr")) { + } else if (tap->has_helper) { + if (tap->has_ifname || tap->has_script || tap->has_downscript || + tap->has_vnet_hdr) { error_report("ifname=, script=, downscript=, and vnet_hdr= " "are invalid with helper="); return -1; } - fd = net_bridge_run_helper(qemu_opt_get(opts, "helper"), - DEFAULT_BRIDGE_INTERFACE); + fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE); if (fd == -1) { return -1; } @@ -636,15 +640,8 @@ int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, model = "bridge"; } else { - if (!qemu_opt_get(opts, "script")) { - qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT); - } - - if (!qemu_opt_get(opts, "downscript")) { - qemu_opt_set(opts, "downscript", DEFAULT_NETWORK_DOWN_SCRIPT); - } - - fd = net_tap_init(opts, &vnet_hdr); + script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; + fd = net_tap_init(tap, &vnet_hdr, script, ifname, sizeof ifname); if (fd == -1) { return -1; } @@ -658,25 +655,24 @@ int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, return -1; } - if (tap_set_sndbuf(s->fd, opts) < 0) { + if (tap_set_sndbuf(s->fd, tap) < 0) { return -1; } - if (qemu_opt_get(opts, "fd")) { + if (tap->has_fd) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); - } else if (qemu_opt_get(opts, "helper")) { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "helper=%s", qemu_opt_get(opts, "helper")); + } else if (tap->has_helper) { + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", + tap->helper); } else { - const char *ifname, *script, *downscript; + const char *downscript; - ifname = qemu_opt_get(opts, "ifname"); - script = qemu_opt_get(opts, "script"); - downscript = qemu_opt_get(opts, "downscript"); + downscript = tap->has_downscript ? tap->downscript : + DEFAULT_NETWORK_DOWN_SCRIPT; snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "ifname=%s,script=%s,downscript=%s", - ifname, script, downscript); + "ifname=%s,script=%s,downscript=%s", ifname, script, + downscript); if (strcmp(downscript, "no") != 0) { snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); @@ -684,25 +680,26 @@ int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, } } - if (qemu_opt_get_bool(opts, "vhost", !!qemu_opt_get(opts, "vhostfd") || - qemu_opt_get_bool(opts, "vhostforce", false))) { - int vhostfd, r; - bool force = qemu_opt_get_bool(opts, "vhostforce", false); - if (qemu_opt_get(opts, "vhostfd")) { - r = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "vhostfd")); - if (r == -1) { + if (tap->has_vhost ? tap->vhost : + tap->has_vhostfd || (tap->has_vhostforce && tap->vhostforce)) { + int vhostfd; + + if (tap->has_vhostfd) { + vhostfd = net_handle_fd_param(cur_mon, tap->vhostfd); + if (vhostfd == -1) { return -1; } - vhostfd = r; } else { vhostfd = -1; } - s->vhost_net = vhost_net_init(&s->nc, vhostfd, force); + + s->vhost_net = vhost_net_init(&s->nc, vhostfd, + tap->has_vhostforce && tap->vhostforce); if (!s->vhost_net) { error_report("vhost-net requested but could not be initialized"); return -1; } - } else if (qemu_opt_get(opts, "vhostfd")) { + } else if (tap->has_vhostfd) { error_report("vhostfd= is not valid without vhost"); return -1; } diff --git a/net/tap.h b/net/tap.h index 44e31cefa9..f092129cef 100644 --- a/net/tap.h +++ b/net/tap.h @@ -47,7 +47,7 @@ void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo); void tap_set_vnet_hdr_len(VLANClientState *vc, int len); -int tap_set_sndbuf(int fd, QemuOpts *opts); +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap); int tap_probe_vnet_hdr(int fd); int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); From f79b51b081e48fb307a9438eb0e7326806bc19d3 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:20 +0200 Subject: [PATCH 18/19] convert net_init_bridge() to NetClientOptions Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net/tap.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/tap.c b/net/tap.c index c5563c0b4e..d2736eae76 100644 --- a/net/tap.c +++ b/net/tap.c @@ -513,21 +513,22 @@ static int net_bridge_run_helper(const char *helper, const char *bridge) return -1; } -int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, +int net_init_bridge(QemuOpts *old_opts, const NetClientOptions *opts, const char *name, VLANState *vlan) { + const NetdevBridgeOptions *bridge; + const char *helper, *br; + TAPState *s; int fd, vnet_hdr; - if (!qemu_opt_get(opts, "br")) { - qemu_opt_set(opts, "br", DEFAULT_BRIDGE_INTERFACE); - } - if (!qemu_opt_get(opts, "helper")) { - qemu_opt_set(opts, "helper", DEFAULT_BRIDGE_HELPER); - } + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_BRIDGE); + bridge = opts->bridge; - fd = net_bridge_run_helper(qemu_opt_get(opts, "helper"), - qemu_opt_get(opts, "br")); + helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER; + br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE; + + fd = net_bridge_run_helper(helper, br); if (fd == -1) { return -1; } @@ -542,8 +543,8 @@ int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, return -1; } - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", - qemu_opt_get(opts, "helper"), qemu_opt_get(opts, "br")); + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper, + br); return 0; } From 1a0c09583df097d62b0580f9073ba45c9d18351a Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 17 Jul 2012 16:17:21 +0200 Subject: [PATCH 19/19] remove unused QemuOpts parameter from net init functions v1->v2: - unchanged v2->v3: - keep "qemu-option.h" included in "net/slirp.h" Signed-off-by: Laszlo Ersek Signed-off-by: Stefan Hajnoczi --- net.c | 14 ++++++-------- net/dump.c | 4 ++-- net/dump.h | 5 ++--- net/slirp.c | 4 ++-- net/slirp.h | 4 ++-- net/socket.c | 4 ++-- net/socket.h | 5 ++--- net/tap-win32.c | 4 ++-- net/tap.c | 8 ++++---- net/tap.h | 9 ++++----- net/vde.c | 4 ++-- net/vde.h | 5 ++--- 12 files changed, 32 insertions(+), 38 deletions(-) diff --git a/net.c b/net.c index a62e9025c1..dbca77bad1 100644 --- a/net.c +++ b/net.c @@ -748,8 +748,8 @@ int net_handle_fd_param(Monitor *mon, const char *param) return fd; } -static int net_init_nic(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +static int net_init_nic(const NetClientOptions *opts, const char *name, + VLANState *vlan) { int idx; NICInfo *nd; @@ -813,8 +813,7 @@ static int net_init_nic(QemuOpts *old_opts, const NetClientOptions *opts, static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])( - QemuOpts *old_opts, - const NetClientOptions *new_opts, + const NetClientOptions *opts, const char *name, VLANState *vlan) = { [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, @@ -833,8 +832,7 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])( }; -static int net_client_init1(const void *object, int is_netdev, - QemuOpts *old_opts, Error **errp) +static int net_client_init1(const void *object, int is_netdev, Error **errp) { union { const Netdev *netdev; @@ -885,7 +883,7 @@ static int net_client_init1(const void *object, int is_netdev, vlan = qemu_find_vlan(u.net->has_vlan ? u.net->vlan : 0, true); } - if (net_client_init_fun[opts->kind](old_opts, opts, name, vlan) < 0) { + if (net_client_init_fun[opts->kind](opts, name, vlan) < 0) { /* TODO push error reporting into init() methods */ error_set(errp, QERR_DEVICE_INIT_FAILED, NetClientOptionsKind_lookup[opts->kind]); @@ -920,7 +918,7 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) } if (!err) { - ret = net_client_init1(object, is_netdev, opts, &err); + ret = net_client_init1(object, is_netdev, &err); } if (object) { diff --git a/net/dump.c b/net/dump.c index f3d2fa9875..b575430787 100644 --- a/net/dump.c +++ b/net/dump.c @@ -144,8 +144,8 @@ static int net_dump_init(VLANState *vlan, const char *device, return 0; } -int net_init_dump(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_dump(const NetClientOptions *opts, const char *name, + VLANState *vlan) { int len; const char *file; diff --git a/net/dump.h b/net/dump.h index 85ac00be2c..0fa2dd72ca 100644 --- a/net/dump.h +++ b/net/dump.h @@ -25,10 +25,9 @@ #define QEMU_NET_DUMP_H #include "net.h" -#include "qemu-common.h" #include "qapi-types.h" -int net_init_dump(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_dump(const NetClientOptions *opts, const char *name, + VLANState *vlan); #endif /* QEMU_NET_DUMP_H */ diff --git a/net/slirp.c b/net/slirp.c index 44b059f233..5c2e6b2cec 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -702,8 +702,8 @@ net_init_slirp_configs(const StringList *fwd, int flags) } } -int net_init_slirp(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_slirp(const NetClientOptions *opts, const char *name, + VLANState *vlan) { struct slirp_config_str *config; char *vnet; diff --git a/net/slirp.h b/net/slirp.h index ef13a65e9c..e2c71eeca0 100644 --- a/net/slirp.h +++ b/net/slirp.h @@ -31,8 +31,8 @@ #ifdef CONFIG_SLIRP -int net_init_slirp(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_slirp(const NetClientOptions *opts, const char *name, + VLANState *vlan); void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); diff --git a/net/socket.c b/net/socket.c index e3cba20cd9..600c287d79 100644 --- a/net/socket.c +++ b/net/socket.c @@ -586,8 +586,8 @@ static int net_socket_udp_init(VLANState *vlan, return 0; } -int net_init_socket(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_socket(const NetClientOptions *opts, const char *name, + VLANState *vlan) { const NetdevSocketOptions *sock; diff --git a/net/socket.h b/net/socket.h index e44d26ea9e..c4809ad0d9 100644 --- a/net/socket.h +++ b/net/socket.h @@ -25,10 +25,9 @@ #define QEMU_NET_SOCKET_H #include "net.h" -#include "qemu-common.h" #include "qapi-types.h" -int net_init_socket(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_socket(const NetClientOptions *opts, const char *name, + VLANState *vlan); #endif /* QEMU_NET_SOCKET_H */ diff --git a/net/tap-win32.c b/net/tap-win32.c index b6099cd847..232807236a 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -699,8 +699,8 @@ static int tap_win32_init(VLANState *vlan, const char *model, return 0; } -int net_init_tap(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_tap(const NetClientOptions *opts, const char *name, + VLANState *vlan) { const NetdevTapOptions *tap; diff --git a/net/tap.c b/net/tap.c index d2736eae76..72062275fe 100644 --- a/net/tap.c +++ b/net/tap.c @@ -513,8 +513,8 @@ static int net_bridge_run_helper(const char *helper, const char *bridge) return -1; } -int net_init_bridge(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_bridge(const NetClientOptions *opts, const char *name, + VLANState *vlan) { const NetdevBridgeOptions *bridge; const char *helper, *br; @@ -586,8 +586,8 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, return fd; } -int net_init_tap(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_tap(const NetClientOptions *opts, const char *name, + VLANState *vlan) { const NetdevTapOptions *tap; diff --git a/net/tap.h b/net/tap.h index f092129cef..19dea58dc5 100644 --- a/net/tap.h +++ b/net/tap.h @@ -27,14 +27,13 @@ #define QEMU_NET_TAP_H #include "qemu-common.h" -#include "qemu-option.h" #include "qapi-types.h" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -int net_init_tap(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_tap(const NetClientOptions *opts, const char *name, + VLANState *vlan); int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); @@ -59,7 +58,7 @@ int tap_get_fd(VLANClientState *vc); struct vhost_net; struct vhost_net *tap_get_vhost_net(VLANClientState *vc); -int net_init_bridge(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_bridge(const NetClientOptions *opts, const char *name, + VLANState *vlan); #endif /* QEMU_NET_TAP_H */ diff --git a/net/vde.c b/net/vde.c index 703888c503..ee19f5c42c 100644 --- a/net/vde.c +++ b/net/vde.c @@ -110,8 +110,8 @@ static int net_vde_init(VLANState *vlan, const char *model, return 0; } -int net_init_vde(QemuOpts *old_opts, const NetClientOptions *opts, - const char *name, VLANState *vlan) +int net_init_vde(const NetClientOptions *opts, const char *name, + VLANState *vlan) { const NetdevVdeOptions *vde; diff --git a/net/vde.h b/net/vde.h index 5fc17f980e..ad502ef4de 100644 --- a/net/vde.h +++ b/net/vde.h @@ -25,13 +25,12 @@ #define QEMU_NET_VDE_H #include "qemu-common.h" -#include "qemu-option.h" #include "qapi-types.h" #ifdef CONFIG_VDE -int net_init_vde(QemuOpts *opts, const NetClientOptions *new_opts, - const char *name, VLANState *vlan); +int net_init_vde(const NetClientOptions *opts, const char *name, + VLANState *vlan); #endif /* CONFIG_VDE */