Commit 22ef826531 for qemu.org

commit 22ef826531493f2556bbbb188e5bb0f4d095869a
Author: Markus Armbruster <armbru@redhat.com>
Date:   Wed May 6 12:54:20 2026 +0200

    qapi/net: Wean SLIRP off QAPI type String to improve documentation

    String's doc comment is useless.  Replace its use in NetdevUserOptions
    by identical types with hopefully useful documentation.

    While there, add a non-doc comment explaining why the port forwarding
    interface is problematic.

    Signed-off-by: Markus Armbruster <armbru@redhat.com>
    Message-ID: <20260506105421.2461117-4-armbru@redhat.com>
    Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
    [Commit message typo fixed]

diff --git a/net/slirp.c b/net/slirp.c
index 04925f3318..a00e0a9651 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -1215,14 +1215,14 @@ void hmp_info_usernet(Monitor *mon, const QDict *qdict)
 }

 static void
-net_init_slirp_configs(const StringList *fwd, int flags)
+net_init_slirp_configs_host(const NetdevUserHostForwardList *fwd)
 {
     while (fwd) {
         struct slirp_config_str *config;

         config = g_malloc0(sizeof(*config));
         pstrcpy(config->str, sizeof(config->str), fwd->value->str);
-        config->flags = flags;
+        config->flags = SLIRP_CFG_HOSTFWD;
         config->next = slirp_configs;
         slirp_configs = config;

@@ -1230,9 +1230,24 @@ net_init_slirp_configs(const StringList *fwd, int flags)
     }
 }

-static const char **slirp_dnssearch(const StringList *dnsname)
+static void
+net_init_slirp_configs_guest(const NetdevUserGuestForwardList *fwd)
+{
+    while (fwd) {
+        struct slirp_config_str *config;
+
+        config = g_malloc0(sizeof(*config));
+        pstrcpy(config->str, sizeof(config->str), fwd->value->str);
+        config->next = slirp_configs;
+        slirp_configs = config;
+
+        fwd = fwd->next;
+    }
+}
+
+static const char **slirp_dnssearch(const NetdevUserDomainSuffixList *dnsname)
 {
-    const StringList *c = dnsname;
+    const NetdevUserDomainSuffixList *c = dnsname;
     size_t i = 0, num_opts = 0;
     const char **ret;

@@ -1285,8 +1300,8 @@ int net_init_slirp(const Netdev *netdev, const char *name,

     /* all optional fields are initialized to "all bits zero" */

-    net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
-    net_init_slirp_configs(user->guestfwd, 0);
+    net_init_slirp_configs_host(user->hostfwd);
+    net_init_slirp_configs_guest(user->guestfwd);

     ret = net_slirp_init(peer, "user", name, user->q_restrict,
                          ipv4, vnet, user->host,
diff --git a/qapi/net.json b/qapi/net.json
index c95aa909a0..2f85956c32 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -264,6 +264,52 @@
     '*param':              ['PasstParameter'] },
     'if': 'CONFIG_PASST' }

+##
+# @NetdevUserDomainSuffix:
+#
+# @str: DNS domain name suffix for host name lookup, similar to
+#     resolv.conf(5)
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevUserDomainSuffix',
+  'data': {
+    'str': 'str' } }
+
+##
+# @NetdevUserHostForward:
+#
+# @str: Host port forwarding rule
+#
+# TODO: This string gets parsed by slirp_hostfwd().  We fail to
+#    document syntax and semantics here.  We do in qemu-options.hx.
+#    Parsing structured configuration from strings is a no-no for QMP.
+#    This should really be a struct.  Not sure it's worth the bother
+#    now.
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevUserHostForward',
+  'data': {
+    'str': 'str' } }
+
+##
+# @NetdevUserGuestForward:
+#
+# @str: Guest port forwarding rule
+#
+# TODO: This string gets parsed by slirp_guestfwd().  We fail to
+#    document syntax and semantics here.  We do in qemu-options.hx.
+#    Parsing structured configuration from strings is a no-no for QMP.
+#    This should really be a struct.  Not sure it's worth the bother
+#    now.
+#
+# Since: 1.2
+##
+{ 'struct': 'NetdevUserGuestForward',
+  'data': {
+    'str': 'str' } }
+
 ##
 # @NetdevUserOptions:
 #
@@ -340,7 +386,7 @@
     '*bootfile':  'str',
     '*dhcpstart': 'str',
     '*dns':       'str',
-    '*dnssearch': ['String'],
+    '*dnssearch': ['NetdevUserDomainSuffix'],
     '*domainname': 'str',
     '*ipv6-prefix':      'str',
     '*ipv6-prefixlen':   'int',
@@ -348,8 +394,8 @@
     '*ipv6-dns':         'str',
     '*smb':       'str',
     '*smbserver': 'str',
-    '*hostfwd':   ['String'],
-    '*guestfwd':  ['String'],
+    '*hostfwd':   ['NetdevUserHostForward'],
+    '*guestfwd':  ['NetdevUserGuestForward'],
     '*tftp-server-name': 'str' } }

 ##