As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field of Netdev structure can collides with "type" field of SocketAddress), we introduce a way to bypass qemu_opts_parse_noisily() and use directly visit_type_Netdev() to parse the backend parameters.
Signed-off-by: Laurent Vivier <lviv...@redhat.com> --- net/net.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/net/net.c b/net/net.c index 58c05c200622..2aab7167316c 100644 --- a/net/net.c +++ b/net/net.c @@ -54,6 +54,7 @@ #include "net/colo-compare.h" #include "net/filter.h" #include "qapi/string-output-visitor.h" +#include "qapi/qobject-input-visitor.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) @@ -63,6 +64,17 @@ static VMChangeStateEntry *net_change_state_entry; static QTAILQ_HEAD(, NetClientState) net_clients; +typedef struct NetdevQueueEntry { + bool is_netdev; + Netdev *nd; + Location loc; + QSIMPLEQ_ENTRY(NetdevQueueEntry) entry; +} NetdevQueueEntry; + +typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue; + +static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue); + /***********************************************************/ /* network device redirectors */ @@ -1559,6 +1571,19 @@ int net_init_clients(Error **errp) QTAILQ_INIT(&net_clients); + while (!QSIMPLEQ_EMPTY(&nd_queue)) { + NetdevQueueEntry *nd = QSIMPLEQ_FIRST(&nd_queue); + + QSIMPLEQ_REMOVE_HEAD(&nd_queue, entry); + loc_push_restore(&nd->loc); + if (net_client_init1(nd->nd, nd->is_netdev, errp) < 0) { + return -1; + } + loc_pop(&nd->loc); + qapi_free_Netdev(nd->nd); + g_free(nd); + } + if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, errp)) { return -1; @@ -1575,8 +1600,37 @@ int net_init_clients(Error **errp) return 0; } +/* + * netdev_is_modern() returns true when the backend needs to bypass + * qemu_opts_parse_noisily() + */ +static bool netdev_is_modern(const char *optarg) +{ + return false; +} + int net_client_parse(QemuOptsList *opts_list, const char *optarg) { + if (netdev_is_modern(optarg)) { + /* + * We need to bypass qemu_opts_parse_noisily() to accept + * new style object like addr.type=inet in SocketAddress + */ + Visitor *v; + NetdevQueueEntry *nd; + + v = qobject_input_visitor_new_str(optarg, "type", + &error_fatal); + nd = g_new(NetdevQueueEntry, 1); + visit_type_Netdev(v, NULL, &nd->nd, &error_fatal); + visit_free(v); + loc_save(&nd->loc); + nd->is_netdev = strcmp(opts_list->name, "netdev") == 0; + + QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry); + return 0; + } + if (!qemu_opts_parse_noisily(opts_list, optarg, true)) { return -1; } -- 2.35.3