@@ -869,7 +869,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
u.net = object;
opts = u.net->opts;
/* missing optional values have been initialized to "all bits zero" */
- name = u.net->name;
+ name = u.net->has_id ? u.net->id : u.net->name;
}
if (net_client_init_fun[opts->kind]) {
@@ -2116,7 +2116,9 @@
#
# @vlan: #optional vlan number
#
-# @name: #optional identifier for monitor commands
+# @id: #optional identifier for monitor commands
+#
+# @name: #optional identifier for monitor commands, ignored if @id is present
#
# @traits: device type specific properties (legacy)
#
@@ -2125,6 +2127,7 @@
{ 'type': 'NetLegacy',
'data': {
'*vlan': 'int32',
+ '*id': 'str',
'*name': 'str',
'opts': 'NetClientOptions' } }
@@ -35,6 +35,12 @@ struct OptsVisitor
* 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;
};
@@ -46,6 +52,27 @@ destroy_list(gpointer 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)
{
@@ -60,21 +87,18 @@ opts_start_struct(Visitor *v, void **obj, const char *kind,
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) {
- GQueue *list;
+ /* ensured by qemu-option.c::opts_do_parse() */
+ assert(strcmp(opt->name, "id") != 0);
- list = g_hash_table_lookup(ov->unprocessed_opts, opt->name);
- if (list == NULL) {
- list = g_queue_new();
+ opts_visitor_insert(ov->unprocessed_opts, opt);
+ }
- /* GHashTable will never try to free the keys -- we supplied NULL
- * as "key_destroy_func" above. Thus cast away key const-ness in
- * order to suppress gcc's warning. */
- g_hash_table_insert(ov->unprocessed_opts, (gpointer)opt->name,
- list);
- }
+ if (ov->opts_root->id != NULL) {
+ ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt);
- /* Similarly, destroy_list() doesn't call g_queue_free_full(). */
- g_queue_push_tail(list, (gpointer)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);
}
}
@@ -390,6 +414,7 @@ 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);
}