@samitouri / QOSamiQemu / commits / 8cb95c6126

net/qapi: add x-query-usernet command

Add a QMP command to query user-mode network stack (slirp) connection states, providing a structured alternative to "info usernet" HMP. The new command returns a list of UsernetInfo, with hub-id, hub-name, and connection info for each slirp stack. It is marked unstable as it is meant for debugging. Rewrite hmp_info_usernet() as a thin wrapper over qmp_x_query_usernet() so the HMP and QMP paths share the same implementation. This is part of the effort to decouple HMP from QEMU core. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com> Message-ID: <20260828-qemu-no-hmp-v5-10-9227de146347@redhat.com>

Marc-André Lureau committed Aug 28, 2026 at 16:04 UTC 8cb95c6126d6e72a73e983eed47ecb5a95e3248e
2 files changed +72 -6
net/slirp.c
+28 -6
@@ -43,6 +43,7 @@
43 #include "system/system.h"
44 #include "qemu/cutils.h"
45 #include "qapi/error.h"
46 +#include "qapi/qapi-commands-net.h"
47 #include "qobject/qdict.h"
48 #include "util.h"
49 #include "migration/register.h"
@@ -1200,18 +1201,39 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
1201 return -1;
1202 }
1203
1203 -void hmp_info_usernet(Monitor *mon, const QDict *qdict)
1204 +UsernetInfoList *qmp_x_query_usernet(Error **errp)
1205 {
1206 + UsernetInfoList *head = NULL, **tail = &head;
1207 SlirpState *s;
1208
1209 QTAILQ_FOREACH(s, &slirp_stacks, entry) {
1210 + UsernetInfo *ui = g_new0(UsernetInfo, 1);
1211 int id;
1209 - bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
1210 - char *info = slirp_connection_info(s->slirp);
1212 +
1213 + if (net_hub_id_for_client(&s->nc, &id) == 0) {
1214 + ui->has_hub_id = true;
1215 + ui->hub_id = id;
1216 + }
1217 + ui->hub_name = g_strdup(s->nc.name);
1218 + ui->info = slirp_connection_info(s->slirp);
1219 +
1220 + QAPI_LIST_APPEND(tail, ui);
1221 + }
1222 +
1223 + return head;
1224 +}
1225 +
1226 +void hmp_info_usernet(Monitor *mon, const QDict *qdict)
1227 +{
1228 + g_autoptr(UsernetInfoList) list = NULL;
1229 + UsernetInfoList *entry;
1230 +
1231 + list = qmp_x_query_usernet(&error_abort);
1232 + for (entry = list; entry; entry = entry->next) {
1233 + UsernetInfo *ui = entry->value;
1234 monitor_printf(mon, "Hub %d (%s):\n%s",
1212 - got_hub_id ? id : -1,
1213 - s->nc.name, info);
1214 - g_free(info);
1235 + ui->has_hub_id ? (int)ui->hub_id : -1,
1236 + ui->hub_name, ui->info);
1237 }
1238 }
1239
qapi/net.json
+44
@@ -1261,3 +1261,47 @@
1261 ##
1262 { 'event': 'NETDEV_VHOST_USER_DISCONNECTED',
1263 'data': { 'netdev-id': 'str' } }
1264 +
1265 +##
1266 +# @UsernetInfo:
1267 +#
1268 +# Information about a user-mode network stack (slirp).
1269 +#
1270 +# @hub-id: The hub id, if available.
1271 +#
1272 +# @hub-name: The name of the hub.
1273 +#
1274 +# @info: Network information from slirp.
1275 +#
1276 +# Since: 11.2
1277 +##
1278 +{ 'struct': 'UsernetInfo',
1279 + 'data': {
1280 + '*hub-id': 'int',
1281 + 'hub-name': 'str',
1282 + 'info': 'str' },
1283 + 'if': 'CONFIG_SLIRP' }
1284 +
1285 +##
1286 +# @x-query-usernet:
1287 +#
1288 +# Query user-mode network stack connection states.
1289 +#
1290 +# Features:
1291 +#
1292 +# @unstable: This command is meant for debugging.
1293 +#
1294 +# Returns: list of user-mode network stack information.
1295 +#
1296 +# Since: 11.2
1297 +#
1298 +# .. qmp-example::
1299 +#
1300 +# -> { "execute": "x-query-usernet" }
1301 +# <- { "return": [ { "hub-id": 0, "hub-name": "vnet",
1302 +# "info": "..." } ] }
1303 +##
1304 +{ 'command': 'x-query-usernet',
1305 + 'returns': ['UsernetInfo'],
1306 + 'if': 'CONFIG_SLIRP',
1307 + 'features': [ 'unstable' ] }