From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876236; cv=none; d=zohomail.com; s=zohoarc; b=V0RAHXTMlovdlYOChXFL8HXdvpSszG3oRj9nIk5tCVSEVHKIF/SzeOgtIBhQ0zzuGVSpOQ5/ltfSVWjBBy+IuMJ4dji2DiZn5uLCOJUCn+VVHTV6xGtDtpKho8RcWgIK+1/lUkq9yH3zEck0p2HY/jUZXP8wmpjU+twXN6waL18= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876236; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=pip8H5LhecWwBCKCriggPkC9ndhlmXdBoFMDWaLqcpM=; b=nG54+wEupJDbrMmAVlTIhNZph0tbxKvb9Eims/PIg8sHDTnGeAbf5Rl5OzRyDzANMdG34dAuAVB3V46fPdxWYxUd9DF3dgBtA0q4TWWZiaS9hnPR7jqg9tvVTnDj7u+Hdn7xjxtRQ+JgNgf+Wwpdf7g0nR5yLgL4BYNGRwBr7d0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876236238517.451471723826; Mon, 7 Jul 2025 01:17:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0j-0008TN-Js; Mon, 07 Jul 2025 04:15:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0c-0008Qs-Dt for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0X-0007Kk-Jv for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:29 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-335-BUiyuuRHPECHz0WL9YZcIg-1; Mon, 07 Jul 2025 04:15:19 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B687E1809C84; Mon, 7 Jul 2025 08:15:17 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C5D4D18046C5; Mon, 7 Jul 2025 08:15:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876122; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pip8H5LhecWwBCKCriggPkC9ndhlmXdBoFMDWaLqcpM=; b=UOkdyIUc462BOPjoDJRugT5j+vfoYQUCRkqPTfFBo66MQ62VoZneqQiJeXOaF+e20I1Z8c Tz/pATygBggLB07F2/wGkH0LVbvRcHFQYS7Ips4upMwrpedYrifK0m4Y8WzgfP4yGSq9lu k75dZrLzmizUzGPFJpj9qDeyt/tG6Bo= X-MC-Unique: BUiyuuRHPECHz0WL9YZcIg-1 X-Mimecast-MFC-AGG-ID: BUiyuuRHPECHz0WL9YZcIg_1751876118 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 01/11] net: Refactor stream logic for reuse in '-net passt' Date: Mon, 7 Jul 2025 10:14:55 +0200 Message-ID: <20250707081505.127519-2-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876237152116600 Content-Type: text/plain; charset="utf-8" To prepare for the implementation of '-net passt', this patch moves the generic stream handling functions from net/stream.c into new net/stream_data.c and net/stream_data.h files. This refactoring introduces a NetStreamData struct that encapsulates the generic fields and logic previously in NetStreamState. The NetStreamState now embeds NetStreamData and delegates the core stream operations to the new generic functions. To maintain flexibility for different users of this generic code, callbacks for send and listen operations are now passed via function pointers within the NetStreamData struct. This allows callers to provide their own specific implementations while reusing the common connection and data transfer logic. Signed-off-by: Laurent Vivier --- net/meson.build | 3 +- net/stream.c | 282 +++++++++++----------------------------------- net/stream_data.c | 193 +++++++++++++++++++++++++++++++ net/stream_data.h | 31 +++++ 4 files changed, 290 insertions(+), 219 deletions(-) create mode 100644 net/stream_data.c create mode 100644 net/stream_data.h diff --git a/net/meson.build b/net/meson.build index bb97b4dcbeb6..bb3c011e5a30 100644 --- a/net/meson.build +++ b/net/meson.build @@ -1,6 +1,7 @@ system_ss.add(files( 'announce.c', 'checksum.c', + 'dgram.c', 'dump.c', 'eth.c', 'filter-buffer.c', @@ -12,7 +13,7 @@ system_ss.add(files( 'queue.c', 'socket.c', 'stream.c', - 'dgram.c', + 'stream_data.c', 'util.c', )) =20 diff --git a/net/stream.c b/net/stream.c index 6152d2a05e52..d893f02cabe3 100644 --- a/net/stream.c +++ b/net/stream.c @@ -27,173 +27,50 @@ =20 #include "net/net.h" #include "clients.h" -#include "monitor/monitor.h" #include "qapi/error.h" -#include "qemu/error-report.h" -#include "qemu/option.h" -#include "qemu/sockets.h" -#include "qemu/iov.h" -#include "qemu/main-loop.h" -#include "qemu/cutils.h" -#include "io/channel.h" -#include "io/channel-socket.h" #include "io/net-listener.h" #include "qapi/qapi-events-net.h" #include "qapi/qapi-visit-sockets.h" #include "qapi/clone-visitor.h" =20 +#include "stream_data.h" + typedef struct NetStreamState { - NetClientState nc; - QIOChannel *listen_ioc; - QIONetListener *listener; - QIOChannel *ioc; - guint ioc_read_tag; - guint ioc_write_tag; - SocketReadState rs; - unsigned int send_index; /* number of bytes sent*/ + NetStreamData data; uint32_t reconnect_ms; guint timer_tag; SocketAddress *addr; } NetStreamState; =20 -static void net_stream_listen(QIONetListener *listener, - QIOChannelSocket *cioc, - void *opaque); static void net_stream_arm_reconnect(NetStreamState *s); =20 -static gboolean net_stream_writable(QIOChannel *ioc, - GIOCondition condition, - gpointer data) -{ - NetStreamState *s =3D data; - - s->ioc_write_tag =3D 0; - - qemu_flush_queued_packets(&s->nc); - - return G_SOURCE_REMOVE; -} - static ssize_t net_stream_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - NetStreamState *s =3D DO_UPCAST(NetStreamState, nc, nc); - uint32_t len =3D htonl(size); - struct iovec iov[] =3D { - { - .iov_base =3D &len, - .iov_len =3D sizeof(len), - }, { - .iov_base =3D (void *)buf, - .iov_len =3D size, - }, - }; - struct iovec local_iov[2]; - unsigned int nlocal_iov; - size_t remaining; - ssize_t ret; - - remaining =3D iov_size(iov, 2) - s->send_index; - nlocal_iov =3D iov_copy(local_iov, 2, iov, 2, s->send_index, remaining= ); - ret =3D qio_channel_writev(s->ioc, local_iov, nlocal_iov, NULL); - if (ret =3D=3D QIO_CHANNEL_ERR_BLOCK) { - ret =3D 0; /* handled further down */ - } - if (ret =3D=3D -1) { - s->send_index =3D 0; - return -errno; - } - if (ret < (ssize_t)remaining) { - s->send_index +=3D ret; - s->ioc_write_tag =3D qio_channel_add_watch(s->ioc, G_IO_OUT, - net_stream_writable, s, N= ULL); - return 0; - } - s->send_index =3D 0; - return size; -} - -static gboolean net_stream_send(QIOChannel *ioc, - GIOCondition condition, - gpointer data); - -static void net_stream_send_completed(NetClientState *nc, ssize_t len) -{ - NetStreamState *s =3D DO_UPCAST(NetStreamState, nc, nc); - - if (!s->ioc_read_tag) { - s->ioc_read_tag =3D qio_channel_add_watch(s->ioc, G_IO_IN, - net_stream_send, s, NULL); - } -} + NetStreamData *d =3D DO_UPCAST(NetStreamData, nc, nc); =20 -static void net_stream_rs_finalize(SocketReadState *rs) -{ - NetStreamState *s =3D container_of(rs, NetStreamState, rs); - - if (qemu_send_packet_async(&s->nc, rs->buf, - rs->packet_len, - net_stream_send_completed) =3D=3D 0) { - if (s->ioc_read_tag) { - g_source_remove(s->ioc_read_tag); - s->ioc_read_tag =3D 0; - } - } + return net_stream_data_receive(d, buf, size); } =20 static gboolean net_stream_send(QIOChannel *ioc, GIOCondition condition, gpointer data) { - NetStreamState *s =3D data; - int size; - int ret; - QEMU_UNINITIALIZED char buf1[NET_BUFSIZE]; - const char *buf; - - size =3D qio_channel_read(s->ioc, buf1, sizeof(buf1), NULL); - if (size < 0) { - if (errno !=3D EWOULDBLOCK) { - goto eoc; - } - } else if (size =3D=3D 0) { - /* end of connection */ - eoc: - s->ioc_read_tag =3D 0; - if (s->ioc_write_tag) { - g_source_remove(s->ioc_write_tag); - s->ioc_write_tag =3D 0; - } - if (s->listener) { - qemu_set_info_str(&s->nc, "listening"); - qio_net_listener_set_client_func(s->listener, net_stream_liste= n, - s, NULL); - } - object_unref(OBJECT(s->ioc)); - s->ioc =3D NULL; - - net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); - s->nc.link_down =3D true; + if (net_stream_data_send(ioc, condition, data) =3D=3D G_SOURCE_REMOVE)= { + NetStreamState *s =3D DO_UPCAST(NetStreamState, data, data); =20 - qapi_event_send_netdev_stream_disconnected(s->nc.name); + qapi_event_send_netdev_stream_disconnected(s->data.nc.name); net_stream_arm_reconnect(s); =20 return G_SOURCE_REMOVE; } - buf =3D buf1; - - ret =3D net_fill_rstate(&s->rs, (const uint8_t *)buf, size); - - if (ret =3D=3D -1) { - goto eoc; - } =20 return G_SOURCE_CONTINUE; } =20 static void net_stream_cleanup(NetClientState *nc) { - NetStreamState *s =3D DO_UPCAST(NetStreamState, nc, nc); + NetStreamState *s =3D DO_UPCAST(NetStreamState, data.nc, nc); if (s->timer_tag) { g_source_remove(s->timer_tag); s->timer_tag =3D 0; @@ -202,28 +79,28 @@ static void net_stream_cleanup(NetClientState *nc) qapi_free_SocketAddress(s->addr); s->addr =3D NULL; } - if (s->ioc) { - if (QIO_CHANNEL_SOCKET(s->ioc)->fd !=3D -1) { - if (s->ioc_read_tag) { - g_source_remove(s->ioc_read_tag); - s->ioc_read_tag =3D 0; + if (s->data.ioc) { + if (QIO_CHANNEL_SOCKET(s->data.ioc)->fd !=3D -1) { + if (s->data.ioc_read_tag) { + g_source_remove(s->data.ioc_read_tag); + s->data.ioc_read_tag =3D 0; } - if (s->ioc_write_tag) { - g_source_remove(s->ioc_write_tag); - s->ioc_write_tag =3D 0; + if (s->data.ioc_write_tag) { + g_source_remove(s->data.ioc_write_tag); + s->data.ioc_write_tag =3D 0; } } - object_unref(OBJECT(s->ioc)); - s->ioc =3D NULL; + object_unref(OBJECT(s->data.ioc)); + s->data.ioc =3D NULL; } - if (s->listen_ioc) { - if (s->listener) { - qio_net_listener_disconnect(s->listener); - object_unref(OBJECT(s->listener)); - s->listener =3D NULL; + if (s->data.listen_ioc) { + if (s->data.listener) { + qio_net_listener_disconnect(s->data.listener); + object_unref(OBJECT(s->data.listener)); + s->data.listener =3D NULL; } - object_unref(OBJECT(s->listen_ioc)); - s->listen_ioc =3D NULL; + object_unref(OBJECT(s->data.listen_ioc)); + s->data.listen_ioc =3D NULL; } } =20 @@ -235,23 +112,13 @@ static NetClientInfo net_stream_info =3D { }; =20 static void net_stream_listen(QIONetListener *listener, - QIOChannelSocket *cioc, - void *opaque) + QIOChannelSocket *cioc, gpointer data) { - NetStreamState *s =3D opaque; + NetStreamData *d =3D data; SocketAddress *addr; char *uri; =20 - object_ref(OBJECT(cioc)); - - qio_net_listener_set_client_func(s->listener, NULL, s, NULL); - - s->ioc =3D QIO_CHANNEL(cioc); - qio_channel_set_name(s->ioc, "stream-server"); - s->nc.link_down =3D false; - - s->ioc_read_tag =3D qio_channel_add_watch(s->ioc, G_IO_IN, net_stream_= send, - s, NULL); + net_stream_data_listen(listener, cioc, data); =20 if (cioc->localAddr.ss_family =3D=3D AF_UNIX) { addr =3D qio_channel_socket_get_local_address(cioc, NULL); @@ -260,22 +127,22 @@ static void net_stream_listen(QIONetListener *listene= r, } g_assert(addr !=3D NULL); uri =3D socket_uri(addr); - qemu_set_info_str(&s->nc, "%s", uri); + qemu_set_info_str(&d->nc, "%s", uri); g_free(uri); - qapi_event_send_netdev_stream_connected(s->nc.name, addr); + qapi_event_send_netdev_stream_connected(d->nc.name, addr); qapi_free_SocketAddress(addr); } =20 static void net_stream_server_listening(QIOTask *task, gpointer opaque) { - NetStreamState *s =3D opaque; - QIOChannelSocket *listen_sioc =3D QIO_CHANNEL_SOCKET(s->listen_ioc); + NetStreamData *d =3D opaque; + QIOChannelSocket *listen_sioc =3D QIO_CHANNEL_SOCKET(d->listen_ioc); SocketAddress *addr; int ret; Error *err =3D NULL; =20 if (qio_task_propagate_error(task, &err)) { - qemu_set_info_str(&s->nc, "error: %s", error_get_pretty(err)); + qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err)); error_free(err); return; } @@ -284,20 +151,21 @@ static void net_stream_server_listening(QIOTask *task= , gpointer opaque) g_assert(addr !=3D NULL); ret =3D qemu_socket_try_set_nonblock(listen_sioc->fd); if (addr->type =3D=3D SOCKET_ADDRESS_TYPE_FD && ret < 0) { - qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)= ", + qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)= ", addr->u.fd.str, -ret); return; } g_assert(ret =3D=3D 0); qapi_free_SocketAddress(addr); =20 - s->nc.link_down =3D true; - s->listener =3D qio_net_listener_new(); + d->nc.link_down =3D true; + d->listener =3D qio_net_listener_new(); =20 - qemu_set_info_str(&s->nc, "listening"); - net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); - qio_net_listener_set_client_func(s->listener, net_stream_listen, s, NU= LL); - qio_net_listener_add(s->listener, listen_sioc); + qemu_set_info_str(&d->nc, "listening"); + net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false); + qio_net_listener_set_client_func(d->listener, d->listen, d, + NULL); + qio_net_listener_add(d->listener, listen_sioc); } =20 static int net_stream_server_init(NetClientState *peer, @@ -307,16 +175,18 @@ static int net_stream_server_init(NetClientState *pee= r, Error **errp) { NetClientState *nc; - NetStreamState *s; + NetStreamData *d; QIOChannelSocket *listen_sioc =3D qio_channel_socket_new(); =20 nc =3D qemu_new_net_client(&net_stream_info, peer, model, name); - s =3D DO_UPCAST(NetStreamState, nc, nc); - qemu_set_info_str(&s->nc, "initializing"); + d =3D DO_UPCAST(NetStreamData, nc, nc); + d->send =3D net_stream_send; + d->listen =3D net_stream_listen; + qemu_set_info_str(&d->nc, "initializing"); =20 - s->listen_ioc =3D QIO_CHANNEL(listen_sioc); + d->listen_ioc =3D QIO_CHANNEL(listen_sioc); qio_channel_socket_listen_async(listen_sioc, addr, 0, - net_stream_server_listening, s, + net_stream_server_listening, d, NULL, NULL); =20 return 0; @@ -325,49 +195,23 @@ static int net_stream_server_init(NetClientState *pee= r, static void net_stream_client_connected(QIOTask *task, gpointer opaque) { NetStreamState *s =3D opaque; - QIOChannelSocket *sioc =3D QIO_CHANNEL_SOCKET(s->ioc); + NetStreamData *d =3D &s->data; + QIOChannelSocket *sioc =3D QIO_CHANNEL_SOCKET(d->ioc); SocketAddress *addr; gchar *uri; - int ret; - Error *err =3D NULL; =20 - if (qio_task_propagate_error(task, &err)) { - qemu_set_info_str(&s->nc, "error: %s", error_get_pretty(err)); - error_free(err); - goto error; + if (net_stream_data_client_connected(task, d) =3D=3D -1) { + net_stream_arm_reconnect(s); + return; } =20 addr =3D qio_channel_socket_get_remote_address(sioc, NULL); g_assert(addr !=3D NULL); uri =3D socket_uri(addr); - qemu_set_info_str(&s->nc, "%s", uri); + qemu_set_info_str(&d->nc, "%s", uri); g_free(uri); - - ret =3D qemu_socket_try_set_nonblock(sioc->fd); - if (addr->type =3D=3D SOCKET_ADDRESS_TYPE_FD && ret < 0) { - qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)= ", - addr->u.fd.str, -ret); - qapi_free_SocketAddress(addr); - goto error; - } - g_assert(ret =3D=3D 0); - - net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); - - /* Disable Nagle algorithm on TCP sockets to reduce latency */ - qio_channel_set_delay(s->ioc, false); - - s->ioc_read_tag =3D qio_channel_add_watch(s->ioc, G_IO_IN, net_stream_= send, - s, NULL); - s->nc.link_down =3D false; - qapi_event_send_netdev_stream_connected(s->nc.name, addr); + qapi_event_send_netdev_stream_connected(d->nc.name, addr); qapi_free_SocketAddress(addr); - - return; -error: - object_unref(OBJECT(s->ioc)); - s->ioc =3D NULL; - net_stream_arm_reconnect(s); } =20 static gboolean net_stream_reconnect(gpointer data) @@ -378,7 +222,7 @@ static gboolean net_stream_reconnect(gpointer data) s->timer_tag =3D 0; =20 sioc =3D qio_channel_socket_new(); - s->ioc =3D QIO_CHANNEL(sioc); + s->data.ioc =3D QIO_CHANNEL(sioc); qio_channel_socket_connect_async(sioc, s->addr, net_stream_client_connected, s, NULL, NULL); @@ -388,7 +232,7 @@ static gboolean net_stream_reconnect(gpointer data) static void net_stream_arm_reconnect(NetStreamState *s) { if (s->reconnect_ms && s->timer_tag =3D=3D 0) { - qemu_set_info_str(&s->nc, "connecting"); + qemu_set_info_str(&s->data.nc, "connecting"); s->timer_tag =3D g_timeout_add(s->reconnect_ms, net_stream_reconne= ct, s); } } @@ -405,11 +249,13 @@ static int net_stream_client_init(NetClientState *pee= r, QIOChannelSocket *sioc =3D qio_channel_socket_new(); =20 nc =3D qemu_new_net_client(&net_stream_info, peer, model, name); - s =3D DO_UPCAST(NetStreamState, nc, nc); - qemu_set_info_str(&s->nc, "connecting"); + s =3D DO_UPCAST(NetStreamState, data.nc, nc); + qemu_set_info_str(&s->data.nc, "connecting"); =20 - s->ioc =3D QIO_CHANNEL(sioc); - s->nc.link_down =3D true; + s->data.ioc =3D QIO_CHANNEL(sioc); + s->data.nc.link_down =3D true; + s->data.send =3D net_stream_send; + s->data.listen =3D net_stream_listen; =20 s->reconnect_ms =3D reconnect_ms; if (reconnect_ms) { diff --git a/net/stream_data.c b/net/stream_data.c new file mode 100644 index 000000000000..5af27e0d1d6a --- /dev/null +++ b/net/stream_data.c @@ -0,0 +1,193 @@ +/* + * net stream generic functions + * + * Copyright Red Hat + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/iov.h" +#include "qapi/error.h" +#include "net/net.h" +#include "io/channel.h" +#include "io/net-listener.h" + +#include "stream_data.h" + +static gboolean net_stream_data_writable(QIOChannel *ioc, + GIOCondition condition, gpointer = data) +{ + NetStreamData *d =3D data; + + d->ioc_write_tag =3D 0; + + qemu_flush_queued_packets(&d->nc); + + return G_SOURCE_REMOVE; +} + +ssize_t net_stream_data_receive(NetStreamData *d, const uint8_t *buf, + size_t size) +{ + uint32_t len =3D htonl(size); + struct iovec iov[] =3D { + { + .iov_base =3D &len, + .iov_len =3D sizeof(len), + }, { + .iov_base =3D (void *)buf, + .iov_len =3D size, + }, + }; + struct iovec local_iov[2]; + unsigned int nlocal_iov; + size_t remaining; + ssize_t ret; + + remaining =3D iov_size(iov, 2) - d->send_index; + nlocal_iov =3D iov_copy(local_iov, 2, iov, 2, d->send_index, remaining= ); + ret =3D qio_channel_writev(d->ioc, local_iov, nlocal_iov, NULL); + if (ret =3D=3D QIO_CHANNEL_ERR_BLOCK) { + ret =3D 0; /* handled further down */ + } + if (ret =3D=3D -1) { + d->send_index =3D 0; + return -errno; + } + if (ret < (ssize_t)remaining) { + d->send_index +=3D ret; + d->ioc_write_tag =3D qio_channel_add_watch(d->ioc, G_IO_OUT, + net_stream_data_writable,= d, + NULL); + return 0; + } + d->send_index =3D 0; + return size; +} + +static void net_stream_data_send_completed(NetClientState *nc, ssize_t len) +{ + NetStreamData *d =3D DO_UPCAST(NetStreamData, nc, nc); + + if (!d->ioc_read_tag) { + d->ioc_read_tag =3D qio_channel_add_watch(d->ioc, G_IO_IN, d->send= , d, + NULL); + } +} + +void net_stream_data_rs_finalize(SocketReadState *rs) +{ + NetStreamData *d =3D container_of(rs, NetStreamData, rs); + + if (qemu_send_packet_async(&d->nc, rs->buf, + rs->packet_len, + net_stream_data_send_completed) =3D=3D 0) { + if (d->ioc_read_tag) { + g_source_remove(d->ioc_read_tag); + d->ioc_read_tag =3D 0; + } + } +} + +gboolean net_stream_data_send(QIOChannel *ioc, GIOCondition condition, + NetStreamData *d) +{ + int size; + int ret; + QEMU_UNINITIALIZED char buf1[NET_BUFSIZE]; + const char *buf; + + size =3D qio_channel_read(d->ioc, buf1, sizeof(buf1), NULL); + if (size < 0) { + if (errno !=3D EWOULDBLOCK) { + goto eoc; + } + } else if (size =3D=3D 0) { + /* end of connection */ + eoc: + d->ioc_read_tag =3D 0; + if (d->ioc_write_tag) { + g_source_remove(d->ioc_write_tag); + d->ioc_write_tag =3D 0; + } + if (d->listener) { + qemu_set_info_str(&d->nc, "listening"); + qio_net_listener_set_client_func(d->listener, + d->listen, d, NULL); + } + object_unref(OBJECT(d->ioc)); + d->ioc =3D NULL; + + net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false); + d->nc.link_down =3D true; + + return G_SOURCE_REMOVE; + } + buf =3D buf1; + + ret =3D net_fill_rstate(&d->rs, (const uint8_t *)buf, size); + + if (ret =3D=3D -1) { + goto eoc; + } + + return G_SOURCE_CONTINUE; +} + +void net_stream_data_listen(QIONetListener *listener, + QIOChannelSocket *cioc, + NetStreamData *d) +{ + object_ref(OBJECT(cioc)); + + qio_net_listener_set_client_func(d->listener, NULL, d, NULL); + + d->ioc =3D QIO_CHANNEL(cioc); + qio_channel_set_name(d->ioc, "stream-server"); + d->nc.link_down =3D false; + + d->ioc_read_tag =3D qio_channel_add_watch(d->ioc, G_IO_IN, d->send, d,= NULL); +} + +int net_stream_data_client_connected(QIOTask *task, NetStreamData *d) +{ + QIOChannelSocket *sioc =3D QIO_CHANNEL_SOCKET(d->ioc); + SocketAddress *addr; + int ret; + Error *err =3D NULL; + + if (qio_task_propagate_error(task, &err)) { + qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err)); + error_free(err); + goto error; + } + + addr =3D qio_channel_socket_get_remote_address(sioc, NULL); + g_assert(addr !=3D NULL); + + ret =3D qemu_socket_try_set_nonblock(sioc->fd); + if (addr->type =3D=3D SOCKET_ADDRESS_TYPE_FD && ret < 0) { + qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)= ", + addr->u.fd.str, -ret); + qapi_free_SocketAddress(addr); + goto error; + } + g_assert(ret =3D=3D 0); + qapi_free_SocketAddress(addr); + + net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false); + + /* Disable Nagle algorithm on TCP sockets to reduce latency */ + qio_channel_set_delay(d->ioc, false); + + d->ioc_read_tag =3D qio_channel_add_watch(d->ioc, G_IO_IN, d->send, d,= NULL); + d->nc.link_down =3D false; + + return 0; +error: + object_unref(OBJECT(d->ioc)); + d->ioc =3D NULL; + + return -1; +} diff --git a/net/stream_data.h b/net/stream_data.h new file mode 100644 index 000000000000..b868625665ae --- /dev/null +++ b/net/stream_data.h @@ -0,0 +1,31 @@ +/* + * net stream generic functions + * + * Copyright Red Hat + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +typedef struct NetStreamData { + NetClientState nc; + QIOChannel *ioc; + guint ioc_read_tag; + guint ioc_write_tag; + SocketReadState rs; + unsigned int send_index; /* number of bytes sent*/ + QIOChannelFunc send; + /* server data */ + QIOChannel *listen_ioc; + QIONetListener *listener; + QIONetListenerClientFunc listen; +} NetStreamData; + +ssize_t net_stream_data_receive(NetStreamData *d, const uint8_t *buf, + size_t size); +void net_stream_data_rs_finalize(SocketReadState *rs); +gboolean net_stream_data_send(QIOChannel *ioc, GIOCondition condition, + NetStreamData *d); +int net_stream_data_client_connected(QIOTask *task, NetStreamData *d); +void net_stream_data_listen(QIONetListener *listener, + QIOChannelSocket *cioc, + NetStreamData *d); --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876187; cv=none; d=zohomail.com; s=zohoarc; b=PNkqAXjJSPxBA9b1S1lEi/iNd6UelX8Qgm7GgeA+JcbPfdugukKGoUA2rdTUaAxDx50Jbc4sbyOT8Pcucj1L8zH+qTORk4a6rX1i9EWPlQuwGXKesLcNjtEZ1JtLZK2MFgniuMj46GLXfkoCkQhq3u9CsU46NYxpYw9BFseGmek= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876187; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XMSAIGjZQm7v/llfYTxAtUXEfhFeRyEzAV9SpCA0wyQ=; b=csF+a0FFBluI1LnReiB6i4AWfdQR7gxVvA45rPI/3HkZ1YNaOHNOAr2f2Zmjw6uoNu7CYiOvdVMVapsUT0ooJ5V1+YhpNCUAiEgOk/UljNjpMNZaaRpLHFhAuvlpsc33K7tvcc4Py4I3aiWY6ab9xeL+Cv4kuQLGXm1uDrtySg0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876187924839.1223885643873; Mon, 7 Jul 2025 01:16:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0k-0008UK-PH; Mon, 07 Jul 2025 04:15:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0d-0008RH-Ij for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0a-0007La-SS for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:31 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-37-uJ3lxr35MV-UtoZQS4oKsg-1; Mon, 07 Jul 2025 04:15:24 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 26AF2190FBCC; Mon, 7 Jul 2025 08:15:23 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 40D071803AFF; Mon, 7 Jul 2025 08:15:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876125; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XMSAIGjZQm7v/llfYTxAtUXEfhFeRyEzAV9SpCA0wyQ=; b=OXcey8QsVWnV/O/a1ozL1RDzUNawi0NCm0m6Ampp8WxSoZoENDZIXZyHLNC1j1/se0pO4L ZYIz7jYUEhEszhGMcPHlMT7K2Gqk8DI8uE3j8JBCtF1ja8a+P5J+f+jTFrbDmzoqlEpExO G3ecqibNqoFu/NHP0p2pcJyKUdJ9P7k= X-MC-Unique: uJ3lxr35MV-UtoZQS4oKsg-1 X-Mimecast-MFC-AGG-ID: uJ3lxr35MV-UtoZQS4oKsg_1751876123 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 02/11] net: Define net_client_set_link() Date: Mon, 7 Jul 2025 10:14:56 +0200 Message-ID: <20250707081505.127519-3-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876191035116600 Content-Type: text/plain; charset="utf-8" The code to set the link status is currently located in qmp_set_link(). This function identifies the device by name, searches for the corresponding NetClientState, and then updates the link status. In some parts of the code, such as vhost-user.c, the NetClientState are already available. Calling qmp_set_link() from these locations leads to a redundant search for the clients. This patch refactors the logic by introducing a new function, net_client_set_link(), which accepts a NetClientState array directly. qmp_set_link() is simplified to be a wrapper that performs the client search and then calls the new function. The vhost-user implementation is updated to use net_client_set_link() directly, thereby eliminating the unnecessary client lookup. Signed-off-by: Laurent Vivier --- include/net/net.h | 1 + net/net.c | 32 ++++++++++++++++++++------------ net/vhost-user.c | 4 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index cdd5b109b0d2..ac59b593ba48 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -298,6 +298,7 @@ void net_client_parse(QemuOptsList *opts_list, const ch= ar *optstr); void show_netdevs(void); void net_init_clients(void); void net_check_clients(void); +void net_client_set_link(NetClientState **ncs, int queues, bool up); void net_cleanup(void); void hmp_host_net_add(Monitor *mon, const QDict *qdict); void hmp_host_net_remove(Monitor *mon, const QDict *qdict); diff --git a/net/net.c b/net/net.c index 39d6f28158a3..cfa2d8e95827 100644 --- a/net/net.c +++ b/net/net.c @@ -1601,21 +1601,11 @@ void colo_notify_filters_event(int event, Error **e= rrp) } } =20 -void qmp_set_link(const char *name, bool up, Error **errp) +void net_client_set_link(NetClientState **ncs, int queues, bool up) { - NetClientState *ncs[MAX_QUEUE_NUM]; NetClientState *nc; - int queues, i; - - queues =3D qemu_find_net_clients_except(name, ncs, - NET_CLIENT_DRIVER__MAX, - MAX_QUEUE_NUM); + int i; =20 - if (queues =3D=3D 0) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", name); - return; - } nc =3D ncs[0]; =20 for (i =3D 0; i < queues; i++) { @@ -1646,6 +1636,24 @@ void qmp_set_link(const char *name, bool up, Error *= *errp) } } =20 +void qmp_set_link(const char *name, bool up, Error **errp) +{ + NetClientState *ncs[MAX_QUEUE_NUM]; + int queues; + + queues =3D qemu_find_net_clients_except(name, ncs, + NET_CLIENT_DRIVER__MAX, + MAX_QUEUE_NUM); + + if (queues =3D=3D 0) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", name); + return; + } + + net_client_set_link(ncs, queues, up); +} + static void net_vm_change_state_handler(void *opaque, bool running, RunState state) { diff --git a/net/vhost-user.c b/net/vhost-user.c index 0b235e50c650..10ac8dc0b3d7 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -264,7 +264,7 @@ static void chr_closed_bh(void *opaque) vhost_user_save_acked_features(ncs[i]); } =20 - qmp_set_link(name, false, &err); + net_client_set_link(ncs, queues, false); =20 qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, NULL, opaque, NULL, true); @@ -300,7 +300,7 @@ static void net_vhost_user_event(void *opaque, QEMUChrE= vent event) } s->watch =3D qemu_chr_fe_add_watch(&s->chr, G_IO_HUP, net_vhost_user_watch, s); - qmp_set_link(name, true, &err); + net_client_set_link(ncs, queues, true); s->started =3D true; qapi_event_send_netdev_vhost_user_connected(name, chr->label); break; --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876274; cv=none; d=zohomail.com; s=zohoarc; b=XJ6FUiKzngPT6L3bTPDyeoqWgfXMQ8YetjX8I8kdPE0UC12jtRF8xTg0gMInCeCuY1r/zPILpfAD7iySKsUP9IyM3c3FRTJ6ejwmOPfOGA8GCqwYcj6bYFExdTH462QqNsn5wHDehIy+k/UVeFnOLxanbn9uoC475maazB9lqm0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876274; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=I76yZiKaUMu4077l3joOwVu/AGYxDmVkJAii/GtwsNA=; b=eGmohKA+efMOIt+aoAQdMn1BhxLZC1UeCTn9FQkUyRo8hNPlgDSvuNPtqrmLc5tfrerClIbUpdR2oCWNiztSd1yeT33aZYDJD+ox7VGnyBjupQwvenM2gHJkqoSR7fJBej93vEWhMCBwCzmkCUyq61wvWF241w09q+arvV1sMjQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876274261130.59974432211197; Mon, 7 Jul 2025 01:17:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0l-0008Ut-S9; Mon, 07 Jul 2025 04:15:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0f-0008Rp-To for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0e-0007Np-AB for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:33 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-301-DUKsWn1UOm2S8Wh-TmNE-g-1; Mon, 07 Jul 2025 04:15:29 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4D2F0190FBC4; Mon, 7 Jul 2025 08:15:28 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A37F518046C3; Mon, 7 Jul 2025 08:15:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876131; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=I76yZiKaUMu4077l3joOwVu/AGYxDmVkJAii/GtwsNA=; b=MnXz91esoT/gOMDw8+zC4tJCEp4sbkI3jP4KzaNRhYRkdS46HwGsHXcI9+i1WtjIu2njt0 tpvcNNtIeK6+OoxCSsKr9i/MH6ATI0K1bgk5pk5o+P9gFBSc3hJFq103z0WY6kg+C8RJr+ 8TQoOgNLQExjqmABLKfkAxrfgsw9GZg= X-MC-Unique: DUKsWn1UOm2S8Wh-TmNE-g-1 X-Mimecast-MFC-AGG-ID: DUKsWn1UOm2S8Wh-TmNE-g_1751876128 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 03/11] vhost_net: Rename vhost_set_vring_enable() for clarity Date: Mon, 7 Jul 2025 10:14:57 +0200 Message-ID: <20250707081505.127519-4-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876275744116600 Content-Type: text/plain; charset="utf-8" This is a cosmetic change with no functional impact. The function vhost_set_vring_enable() is specific to vhost_net and is used outside of vhost_net.c (specifically, in hw/net/virtio-net.c). To prevent confusion with other similarly named vhost functions, such as the one found in cryptodev-vhost.c, it has been renamed to vhost_net_set_vring_enable(). This clarifies that the function belongs to the vhost_net module. Signed-off-by: Laurent Vivier --- hw/net/vhost_net-stub.c | 2 +- hw/net/vhost_net.c | 4 ++-- hw/net/virtio-net.c | 4 ++-- include/net/vhost_net.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c index 72df6d757e4d..7bed0bf92b8e 100644 --- a/hw/net/vhost_net-stub.c +++ b/hw/net/vhost_net-stub.c @@ -101,7 +101,7 @@ VHostNetState *get_vhost_net(NetClientState *nc) return 0; } =20 -int vhost_set_vring_enable(NetClientState *nc, int enable) +int vhost_net_set_vring_enable(NetClientState *nc, int enable) { return 0; } diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 891f235a0a6e..cb8705639787 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -551,7 +551,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *= ncs, =20 if (peer->vring_enable) { /* restore vring enable state */ - r =3D vhost_set_vring_enable(peer, peer->vring_enable); + r =3D vhost_net_set_vring_enable(peer, peer->vring_enable); =20 if (r < 0) { goto err_guest_notifiers; @@ -686,7 +686,7 @@ VHostNetState *get_vhost_net(NetClientState *nc) return vhost_net; } =20 -int vhost_set_vring_enable(NetClientState *nc, int enable) +int vhost_net_set_vring_enable(NetClientState *nc, int enable) { VHostNetState *net =3D get_vhost_net(nc); const VhostOps *vhost_ops =3D net->dev.vhost_ops; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index eb93607b8c76..b52660436273 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -697,7 +697,7 @@ static int peer_attach(VirtIONet *n, int index) } =20 if (nc->peer->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { - vhost_set_vring_enable(nc->peer, 1); + vhost_net_set_vring_enable(nc->peer, 1); } =20 if (nc->peer->info->type !=3D NET_CLIENT_DRIVER_TAP) { @@ -720,7 +720,7 @@ static int peer_detach(VirtIONet *n, int index) } =20 if (nc->peer->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { - vhost_set_vring_enable(nc->peer, 0); + vhost_net_set_vring_enable(nc->peer, 0); } =20 if (nc->peer->info->type !=3D NET_CLIENT_DRIVER_TAP) { diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index c6a5361a2ae4..0f40049f3419 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -41,7 +41,7 @@ void vhost_net_config_mask(VHostNetState *net, VirtIODevi= ce *dev, bool mask); int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); VHostNetState *get_vhost_net(NetClientState *nc); =20 -int vhost_set_vring_enable(NetClientState * nc, int enable); +int vhost_net_set_vring_enable(NetClientState *nc, int enable); =20 uint64_t vhost_net_get_acked_features(VHostNetState *net); =20 --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876275; cv=none; d=zohomail.com; s=zohoarc; b=bztSJKf676WLHw+CxQ6jU0a6n/45Lczd6nQKpSKaiiK30fS6uAMi6sPb9x9ytM6LibmqoLzYM5I8uz+boKkVyflHc2WWpfZUfyWqvHobJ2Ao2atxsk/sZJovDNgm8jrU7xzz4EOGTrf5BzXgkHRLDqj4xIlERn+mMRsnRBd5YM0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876275; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=RRTDdN35n6z4fleUcFXK6SKMfJFzYOV4xsz/UGqW6Qw=; b=fwOrmQYd34p04xKBGJ5gC9W/n3ClMGCnQqu7Uc1M0mU8uMEN/zS8XX3Ua8g+uV2xzXlCF3FlzUxzwrEJGR6nZL5b6nq/x4lT55ZxGYwYh8NLNMz5O7OypZCJtBAE9fEQ0pHWDL9c92keDcn39MY2WUfT8C9xTP5guPZkdlZ1I+o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876275066964.9907517235722; Mon, 7 Jul 2025 01:17:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0n-0008WA-SV; Mon, 07 Jul 2025 04:15:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0m-0008VK-3S for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0k-0007Pj-6y for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:39 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-497-Tjv-VTMTMJasPitqtn2nyw-1; Mon, 07 Jul 2025 04:15:34 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 422DD1978C9A; Mon, 7 Jul 2025 08:15:33 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EFCEE18046C5; Mon, 7 Jul 2025 08:15:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876137; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RRTDdN35n6z4fleUcFXK6SKMfJFzYOV4xsz/UGqW6Qw=; b=ZWz5UjZRIKTxfRrWvVv3APgWPniwqeVl70zl7xa/FPo/ULN0hpHoZAqhP9jh0ETcUUKBXO CgvFmkbNMr9BZwtyOdE6NvmpFOJj3uuGUwnRrQgtJ84C9WVOYx+I0FolHvG34JM8IrDJPy CJHo/yY1t8jYRxlqUXcB9K2bC+gARCI= X-MC-Unique: Tjv-VTMTMJasPitqtn2nyw-1 X-Mimecast-MFC-AGG-ID: Tjv-VTMTMJasPitqtn2nyw_1751876133 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 04/11] net: Add get_vhost_net callback to NetClientInfo Date: Mon, 7 Jul 2025 10:14:58 +0200 Message-ID: <20250707081505.127519-5-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876278115116600 Content-Type: text/plain; charset="utf-8" The get_vhost_net() function previously contained a large switch statement to find the VHostNetState pointer based on the net client's type. This created a tight coupling, requiring the generic vhost layer to be aware of every specific backend that supported vhost, such as tap, vhost-user, and vhost-vdpa. This approach is not scalable and requires modifying a central function for any new backend. It also forced each backend to expose its internal getter function in a public header file. This patch refactors the logic by introducing a new get_vhost_net function pointer to the NetClientInfo struct. The central get_vhost_net() function is now a simple, generic dispatcher that invokes the callback provided by the net client. Each backend now implements its own private getter and registers it in its NetClientInfo. Signed-off-by: Laurent Vivier --- hw/net/vhost_net.c | 31 ++++--------------------------- include/net/net.h | 2 ++ include/net/tap.h | 3 --- include/net/vhost-user.h | 1 - include/net/vhost-vdpa.h | 2 -- net/tap-win32.c | 5 ----- net/tap.c | 20 +++++++++++++------- net/vhost-user.c | 3 ++- net/vhost-vdpa.c | 4 +++- 9 files changed, 24 insertions(+), 47 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index cb8705639787..db8b97b753d8 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -649,41 +649,18 @@ void vhost_net_config_mask(VHostNetState *net, VirtIO= Device *dev, bool mask) { vhost_config_mask(&net->dev, dev, mask); } + VHostNetState *get_vhost_net(NetClientState *nc) { - VHostNetState *vhost_net =3D 0; - if (!nc) { return 0; } =20 - switch (nc->info->type) { - case NET_CLIENT_DRIVER_TAP: - vhost_net =3D tap_get_vhost_net(nc); - /* - * tap_get_vhost_net() can return NULL if a tap net-device backend= is - * created with 'vhost=3Doff' option, 'vhostforce=3Doff' or no vho= st or - * vhostforce or vhostfd options at all. Please see net_init_tap_o= ne(). - * Hence, we omit the assertion here. - */ - break; -#ifdef CONFIG_VHOST_NET_USER - case NET_CLIENT_DRIVER_VHOST_USER: - vhost_net =3D vhost_user_get_vhost_net(nc); - assert(vhost_net); - break; -#endif -#ifdef CONFIG_VHOST_NET_VDPA - case NET_CLIENT_DRIVER_VHOST_VDPA: - vhost_net =3D vhost_vdpa_get_vhost_net(nc); - assert(vhost_net); - break; -#endif - default: - break; + if (nc->info->get_vhost_net) { + return nc->info->get_vhost_net(nc); } =20 - return vhost_net; + return NULL; } =20 int vhost_net_set_vring_enable(NetClientState *nc, int enable) diff --git a/include/net/net.h b/include/net/net.h index ac59b593ba48..e67b37562638 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -67,6 +67,7 @@ typedef void (SocketReadStateFinalize)(SocketReadState *r= s); typedef void (NetAnnounce)(NetClientState *); typedef bool (SetSteeringEBPF)(NetClientState *, int); typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error **); +typedef struct vhost_net *(GetVHostNet)(NetClientState *nc); =20 typedef struct NetClientInfo { NetClientDriver type; @@ -92,6 +93,7 @@ typedef struct NetClientInfo { NetAnnounce *announce; SetSteeringEBPF *set_steering_ebpf; NetCheckPeerType *check_peer_type; + GetVHostNet *get_vhost_net; } NetClientInfo; =20 struct NetClientState { diff --git a/include/net/tap.h b/include/net/tap.h index 5d585515f9e3..6f34f13eae44 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -33,7 +33,4 @@ int tap_disable(NetClientState *nc); =20 int tap_get_fd(NetClientState *nc); =20 -struct vhost_net; -struct vhost_net *tap_get_vhost_net(NetClientState *nc); - #endif /* QEMU_NET_TAP_H */ diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h index 35bf61970985..0b233a267345 100644 --- a/include/net/vhost-user.h +++ b/include/net/vhost-user.h @@ -12,7 +12,6 @@ #define VHOST_USER_H =20 struct vhost_net; -struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc); uint64_t vhost_user_get_acked_features(NetClientState *nc); void vhost_user_save_acked_features(NetClientState *nc); =20 diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h index b81f9a6f2a0e..916ead3793d9 100644 --- a/include/net/vhost-vdpa.h +++ b/include/net/vhost-vdpa.h @@ -14,8 +14,6 @@ =20 #define TYPE_VHOST_VDPA "vhost-vdpa" =20 -struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc); - extern const int vdpa_feature_bits[]; =20 #endif /* VHOST_VDPA_H */ diff --git a/net/tap-win32.c b/net/tap-win32.c index 671dee970f7a..38baf90e0b3f 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -704,11 +704,6 @@ static void tap_win32_send(void *opaque) } } =20 -struct vhost_net *tap_get_vhost_net(NetClientState *nc) -{ - return NULL; -} - static NetClientInfo net_tap_win32_info =3D { .type =3D NET_CLIENT_DRIVER_TAP, .size =3D sizeof(TAPState), diff --git a/net/tap.c b/net/tap.c index ae1c7e398321..4beba6d7a784 100644 --- a/net/tap.c +++ b/net/tap.c @@ -329,6 +329,18 @@ int tap_get_fd(NetClientState *nc) return s->fd; } =20 +/* + * tap_get_vhost_net() can return NULL if a tap net-device backend is + * created with 'vhost=3Doff' option, 'vhostforce=3Doff' or no vhost or + * vhostforce or vhostfd options at all. Please see net_init_tap_one(). + */ +static VHostNetState *tap_get_vhost_net(NetClientState *nc) +{ + TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); + return s->vhost_net; +} + /* fd support */ =20 static NetClientInfo net_tap_info =3D { @@ -347,6 +359,7 @@ static NetClientInfo net_tap_info =3D { .set_vnet_le =3D tap_set_vnet_le, .set_vnet_be =3D tap_set_vnet_be, .set_steering_ebpf =3D tap_set_steering_ebpf, + .get_vhost_net =3D tap_get_vhost_net, }; =20 static TAPState *net_tap_fd_init(NetClientState *peer, @@ -980,13 +993,6 @@ free_fail: return 0; } =20 -VHostNetState *tap_get_vhost_net(NetClientState *nc) -{ - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); - assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); - return s->vhost_net; -} - int tap_enable(NetClientState *nc) { TAPState *s =3D DO_UPCAST(TAPState, nc, nc); diff --git a/net/vhost-user.c b/net/vhost-user.c index 10ac8dc0b3d7..b7bf0d2042e8 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -32,7 +32,7 @@ typedef struct NetVhostUserState { bool started; } NetVhostUserState; =20 -VHostNetState *vhost_user_get_vhost_net(NetClientState *nc) +static struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc) { NetVhostUserState *s =3D DO_UPCAST(NetVhostUserState, nc, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER); @@ -231,6 +231,7 @@ static NetClientInfo net_vhost_user_info =3D { .set_vnet_be =3D vhost_user_set_vnet_endianness, .set_vnet_le =3D vhost_user_set_vnet_endianness, .check_peer_type =3D vhost_user_check_peer_type, + .get_vhost_net =3D vhost_user_get_vhost_net, }; =20 static gboolean net_vhost_user_watch(void *do_not_use, GIOCondition cond, diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 58d738945dbc..0b86c917ed68 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -132,7 +132,7 @@ static const uint64_t vdpa_svq_device_features =3D =20 #define VHOST_VDPA_NET_CVQ_ASID 1 =20 -VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) +static struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc) { VhostVDPAState *s =3D DO_UPCAST(VhostVDPAState, nc, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_VDPA); @@ -432,6 +432,7 @@ static NetClientInfo net_vhost_vdpa_info =3D { .set_vnet_le =3D vhost_vdpa_set_vnet_le, .check_peer_type =3D vhost_vdpa_check_peer_type, .set_steering_ebpf =3D vhost_vdpa_set_steering_ebpf, + .get_vhost_net =3D vhost_vdpa_get_vhost_net, }; =20 static int64_t vhost_vdpa_get_vring_group(int device_fd, unsigned vq_index, @@ -1287,6 +1288,7 @@ static NetClientInfo net_vhost_vdpa_cvq_info =3D { .has_ufo =3D vhost_vdpa_has_ufo, .check_peer_type =3D vhost_vdpa_check_peer_type, .set_steering_ebpf =3D vhost_vdpa_set_steering_ebpf, + .get_vhost_net =3D vhost_vdpa_get_vhost_net, }; =20 /* --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876256; cv=none; d=zohomail.com; s=zohoarc; b=aDHOJ+KFCsDl+Ev4PJ/pJQBxgM/fUW+VI0+9EXxlECODmRTqnq8UE2KsCSjiCEVp5SA9vrUvC/WAl1E1WEYp231OnTlYK3VzRpMuyLWiZYsoBldRHI+dDc4vmbxg4Dtyr8TSUJUaPJmhbISCFgO0GxUJxu7X+CA5NAHW1h8lSgw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876256; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tfZjc6j5sXAM2bS0yOshLl4QKC/OUj5fmMiiuI37S1o=; b=O7Yo1ZNausCGdgQbbFl6Epmb6Gww5S85IW2U1nbXFuXwz3TQ4Ml23bdjsywIJGJj5bDK8L/kFQV0NirVddfd5eyRwJGkZhKLRQiS/mKObiYB7jWuL3NEvAq3JNoeuJeVLG1vT6KxhI5VCO2NxuQFrMt9VBhjNEq7bpA01gsKfCk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876256534747.4858527832812; Mon, 7 Jul 2025 01:17:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0u-00008A-ID; Mon, 07 Jul 2025 04:15:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0r-000060-Qp for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:46 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0p-0007Qy-Jh for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:45 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-114-Ntm4E7HMN8CTbnFNkBef6A-1; Mon, 07 Jul 2025 04:15:39 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 18CC0180028F; Mon, 7 Jul 2025 08:15:38 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BF6121803AF2; Mon, 7 Jul 2025 08:15:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876142; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tfZjc6j5sXAM2bS0yOshLl4QKC/OUj5fmMiiuI37S1o=; b=NqMGOAvPt5kCtagY2ijwJoWCY6H+bvbVi62lcew7wHJf0jeEta9BAZhRnEl4op5zXaiTE1 30spC86NI/A3RuT1BXf89/8ggQ5EUa4Bo0r//SMZdpNtqIJMAH8d7GZZi7dwdSHVDv6uAr VIWw+oa1V53gDN6QBD7J6xo/JosyWzo= X-MC-Unique: Ntm4E7HMN8CTbnFNkBef6A-1 X-Mimecast-MFC-AGG-ID: Ntm4E7HMN8CTbnFNkBef6A_1751876138 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 05/11] net: Consolidate vhost feature bits into vhost_net structure Date: Mon, 7 Jul 2025 10:14:59 +0200 Message-ID: <20250707081505.127519-6-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876257538116600 Content-Type: text/plain; charset="utf-8" Previously, the vhost_net_get_feature_bits() function in hw/net/vhost_net.c used a large switch statement to determine the appropriate feature bits based on the NetClientDriver type. This created unnecessary coupling between the generic vhost layer and specific network backends (like TAP, vhost-user, and vhost-vdpa). This patch moves the definition of vhost feature bits directly into the vhost_net structure for each relevant network client. Signed-off-by: Laurent Vivier --- hw/net/vhost_net.c | 90 ++------------------------------------- include/hw/virtio/vhost.h | 1 + include/net/vhost-vdpa.h | 2 - include/net/vhost_net.h | 1 + net/tap.c | 19 +++++++++ net/vhost-user.c | 43 +++++++++++++++++++ net/vhost-vdpa.c | 3 +- 7 files changed, 69 insertions(+), 90 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index db8b97b753d8..787c769ccc37 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -36,94 +36,9 @@ #include "hw/virtio/virtio-bus.h" #include "linux-headers/linux/vhost.h" =20 - -/* Features supported by host kernel. */ -static const int kernel_feature_bits[] =3D { - VIRTIO_F_NOTIFY_ON_EMPTY, - VIRTIO_RING_F_INDIRECT_DESC, - VIRTIO_RING_F_EVENT_IDX, - VIRTIO_NET_F_MRG_RXBUF, - VIRTIO_F_VERSION_1, - VIRTIO_NET_F_MTU, - VIRTIO_F_IOMMU_PLATFORM, - VIRTIO_F_RING_PACKED, - VIRTIO_F_RING_RESET, - VIRTIO_F_IN_ORDER, - VIRTIO_F_NOTIFICATION_DATA, - VIRTIO_NET_F_RSC_EXT, - VIRTIO_NET_F_HASH_REPORT, - VHOST_INVALID_FEATURE_BIT -}; - -/* Features supported by others. */ -static const int user_feature_bits[] =3D { - VIRTIO_F_NOTIFY_ON_EMPTY, - VIRTIO_F_NOTIFICATION_DATA, - VIRTIO_RING_F_INDIRECT_DESC, - VIRTIO_RING_F_EVENT_IDX, - - VIRTIO_F_ANY_LAYOUT, - VIRTIO_F_VERSION_1, - VIRTIO_NET_F_CSUM, - VIRTIO_NET_F_GUEST_CSUM, - VIRTIO_NET_F_GSO, - VIRTIO_NET_F_GUEST_TSO4, - VIRTIO_NET_F_GUEST_TSO6, - VIRTIO_NET_F_GUEST_ECN, - VIRTIO_NET_F_GUEST_UFO, - VIRTIO_NET_F_HOST_TSO4, - VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, - VIRTIO_NET_F_HOST_UFO, - VIRTIO_NET_F_MRG_RXBUF, - VIRTIO_NET_F_MTU, - VIRTIO_F_IOMMU_PLATFORM, - VIRTIO_F_RING_PACKED, - VIRTIO_F_RING_RESET, - VIRTIO_F_IN_ORDER, - VIRTIO_NET_F_RSS, - VIRTIO_NET_F_RSC_EXT, - VIRTIO_NET_F_HASH_REPORT, - VIRTIO_NET_F_GUEST_USO4, - VIRTIO_NET_F_GUEST_USO6, - VIRTIO_NET_F_HOST_USO, - - /* This bit implies RARP isn't sent by QEMU out of band */ - VIRTIO_NET_F_GUEST_ANNOUNCE, - - VIRTIO_NET_F_MQ, - - VHOST_INVALID_FEATURE_BIT -}; - -static const int *vhost_net_get_feature_bits(struct vhost_net *net) -{ - const int *feature_bits =3D 0; - - switch (net->nc->info->type) { - case NET_CLIENT_DRIVER_TAP: - feature_bits =3D kernel_feature_bits; - break; - case NET_CLIENT_DRIVER_VHOST_USER: - feature_bits =3D user_feature_bits; - break; -#ifdef CONFIG_VHOST_NET_VDPA - case NET_CLIENT_DRIVER_VHOST_VDPA: - feature_bits =3D vdpa_feature_bits; - break; -#endif - default: - error_report("Feature bits not defined for this type: %d", - net->nc->info->type); - break; - } - - return feature_bits; -} - uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features) { - return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), + return vhost_get_features(&net->dev, net->feature_bits, features); } int vhost_net_get_config(struct vhost_net *net, uint8_t *config, @@ -140,7 +55,7 @@ int vhost_net_set_config(struct vhost_net *net, const ui= nt8_t *data, void vhost_net_ack_features(struct vhost_net *net, uint64_t features) { net->dev.acked_features =3D net->dev.backend_features; - vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), feature= s); + vhost_ack_features(&net->dev, net->feature_bits, features); } =20 uint64_t vhost_net_get_max_queues(VHostNetState *net) @@ -329,6 +244,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) } net->nc =3D options->net_backend; net->dev.nvqs =3D options->nvqs; + net->feature_bits =3D options->feature_bits; =20 net->dev.max_queues =3D 1; net->dev.vqs =3D net->vqs; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 38800a7156b0..6a75fdc0213c 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -143,6 +143,7 @@ struct vhost_net { struct vhost_dev dev; struct vhost_virtqueue vqs[2]; int backend; + const int *feature_bits; NetClientState *nc; }; =20 diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h index 916ead3793d9..f8d7d6c9045b 100644 --- a/include/net/vhost-vdpa.h +++ b/include/net/vhost-vdpa.h @@ -14,6 +14,4 @@ =20 #define TYPE_VHOST_VDPA "vhost-vdpa" =20 -extern const int vdpa_feature_bits[]; - #endif /* VHOST_VDPA_H */ diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 0f40049f3419..fbed37385a3c 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -12,6 +12,7 @@ typedef struct VhostNetOptions { NetClientState *net_backend; uint32_t busyloop_timeout; unsigned int nvqs; + const int *feature_bits; void *opaque; } VhostNetOptions; =20 diff --git a/net/tap.c b/net/tap.c index 4beba6d7a784..a33eb2321242 100644 --- a/net/tap.c +++ b/net/tap.c @@ -42,11 +42,29 @@ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qemu/sockets.h" +#include "hw/virtio/vhost.h" =20 #include "net/tap.h" =20 #include "net/vhost_net.h" =20 +static const int kernel_feature_bits[] =3D { + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_F_VERSION_1, + VIRTIO_NET_F_MTU, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_RING_PACKED, + VIRTIO_F_RING_RESET, + VIRTIO_F_IN_ORDER, + VIRTIO_F_NOTIFICATION_DATA, + VIRTIO_NET_F_RSC_EXT, + VIRTIO_NET_F_HASH_REPORT, + VHOST_INVALID_FEATURE_BIT +}; + typedef struct TAPState { NetClientState nc; int fd; @@ -725,6 +743,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, } options.opaque =3D (void *)(uintptr_t)vhostfd; options.nvqs =3D 2; + options.feature_bits =3D kernel_feature_bits; =20 s->vhost_net =3D vhost_net_init(&options); if (!s->vhost_net) { diff --git a/net/vhost-user.c b/net/vhost-user.c index b7bf0d2042e8..bc8e82a09263 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -12,7 +12,9 @@ #include "clients.h" #include "net/vhost_net.h" #include "net/vhost-user.h" +#include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user.h" +#include "standard-headers/linux/virtio_net.h" #include "chardev/char-fe.h" #include "qapi/error.h" #include "qapi/qapi-commands-net.h" @@ -22,6 +24,46 @@ #include "qemu/option.h" #include "trace.h" =20 +static const int user_feature_bits[] =3D { + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_NOTIFICATION_DATA, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + + VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_VERSION_1, + VIRTIO_NET_F_CSUM, + VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GSO, + VIRTIO_NET_F_GUEST_TSO4, + VIRTIO_NET_F_GUEST_TSO6, + VIRTIO_NET_F_GUEST_ECN, + VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_HOST_TSO4, + VIRTIO_NET_F_HOST_TSO6, + VIRTIO_NET_F_HOST_ECN, + VIRTIO_NET_F_HOST_UFO, + VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_NET_F_MTU, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_RING_PACKED, + VIRTIO_F_RING_RESET, + VIRTIO_F_IN_ORDER, + VIRTIO_NET_F_RSS, + VIRTIO_NET_F_RSC_EXT, + VIRTIO_NET_F_HASH_REPORT, + VIRTIO_NET_F_GUEST_USO4, + VIRTIO_NET_F_GUEST_USO6, + VIRTIO_NET_F_HOST_USO, + + /* This bit implies RARP isn't sent by QEMU out of band */ + VIRTIO_NET_F_GUEST_ANNOUNCE, + + VIRTIO_NET_F_MQ, + + VHOST_INVALID_FEATURE_BIT +}; + typedef struct NetVhostUserState { NetClientState nc; CharBackend chr; /* only queue index 0 */ @@ -96,6 +138,7 @@ static int vhost_user_start(int queues, NetClientState *= ncs[], options.opaque =3D be; options.busyloop_timeout =3D 0; options.nvqs =3D 2; + options.feature_bits =3D user_feature_bits; net =3D vhost_net_init(&options); if (!net) { error_report("failed to init vhost_net for queue %d", i); diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 0b86c917ed68..cbbea0eb7198 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -55,7 +55,7 @@ typedef struct VhostVDPAState { * with the exception of VHOST_INVALID_FEATURE_BIT, * which should always be the last entry. */ -const int vdpa_feature_bits[] =3D { +static const int vdpa_feature_bits[] =3D { VIRTIO_F_ANY_LAYOUT, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_NOTIFY_ON_EMPTY, @@ -201,6 +201,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be, options.opaque =3D be; options.busyloop_timeout =3D 0; options.nvqs =3D nvqs; + options.feature_bits =3D vdpa_feature_bits; =20 net =3D vhost_net_init(&options); if (!net) { --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876271; cv=none; d=zohomail.com; s=zohoarc; b=arVrqJMcEf07c1agHuRb9JTGgF0oQXnUd8a8QmeYGaVcbCUm7euG9RifjrLJkD+f16Nlwrk7TXTZTiFlQHsoscmVDfol1gtJja32tYjH9I+IUSPLWfQhDjUdaD0gmNgPtRhMHq9LA0oyBFuZIup04rN/sS4mMqxsDXXD0DKegC0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876271; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=QAO7Ut8y2fzNcNSTmMKmzgfJ9mZ8UAi2ecrs8pm9WC4=; b=Ayba/PjnuL1a15FQROlhEFK7FvPlSJ397LQdv8VubyPlAPEa4A65TwCoMRTEf+ma2crU/btO34/sP8swLftm7pR+geh4F2/fqDcF5AIL2vaOmx2rXlY24Kn05beUTEFAAADQx5nH4AuXRVFc3KGwPOx6puBfMRLtAzJ+rJgt52o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876271661303.04397224560614; Mon, 7 Jul 2025 01:17:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh0x-00009e-Ms; Mon, 07 Jul 2025 04:15:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0v-00008b-R5 for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh0u-0007Ru-31 for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:15:49 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-537-9ND-dneIMzeImPJ2l_g-xQ-1; Mon, 07 Jul 2025 04:15:43 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 905FA19560A1; Mon, 7 Jul 2025 08:15:42 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 96354180045B; Mon, 7 Jul 2025 08:15:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876147; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QAO7Ut8y2fzNcNSTmMKmzgfJ9mZ8UAi2ecrs8pm9WC4=; b=N/CzspF2UqtHjn4F3vh/kKapFIT8MMr4mAUo0K7HIV+9/CYFUos00Kug/jvgAH27A3prqw c3GKPoFvDU+I5gS3zlKpD5n5dA1hi1ESyyPRwMIy7srYFJW/qntc9FVJBNv78FavpZ7q+4 prgsVV2hXo0r2xJNfo+L3mbzEmsQbwc= X-MC-Unique: 9ND-dneIMzeImPJ2l_g-xQ-1 X-Mimecast-MFC-AGG-ID: 9ND-dneIMzeImPJ2l_g-xQ_1751876142 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 06/11] net: Add get_acked_features callback to VhostNetOptions Date: Mon, 7 Jul 2025 10:15:00 +0200 Message-ID: <20250707081505.127519-7-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876273714116600 Content-Type: text/plain; charset="utf-8" This patch continues the effort to decouple the generic vhost layer from specific network backend implementations. Previously, the vhost_net initialization code contained a hardcoded check for the vhost-user client type to retrieve its acked features by calling vhost_user_get_acked_features(). This exposed an internal vhost-user function in a public header and coupled the two modules. The vhost-user backend is updated to provide a callback, and its getter function is now static. The call site in vhost_net.c is simplified to use the new generic helper, removing the type check and the direct dependency. Signed-off-by: Laurent Vivier --- hw/net/vhost_net.c | 6 ++---- include/net/vhost-user.h | 2 -- include/net/vhost_net.h | 3 +++ net/tap.c | 1 + net/vhost-user.c | 4 +++- net/vhost-vdpa.c | 1 + 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 787c769ccc37..fb169af0e81b 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -288,9 +288,8 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) } =20 /* Set sane init value. Override when guest acks. */ -#ifdef CONFIG_VHOST_NET_USER - if (net->nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { - features =3D vhost_user_get_acked_features(net->nc); + if (options->get_acked_features) { + features =3D options->get_acked_features(net->nc); if (~net->dev.features & features) { fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64 " for backend\n", @@ -298,7 +297,6 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) goto fail; } } -#endif =20 vhost_net_ack_features(net, features); =20 diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h index 0b233a267345..a4d0ce4b8dd1 100644 --- a/include/net/vhost-user.h +++ b/include/net/vhost-user.h @@ -11,8 +11,6 @@ #ifndef VHOST_USER_H #define VHOST_USER_H =20 -struct vhost_net; -uint64_t vhost_user_get_acked_features(NetClientState *nc); void vhost_user_save_acked_features(NetClientState *nc); =20 #endif /* VHOST_USER_H */ diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index fbed37385a3c..a8d281c8f7c2 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -7,12 +7,15 @@ struct vhost_net; typedef struct vhost_net VHostNetState; =20 +typedef uint64_t (GetAckedFeatures)(NetClientState *nc); + typedef struct VhostNetOptions { VhostBackendType backend_type; NetClientState *net_backend; uint32_t busyloop_timeout; unsigned int nvqs; const int *feature_bits; + GetAckedFeatures *get_acked_features; void *opaque; } VhostNetOptions; =20 diff --git a/net/tap.c b/net/tap.c index a33eb2321242..acd77f816fec 100644 --- a/net/tap.c +++ b/net/tap.c @@ -744,6 +744,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, options.opaque =3D (void *)(uintptr_t)vhostfd; options.nvqs =3D 2; options.feature_bits =3D kernel_feature_bits; + options.get_acked_features =3D NULL; =20 s->vhost_net =3D vhost_net_init(&options); if (!s->vhost_net) { diff --git a/net/vhost-user.c b/net/vhost-user.c index bc8e82a09263..93b413b49f34 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -81,7 +81,7 @@ static struct vhost_net *vhost_user_get_vhost_net(NetClie= ntState *nc) return s->vhost_net; } =20 -uint64_t vhost_user_get_acked_features(NetClientState *nc) +static uint64_t vhost_user_get_acked_features(NetClientState *nc) { NetVhostUserState *s =3D DO_UPCAST(NetVhostUserState, nc, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER); @@ -139,6 +139,8 @@ static int vhost_user_start(int queues, NetClientState = *ncs[], options.busyloop_timeout =3D 0; options.nvqs =3D 2; options.feature_bits =3D user_feature_bits; + options.get_acked_features =3D vhost_user_get_acked_features; + net =3D vhost_net_init(&options); if (!net) { error_report("failed to init vhost_net for queue %d", i); diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index cbbea0eb7198..a3980d1fb5ed 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -202,6 +202,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be, options.busyloop_timeout =3D 0; options.nvqs =3D nvqs; options.feature_bits =3D vdpa_feature_bits; + options.get_acked_features =3D NULL; =20 net =3D vhost_net_init(&options); if (!net) { --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876980; cv=none; d=zohomail.com; s=zohoarc; b=me7hUV98KBhaR4s6iqciQLnSUH8/s7Z+QFa6TGmBbNkCwq6cold5uLGjOtiA1qEjqwHB3P0NkRDTOqSbezcNoI8E5LXlFH4J5pn/ML1sALu4QWEIEvAZGO/tbgFuP2V3Eyjusv79TdAdXlIEvUmWBgPNykLTTvz5p/asmRqzNMA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876980; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TEHH5PwPPhiBn0zoqbiFaFLfogPQjxS5hORUtCtU9hk=; b=MLieXD/VZaNafbNMd6+g+8XFXC/8T3xA2ywpUE1RlIduLrh5E0/5i9lUOpnRgBahTI5nPvHl1INTzFska6vvwqoM734/85qJocrLdNZidGYsTcGZX9USij605PGgyWNteMEGJsecZ1naM2gQ2byFeer2Vpe6fIbLhb++5Zx1qXw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876980842269.5084651915595; Mon, 7 Jul 2025 01:29:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYhDe-0004QY-Hg; Mon, 07 Jul 2025 04:28:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYhDW-0004Ot-5c for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:28:52 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYhDS-0001hU-RN for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:28:49 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-245-Du5oivRuMuCvWyDNopPPFg-1; Mon, 07 Jul 2025 04:15:49 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BDF501809C9D; Mon, 7 Jul 2025 08:15:47 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 18CBF180045B; Mon, 7 Jul 2025 08:15:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876923; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TEHH5PwPPhiBn0zoqbiFaFLfogPQjxS5hORUtCtU9hk=; b=e9APFLEdRAFrPtmznyNzBpv4XylP9kl/6OTy0MJCkp1W0hCSZtEiIeFajzF64Om88ZVlsY UpMp7TM5vaZL2S7JdwpNh6PIEKBMDyuFgr6qscShTT1d/aY9nPFZgf8+6fN53cj0CXC/G6 BNPsSlc4Q1jvNViX53OYxZi0g+co5aw= X-MC-Unique: Du5oivRuMuCvWyDNopPPFg-1 X-Mimecast-MFC-AGG-ID: Du5oivRuMuCvWyDNopPPFg_1751876148 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 07/11] net: Add save_acked_features callback to vhost_net Date: Mon, 7 Jul 2025 10:15:01 +0200 Message-ID: <20250707081505.127519-8-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876981971116600 Content-Type: text/plain; charset="utf-8" This commit introduces a save_acked_features function pointer to vhost_net and converts the vhost_net function into a generic dispatcher. The vhost-user backend provides the callback, making its function static. With this change, no other module has a direct dependency on the vhost-user implementation. This cleanup allows for the complete removal of the net/vhost-user.h header file. Signed-off-by: Laurent Vivier --- hw/net/vhost_net-stub.c | 1 - hw/net/vhost_net.c | 10 +++++----- include/hw/virtio/vhost.h | 2 ++ include/net/vhost-user.h | 16 ---------------- include/net/vhost_net.h | 2 ++ net/tap.c | 1 + net/vhost-user-stub.c | 1 - net/vhost-user.c | 4 ++-- net/vhost-vdpa.c | 1 + 9 files changed, 13 insertions(+), 25 deletions(-) delete mode 100644 include/net/vhost-user.h diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c index 7bed0bf92b8e..7d49f82906a9 100644 --- a/hw/net/vhost_net-stub.c +++ b/hw/net/vhost_net-stub.c @@ -13,7 +13,6 @@ #include "qemu/osdep.h" #include "net/net.h" #include "net/tap.h" -#include "net/vhost-user.h" =20 #include "hw/virtio/virtio-net.h" #include "net/vhost_net.h" diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index fb169af0e81b..976d2b315a2f 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -16,7 +16,6 @@ #include "qemu/osdep.h" #include "net/net.h" #include "net/tap.h" -#include "net/vhost-user.h" #include "net/vhost-vdpa.h" =20 #include "standard-headers/linux/vhost_types.h" @@ -70,11 +69,11 @@ uint64_t vhost_net_get_acked_features(VHostNetState *ne= t) =20 void vhost_net_save_acked_features(NetClientState *nc) { -#ifdef CONFIG_VHOST_NET_USER - if (nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { - vhost_user_save_acked_features(nc); + struct vhost_net *net =3D get_vhost_net(nc); + + if (net && net->save_acked_features) { + net->save_acked_features(nc); } -#endif } =20 static void vhost_net_disable_notifiers_nvhosts(VirtIODevice *dev, @@ -245,6 +244,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) net->nc =3D options->net_backend; net->dev.nvqs =3D options->nvqs; net->feature_bits =3D options->feature_bits; + net->save_acked_features =3D options->save_acked_features; =20 net->dev.max_queues =3D 1; net->dev.vqs =3D net->vqs; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 6a75fdc0213c..b0830bac798a 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -1,6 +1,7 @@ #ifndef VHOST_H #define VHOST_H =20 +#include "net/vhost_net.h" #include "hw/virtio/vhost-backend.h" #include "hw/virtio/virtio.h" #include "system/memory.h" @@ -144,6 +145,7 @@ struct vhost_net { struct vhost_virtqueue vqs[2]; int backend; const int *feature_bits; + SaveAcketFeatures *save_acked_features; NetClientState *nc; }; =20 diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h deleted file mode 100644 index a4d0ce4b8dd1..000000000000 --- a/include/net/vhost-user.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * vhost-user.h - * - * Copyright (c) 2013 Virtual Open Systems Sarl. - * - * This work is licensed under the terms of the GNU GPL, version 2 or late= r. - * See the COPYING file in the top-level directory. - * - */ - -#ifndef VHOST_USER_H -#define VHOST_USER_H - -void vhost_user_save_acked_features(NetClientState *nc); - -#endif /* VHOST_USER_H */ diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index a8d281c8f7c2..eb26ed9bdcbf 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -8,6 +8,7 @@ struct vhost_net; typedef struct vhost_net VHostNetState; =20 typedef uint64_t (GetAckedFeatures)(NetClientState *nc); +typedef void (SaveAcketFeatures)(NetClientState *nc); =20 typedef struct VhostNetOptions { VhostBackendType backend_type; @@ -16,6 +17,7 @@ typedef struct VhostNetOptions { unsigned int nvqs; const int *feature_bits; GetAckedFeatures *get_acked_features; + SaveAcketFeatures *save_acked_features; void *opaque; } VhostNetOptions; =20 diff --git a/net/tap.c b/net/tap.c index acd77f816fec..79fa02a65c91 100644 --- a/net/tap.c +++ b/net/tap.c @@ -745,6 +745,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, options.nvqs =3D 2; options.feature_bits =3D kernel_feature_bits; options.get_acked_features =3D NULL; + options.save_acked_features =3D NULL; =20 s->vhost_net =3D vhost_net_init(&options); if (!s->vhost_net) { diff --git a/net/vhost-user-stub.c b/net/vhost-user-stub.c index 52ab4e13f12a..283dee87db2d 100644 --- a/net/vhost-user-stub.c +++ b/net/vhost-user-stub.c @@ -11,7 +11,6 @@ #include "qemu/osdep.h" #include "clients.h" #include "net/vhost_net.h" -#include "net/vhost-user.h" #include "qemu/error-report.h" #include "qapi/error.h" =20 diff --git a/net/vhost-user.c b/net/vhost-user.c index 93b413b49f34..8a3df27b02cf 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -11,7 +11,6 @@ #include "qemu/osdep.h" #include "clients.h" #include "net/vhost_net.h" -#include "net/vhost-user.h" #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user.h" #include "standard-headers/linux/virtio_net.h" @@ -88,7 +87,7 @@ static uint64_t vhost_user_get_acked_features(NetClientSt= ate *nc) return s->acked_features; } =20 -void vhost_user_save_acked_features(NetClientState *nc) +static void vhost_user_save_acked_features(NetClientState *nc) { NetVhostUserState *s; =20 @@ -140,6 +139,7 @@ static int vhost_user_start(int queues, NetClientState = *ncs[], options.nvqs =3D 2; options.feature_bits =3D user_feature_bits; options.get_acked_features =3D vhost_user_get_acked_features; + options.save_acked_features =3D vhost_user_save_acked_features; =20 net =3D vhost_net_init(&options); if (!net) { diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index a3980d1fb5ed..c63225d3d2ed 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -203,6 +203,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be, options.nvqs =3D nvqs; options.feature_bits =3D vdpa_feature_bits; options.get_acked_features =3D NULL; + options.save_acked_features =3D NULL; =20 net =3D vhost_net_init(&options); if (!net) { --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876200; cv=none; d=zohomail.com; s=zohoarc; b=bZiSgTooULTsic3rUhfiqC/J03fG1hwEPtwJa1kyYiIx+uee+T3LShBBZWEuERTX+Vxw8oBesk4/sAkscu/FW18nv+E5xzjmEqomivZIQbCWsudNXpTo9bekS+ElbUgZ5fluqRXm+uLUAQSEnQcnn3kdWD40QM4BJY49UsbTUtc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876200; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=fI0g4aSAGtXxXc4YGSTKu7BnCDGAeLc3PRCc1/pH5ls=; b=NdeHu6YQzWP/mmCZZ83Ekm7ywa/sE/WELhlBPHIcQPK2JNOa5ajU/YHKx/eJs+8XWQwpwkl2/xNHROwfLMpU+8IALqbeSFo/s+kCFmRCT4TWFcJp8+/5E4t5qVUgKMYV5kAK3R7J7wJdSKpnG5XAjvhgktef352PzKQtWmR5FJ0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876200136443.8355204840343; Mon, 7 Jul 2025 01:16:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh18-0000Ey-AE; Mon, 07 Jul 2025 04:16:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh16-0000Dn-9o for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:00 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh14-0007TD-G2 for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:00 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-546-pakXk4O0OmGYwuJgP6O91g-1; Mon, 07 Jul 2025 04:15:54 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AA6681944A8C; Mon, 7 Jul 2025 08:15:52 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4A93518046C6; Mon, 7 Jul 2025 08:15:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876157; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fI0g4aSAGtXxXc4YGSTKu7BnCDGAeLc3PRCc1/pH5ls=; b=I6KTkOv6BeLp0QZnayFXaizTRmoYPtxezEhMs4LT1CiAezC52+GqpuQ7Mp+In6eBIYd5ND bjroe+CU2THRr7INQoNCKSU38uTVU5XE2keRbvWYWsXshIUtCyYfs7oS+rJKqSCMfaQpfr Y1t+dyFyc4f3pQ0zdlbBkjjnn+7HT7I= X-MC-Unique: pakXk4O0OmGYwuJgP6O91g-1 X-Mimecast-MFC-AGG-ID: pakXk4O0OmGYwuJgP6O91g_1751876152 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 08/11] net: Allow network backends to advertise max TX queue size Date: Mon, 7 Jul 2025 10:15:02 +0200 Message-ID: <20250707081505.127519-9-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876202534116600 Content-Type: text/plain; charset="utf-8" This commit refactors how the maximum transmit queue size for virtio-net devices is determined, making the mechanism more generic and extensible. Previously, virtio_net_max_tx_queue_size() contained hardcoded checks for specific network backend types (vhost-user and vhost-vdpa) to determine their supported maximum queue size. This created direct dependencies and would require modifications for every new backend that supports variable queue sizes. To improve flexibility, a new max_tx_queue_size field is added to the vhost_net structure. This allows each network backend to advertise its supported maximum transmit queue size directly. The virtio_net_max_tx_queue_size() function now retrieves the max TX queue size from the vhost_net struct, if available and set. Otherwise, it defaults to VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE. Signed-off-by: Laurent Vivier --- hw/net/vhost_net.c | 1 + hw/net/virtio-net.c | 24 ++++++++++++------------ include/hw/virtio/vhost.h | 1 + include/net/vhost_net.h | 1 + net/tap.c | 1 + net/vhost-user.c | 1 + net/vhost-vdpa.c | 1 + 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 976d2b315a2f..74d2e3ed90f5 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -245,6 +245,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) net->dev.nvqs =3D options->nvqs; net->feature_bits =3D options->feature_bits; net->save_acked_features =3D options->save_acked_features; + net->max_tx_queue_size =3D options->max_tx_queue_size; =20 net->dev.max_queues =3D 1; net->dev.vqs =3D net->vqs; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b52660436273..789717818317 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -670,22 +670,22 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, = int mergeable_rx_bufs, static int virtio_net_max_tx_queue_size(VirtIONet *n) { NetClientState *peer =3D n->nic_conf.peers.ncs[0]; + struct vhost_net *net; =20 - /* - * Backends other than vhost-user or vhost-vdpa don't support max queue - * size. - */ if (!peer) { - return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; + goto default_value; } =20 - switch(peer->info->type) { - case NET_CLIENT_DRIVER_VHOST_USER: - case NET_CLIENT_DRIVER_VHOST_VDPA: - return VIRTQUEUE_MAX_SIZE; - default: - return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; - }; + net =3D get_vhost_net(peer); + + if (!net || !net->max_tx_queue_size) { + goto default_value; + } + + return net->max_tx_queue_size; + +default_value: + return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; } =20 static int peer_attach(VirtIONet *n, int index) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index b0830bac798a..a62992c8192e 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -145,6 +145,7 @@ struct vhost_net { struct vhost_virtqueue vqs[2]; int backend; const int *feature_bits; + int max_tx_queue_size; SaveAcketFeatures *save_acked_features; NetClientState *nc; }; diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index eb26ed9bdcbf..8f4fddfb69ea 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -16,6 +16,7 @@ typedef struct VhostNetOptions { uint32_t busyloop_timeout; unsigned int nvqs; const int *feature_bits; + int max_tx_queue_size; GetAckedFeatures *get_acked_features; SaveAcketFeatures *save_acked_features; void *opaque; diff --git a/net/tap.c b/net/tap.c index 79fa02a65c91..2f0cb55c9a77 100644 --- a/net/tap.c +++ b/net/tap.c @@ -746,6 +746,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, options.feature_bits =3D kernel_feature_bits; options.get_acked_features =3D NULL; options.save_acked_features =3D NULL; + options.max_tx_queue_size =3D 0; =20 s->vhost_net =3D vhost_net_init(&options); if (!s->vhost_net) { diff --git a/net/vhost-user.c b/net/vhost-user.c index 8a3df27b02cf..bf892915def1 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -138,6 +138,7 @@ static int vhost_user_start(int queues, NetClientState = *ncs[], options.busyloop_timeout =3D 0; options.nvqs =3D 2; options.feature_bits =3D user_feature_bits; + options.max_tx_queue_size =3D VIRTQUEUE_MAX_SIZE; options.get_acked_features =3D vhost_user_get_acked_features; options.save_acked_features =3D vhost_user_save_acked_features; =20 diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index c63225d3d2ed..353392b3d741 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -204,6 +204,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be, options.feature_bits =3D vdpa_feature_bits; options.get_acked_features =3D NULL; options.save_acked_features =3D NULL; + options.max_tx_queue_size =3D VIRTQUEUE_MAX_SIZE; =20 net =3D vhost_net_init(&options); if (!net) { --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876298; cv=none; d=zohomail.com; s=zohoarc; b=agiC+PeVV8EKodk0MueVgLAS2h8QPzR25rz2x2lBCL9B/if/TonIg1SGPhAUTkKfDCGymi85ne9IlDTXcnuJ1O/B5IspXEU1m/L0rA6ThkfXOXnyiL3VEWcneToHqj06HCPvrDkshy4TIUD5El25/xTVx29T9n4r2oDrv7KJVC4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876298; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qrDrFGgxVI/5jPLGv6XBLu49UEWzUDEnHNCSZAEK+0k=; b=BeAxlZNEJeknO666gZ4A/iKPKXLH3u+Q0Nc/WX3bKFgpbot1E0SxHO/Cv5LWZj0ZQDdHH+u7vz083/becVtHrAc0wJCTUp9Px9/x4mYq1vm1y3wD2F+P9UIMy7tdIN+RPfmA834/jOfjBCg7MygyFQh1qZtonprCwTsCW+yT8xg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876298432866.0158329159863; Mon, 7 Jul 2025 01:18:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh1A-0000G4-0d; Mon, 07 Jul 2025 04:16:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh18-0000FA-FW for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:02 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh16-0007TS-HZ for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:02 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-477-Vwex5cGIO9-jhEUwiWko3w-1; Mon, 07 Jul 2025 04:15:58 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 74C8819560A1; Mon, 7 Jul 2025 08:15:57 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 31C5218046C5; Mon, 7 Jul 2025 08:15:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qrDrFGgxVI/5jPLGv6XBLu49UEWzUDEnHNCSZAEK+0k=; b=QlDy8yE8sjAyO9CTobkuod+/Nv+Zgw1VJrq6ZPAymuhukXh33hbqpiZNbdkC0CstgzG4fv zLBv8/Xujxtfl4mpG6y+JoKtlqoSotKxeov0/NouKJdEe14ImOxregCfK1RM7IROS5/bN0 B0T0GPXjiNVcWTdMAgM2XtT6urn/vBc= X-MC-Unique: Vwex5cGIO9-jhEUwiWko3w-1 X-Mimecast-MFC-AGG-ID: Vwex5cGIO9-jhEUwiWko3w_1751876157 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 09/11] net: Add is_vhost_user flag to vhost_net struct Date: Mon, 7 Jul 2025 10:15:03 +0200 Message-ID: <20250707081505.127519-10-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876299999116600 Content-Type: text/plain; charset="utf-8" Introduce a boolean is_vhost_user field to the vhost_net structure. This flag is initialized during vhost_net_init based on whether the backend is vhost-user. This refactoring simplifies checks for vhost-user specific behavior, replacing direct comparisons of 'net->nc->info->type' with the new flag. It improves readability and encapsulates the backend type information directly within the vhost_net instance. Signed-off-by: Laurent Vivier --- hw/net/vhost_net.c | 3 ++- hw/net/virtio-net.c | 8 ++++++-- include/hw/virtio/vhost.h | 1 + include/net/vhost_net.h | 1 + net/tap.c | 1 + net/vhost-user.c | 1 + net/vhost-vdpa.c | 1 + 7 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 74d2e3ed90f5..540492b37ddc 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -246,6 +246,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *optio= ns) net->feature_bits =3D options->feature_bits; net->save_acked_features =3D options->save_acked_features; net->max_tx_queue_size =3D options->max_tx_queue_size; + net->is_vhost_user =3D options->is_vhost_user; =20 net->dev.max_queues =3D 1; net->dev.vqs =3D net->vqs; @@ -440,7 +441,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *= ncs, * because vhost user doesn't interrupt masking/unmasking * properly. */ - if (net->nc->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { + if (net->is_vhost_user) { dev->use_guest_notifier_mask =3D false; } } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 789717818317..3b5448de8191 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -691,12 +691,14 @@ default_value: static int peer_attach(VirtIONet *n, int index) { NetClientState *nc =3D qemu_get_subqueue(n->nic, index); + struct vhost_net *net; =20 if (!nc->peer) { return 0; } =20 - if (nc->peer->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { + net =3D get_vhost_net(nc->peer); + if (net && net->is_vhost_user) { vhost_net_set_vring_enable(nc->peer, 1); } =20 @@ -714,12 +716,14 @@ static int peer_attach(VirtIONet *n, int index) static int peer_detach(VirtIONet *n, int index) { NetClientState *nc =3D qemu_get_subqueue(n->nic, index); + struct vhost_net *net; =20 if (!nc->peer) { return 0; } =20 - if (nc->peer->info->type =3D=3D NET_CLIENT_DRIVER_VHOST_USER) { + net =3D get_vhost_net(nc->peer); + if (net && net->is_vhost_user) { vhost_net_set_vring_enable(nc->peer, 0); } =20 diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index a62992c8192e..f178cf9e1d57 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -147,6 +147,7 @@ struct vhost_net { const int *feature_bits; int max_tx_queue_size; SaveAcketFeatures *save_acked_features; + bool is_vhost_user; NetClientState *nc; }; =20 diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 8f4fddfb69ea..879781dad7b6 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -17,6 +17,7 @@ typedef struct VhostNetOptions { unsigned int nvqs; const int *feature_bits; int max_tx_queue_size; + bool is_vhost_user; GetAckedFeatures *get_acked_features; SaveAcketFeatures *save_acked_features; void *opaque; diff --git a/net/tap.c b/net/tap.c index 2f0cb55c9a77..23536c09b465 100644 --- a/net/tap.c +++ b/net/tap.c @@ -747,6 +747,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, options.get_acked_features =3D NULL; options.save_acked_features =3D NULL; options.max_tx_queue_size =3D 0; + options.is_vhost_user =3D false; =20 s->vhost_net =3D vhost_net_init(&options); if (!s->vhost_net) { diff --git a/net/vhost-user.c b/net/vhost-user.c index bf892915def1..1c3b8b36f351 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -141,6 +141,7 @@ static int vhost_user_start(int queues, NetClientState = *ncs[], options.max_tx_queue_size =3D VIRTQUEUE_MAX_SIZE; options.get_acked_features =3D vhost_user_get_acked_features; options.save_acked_features =3D vhost_user_save_acked_features; + options.is_vhost_user =3D true; =20 net =3D vhost_net_init(&options); if (!net) { diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 353392b3d741..943e9c585c4c 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -205,6 +205,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be, options.get_acked_features =3D NULL; options.save_acked_features =3D NULL; options.max_tx_queue_size =3D VIRTQUEUE_MAX_SIZE; + options.is_vhost_user =3D false; =20 net =3D vhost_net_init(&options); if (!net) { --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876202; cv=none; d=zohomail.com; s=zohoarc; b=D1L3IMIyIbhrmQ4eWgTgI6aYrpNoslNqv8CTkhgX9HkS8ILjl0ROuzWGp/Vx+U1jKOvSKddAPQA1/gceTkA2W9ostUleW9YfvFsIF+6KLZdfLLpuwkybPqyFl56B3UQoCxA9gOm9ssSP7xB+KZNzG6U98i33hudoXSgenW5KpdU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876202; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=FnYydR4V0quatpugzQCe28351azNl+MR44OzIdbCWKg=; b=fDtgkw7Vr+4MSnAJQJMZPQp1Uqyxzf0KX6BTBbAoWTAz2QEfVuJ5zFIJD68JqrpDWP/1wkXl+sbZmbJ5FJCwICxk0JmU6mv4hYymaefYDLbwir70DJ8O1+2fJFFwO+5HaX1i2dbQq93dDk1T5Fdr3Hh8/pm1HsImil6v5cRha8s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17518762027101014.3042479808837; Mon, 7 Jul 2025 01:16:42 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh1N-0000Jr-Dm; Mon, 07 Jul 2025 04:16:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh1F-0000Ic-NE for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh1B-0007UH-Ee for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:09 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-224-3tXYiOvCM0O_MMp4guyHSw-1; Mon, 07 Jul 2025 04:16:03 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 208C71944AA5; Mon, 7 Jul 2025 08:16:02 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 24AA71803AF2; Mon, 7 Jul 2025 08:15:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876164; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FnYydR4V0quatpugzQCe28351azNl+MR44OzIdbCWKg=; b=fE362Y0AHnWwFBSymU+quuUtDNqr7i+I8zLyG/JPjLH7U/GGDEAzm9KxLnci9kdwvjzlTq a+qgwSWNnQOggKAnXmjKhx1II5SnUdLy4CNZbQ66wiewhpv5s3QArUPMkxvQzqwG4/iCJ1 SyIP2WkhOyoEAdJiezxaJJmS1lg1aUs= X-MC-Unique: 3tXYiOvCM0O_MMp4guyHSw-1 X-Mimecast-MFC-AGG-ID: 3tXYiOvCM0O_MMp4guyHSw_1751876162 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 10/11] net: Add passt network backend Date: Mon, 7 Jul 2025 10:15:04 +0200 Message-ID: <20250707081505.127519-11-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, PDS_OTHER_BAD_TLD=1.999, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876205040116600 Content-Type: text/plain; charset="utf-8" This commit introduces support for passt as a new network backend. passt is an unprivileged, user-mode networking solution that provides connectivity for virtual machines by launching an external helper process. The implementation reuses the generic stream data handling logic. It launches the passt binary using GSubprocess, passing it a file descriptor from a socketpair() for communication. QEMU connects to the other end of the socket pair to establish the network data stream. The PID of the passt daemon is tracked via a temporary file to ensure it is terminated when QEMU exits. Signed-off-by: Laurent Vivier --- docs/system/devices/net.rst | 40 +++++- hmp-commands.hx | 3 + meson.build | 6 + meson_options.txt | 2 + net/clients.h | 4 + net/hub.c | 3 + net/meson.build | 3 + net/net.c | 4 + net/passt.c | 241 ++++++++++++++++++++++++++++++++++ qapi/net.json | 25 ++++ qemu-options.hx | 44 ++++++- scripts/meson-buildoptions.sh | 3 + 12 files changed, 374 insertions(+), 4 deletions(-) create mode 100644 net/passt.c diff --git a/docs/system/devices/net.rst b/docs/system/devices/net.rst index a3efbdcabd1a..255ac9b8d1ed 100644 --- a/docs/system/devices/net.rst +++ b/docs/system/devices/net.rst @@ -85,13 +85,49 @@ passt doesn't require any capability or privilege. pass= t has better performance than ``-net user``, full IPv6 support and better securi= ty as it's a daemon that is not executed in QEMU context. =20 -passt can be connected to QEMU either by using a socket -(``-netdev stream``) or using the vhost-user interface (``-netdev vhost-us= er``). +passt_ can be used in the same way as the user backend (using ``-net passt= ``, +``-netdev passt`` or ``-nic passt``) or it can be launched manually and +connected to QEMU either by using a socket (``-netdev stream``) or by using +the vhost-user interface (``-netdev vhost-user``). + +Using ``-netdev stream`` or ``-netdev vhost-user`` will allow the user to +enable functionalities not available through the passt backend interface +(like migration). + See `passt(1)`_ for more details on passt. =20 .. _passt: https://passt.top/ .. _passt(1): https://passt.top/builds/latest/web/passt.1.html =20 +To use the passt backend interface +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no need to start the daemon as QEMU will do it for you. + +passt is started in the socket-based mode. + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -nic passt + + (qemu) info network + e1000e.0: index=3D0,type=3Dnic,model=3De1000e,macaddr=3D52:54:00:12:34:= 56 + \ #net071: index=3D0,type=3Dpasst,stream,connected to pid 24846 + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -net nic -net passt,param=3D--tcp-ports= =3D10001,param=3Dudp-ports=3D10001 + + (qemu) info network + hub 0 + \ hub0port1: #net136: index=3D0,type=3Dpasst,stream,connected to pid 2= 5204 + \ hub0port0: e1000e.0: index=3D0,type=3Dnic,model=3De1000e,macaddr=3D5= 2:54:00:12:34:56 + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -netdev passt,id=3Dnetdev0 -device virtio= -net,mac=3D9a:2b:2c:2d:2e:2f,id=3Dvirtio0,netdev=3Dnetdev0 + + (qemu) info network + virtio0: index=3D0,type=3Dnic,model=3Dvirtio-net-pci,macaddr=3D9a:2b:2c= :2d:2e:2f + \ netdev0: index=3D0,type=3Dpasst,stream,connected to pid 25428 + To use socket based passt interface: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ =20 diff --git a/hmp-commands.hx b/hmp-commands.hx index 06746f0afc37..d0e4f35a30af 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1287,6 +1287,9 @@ ERST .name =3D "netdev_add", .args_type =3D "netdev:O", .params =3D "[user|tap|socket|stream|dgram|vde|bridge|hubport|= netmap|vhost-user" +#ifdef CONFIG_PASST + "|passt" +#endif #ifdef CONFIG_AF_XDP "|af-xdp" #endif diff --git a/meson.build b/meson.build index dbc97bfdf7a0..3dd533e57184 100644 --- a/meson.build +++ b/meson.build @@ -1285,6 +1285,10 @@ if not get_option('slirp').auto() or have_system endif endif =20 +enable_passt =3D get_option('passt') \ + .require(host_os =3D=3D 'linux', error_message: 'passt is supported only= on Linux') \ + .allowed() + vde =3D not_found if not get_option('vde').auto() or have_system or have_tools vde =3D cc.find_library('vdeplug', has_headers: ['libvdeplug.h'], @@ -2538,6 +2542,7 @@ if seccomp.found() config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc) endif config_host_data.set('CONFIG_PIXMAN', pixman.found()) +config_host_data.set('CONFIG_PASST', enable_passt) config_host_data.set('CONFIG_SLIRP', slirp.found()) config_host_data.set('CONFIG_SNAPPY', snappy.found()) config_host_data.set('CONFIG_SOLARIS', host_os =3D=3D 'sunos') @@ -4925,6 +4930,7 @@ if host_os =3D=3D 'darwin' summary_info +=3D {'vmnet.framework support': vmnet} endif summary_info +=3D {'AF_XDP support': libxdp} +summary_info +=3D {'passt support': enable_passt} summary_info +=3D {'slirp support': slirp} summary_info +=3D {'vde support': vde} summary_info +=3D {'netmap support': have_netmap} diff --git a/meson_options.txt b/meson_options.txt index a442be29958f..3146eec19440 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -234,6 +234,8 @@ option('pixman', type : 'feature', value : 'auto', description: 'pixman support') option('slirp', type: 'feature', value: 'auto', description: 'libslirp user mode network backend support') +option('passt', type: 'feature', value: 'auto', + description: 'passt network backend support') option('vde', type : 'feature', value : 'auto', description: 'vde network backend support') option('vmnet', type : 'feature', value : 'auto', diff --git a/net/clients.h b/net/clients.h index be53794582cf..e786ab420352 100644 --- a/net/clients.h +++ b/net/clients.h @@ -29,6 +29,10 @@ int net_init_dump(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp); =20 +#ifdef CONFIG_PASST +int net_init_passt(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp); +#endif #ifdef CONFIG_SLIRP int net_init_slirp(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp); diff --git a/net/hub.c b/net/hub.c index cba20ebd874f..e3b58b1c4f8e 100644 --- a/net/hub.c +++ b/net/hub.c @@ -285,6 +285,9 @@ void net_hub_check_clients(void) case NET_CLIENT_DRIVER_NIC: has_nic =3D 1; break; +#ifdef CONFIG_PASST + case NET_CLIENT_DRIVER_PASST: +#endif case NET_CLIENT_DRIVER_USER: case NET_CLIENT_DRIVER_TAP: case NET_CLIENT_DRIVER_SOCKET: diff --git a/net/meson.build b/net/meson.build index bb3c011e5a30..da6ea635e95d 100644 --- a/net/meson.build +++ b/net/meson.build @@ -34,6 +34,9 @@ system_ss.add(when: 'CONFIG_TCG', if_true: files('filter-= replay.c')) if have_l2tpv3 system_ss.add(files('l2tpv3.c')) endif +if enable_passt + system_ss.add(files('passt.c')) +endif system_ss.add(when: slirp, if_true: files('slirp.c')) system_ss.add(when: vde, if_true: files('vde.c')) if have_netmap diff --git a/net/net.c b/net/net.c index cfa2d8e95827..90f69fdf39b0 100644 --- a/net/net.c +++ b/net/net.c @@ -1248,6 +1248,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DR= IVER__MAX])( const char *name, NetClientState *peer, Error **errp) =3D { [NET_CLIENT_DRIVER_NIC] =3D net_init_nic, +#ifdef CONFIG_PASST + [NET_CLIENT_DRIVER_PASST] =3D net_init_passt, +#endif #ifdef CONFIG_SLIRP [NET_CLIENT_DRIVER_USER] =3D net_init_slirp, #endif @@ -1353,6 +1356,7 @@ void show_netdevs(void) "dgram", "hubport", "tap", + "passt", #ifdef CONFIG_SLIRP "user", #endif diff --git a/net/passt.c b/net/passt.c new file mode 100644 index 000000000000..4936825d681c --- /dev/null +++ b/net/passt.c @@ -0,0 +1,241 @@ +/* + * passt network backend + * + * Copyright Red Hat + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include +#include +#include "net/net.h" +#include "clients.h" +#include "qapi/error.h" +#include "io/net-listener.h" +#include "stream_data.h" + +typedef struct NetPasstState { + NetStreamData data; + GPtrArray *args; + gchar *pidfile; + pid_t pid; +} NetPasstState; + +static int net_passt_stream_start(NetPasstState *s, Error **errp); + +static void net_passt_cleanup(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + kill(s->pid, SIGTERM); + g_remove(s->pidfile); + g_free(s->pidfile); + g_ptr_array_free(s->args, TRUE); +} + +static ssize_t net_passt_receive(NetClientState *nc, const uint8_t *buf, + size_t size) +{ + NetStreamData *d =3D DO_UPCAST(NetStreamData, nc, nc); + + return net_stream_data_receive(d, buf, size); +} + +static gboolean net_passt_send(QIOChannel *ioc, GIOCondition condition, + gpointer data) +{ + if (net_stream_data_send(ioc, condition, data) =3D=3D G_SOURCE_REMOVE)= { + NetPasstState *s =3D DO_UPCAST(NetPasstState, data, data); + Error *error; + + /* we need to restart passt */ + kill(s->pid, SIGTERM); + if (net_passt_stream_start(s, &error) =3D=3D -1) { + error_report_err(error); + } + + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +static NetClientInfo net_passt_info =3D { + .type =3D NET_CLIENT_DRIVER_PASST, + .size =3D sizeof(NetPasstState), + .receive =3D net_passt_receive, + .cleanup =3D net_passt_cleanup, +}; + +static void net_passt_client_connected(QIOTask *task, gpointer opaque) +{ + NetPasstState *s =3D opaque; + + if (net_stream_data_client_connected(task, &s->data) =3D=3D 0) { + qemu_set_info_str(&s->data.nc, "stream,connected to pid %d", s->pi= d); + } +} + +static int net_passt_start_daemon(NetPasstState *s, int sock, Error **errp) +{ + g_autoptr(GSubprocess) daemon =3D NULL; + g_autofree gchar *contents =3D NULL; + g_autoptr(GError) error =3D NULL; + GSubprocessLauncher *launcher; + + qemu_set_info_str(&s->data.nc, "launching passt"); + + launcher =3D g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_NONE); + g_subprocess_launcher_take_fd(launcher, sock, 3); + + daemon =3D g_subprocess_launcher_spawnv(launcher, + (const gchar *const *)s->args->= pdata, + &error); + g_object_unref(launcher); + + if (!daemon) { + error_setg(errp, "Error creating daemon: %s", error->message); + return -1; + } + + if (!g_subprocess_wait(daemon, NULL, &error)) { + error_setg(errp, "Error waiting for daemon: %s", error->message); + return -1; + } + + if (g_subprocess_get_if_exited(daemon) && + g_subprocess_get_exit_status(daemon)) { + return -1; + } + + if (!g_file_get_contents(s->pidfile, &contents, NULL, &error)) { + error_setg(errp, "Cannot read passt pid: %s", error->message); + return -1; + } + + s->pid =3D (pid_t)g_ascii_strtoll(contents, NULL, 10); + if (s->pid <=3D 0) { + error_setg(errp, "File '%s' did not contain a valid PID.", s->pidf= ile); + return -1; + } + + return 0; +} + +static int net_passt_stream_start(NetPasstState *s, Error **errp) +{ + QIOChannelSocket *sioc; + SocketAddress *addr; + int sv[2]; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) =3D=3D -1) { + error_setg_errno(errp, errno, "socketpair() failed"); + return -1; + } + + /* connect to passt */ + qemu_set_info_str(&s->data.nc, "connecting to passt"); + + /* create socket channel */ + sioc =3D qio_channel_socket_new(); + s->data.ioc =3D QIO_CHANNEL(sioc); + s->data.nc.link_down =3D true; + s->data.send =3D net_passt_send; + + addr =3D g_new0(SocketAddress, 1); + addr->type =3D SOCKET_ADDRESS_TYPE_FD; + addr->u.fd.str =3D g_strdup_printf("%d", sv[0]); + + qio_channel_socket_connect_async(sioc, addr, + net_passt_client_connected, s, + NULL, NULL); + + qapi_free_SocketAddress(addr); + + /* start passt */ + if (net_passt_start_daemon(s, sv[1], errp) =3D=3D -1) { + close(sv[0]); + close(sv[1]); + return -1; + } + close(sv[1]); + + return 0; +} + +static GPtrArray *net_passt_decode_args(const NetDevPasstOptions *passt, + gchar *pidfile, Error **errp) +{ + GPtrArray *args =3D g_ptr_array_new_with_free_func(g_free); + + if (passt->path) { + g_ptr_array_add(args, g_strdup(passt->path)); + } else { + g_ptr_array_add(args, g_strdup("passt")); + } + + /* by default, be quiet */ + if (!passt->has_quiet || passt->quiet) { + g_ptr_array_add(args, g_strdup("--quiet")); + } + + if (passt->has_param && passt->param) { + const StringList *list =3D passt->param; + + while (list) { + g_ptr_array_add(args, g_strdup(list->value->str)); + list =3D list->next; + } + } + + /* provide a pid file to be able to kil passt on exit */ + g_ptr_array_add(args, g_strdup("--pid")); + g_ptr_array_add(args, g_strdup(pidfile)); + + /* g_subprocess_launcher_take_fd() will set the socket on fd 3 */ + g_ptr_array_add(args, g_strdup("--fd")); + g_ptr_array_add(args, g_strdup("3")); + + g_ptr_array_add(args, NULL); + + return args; +} + +int net_init_passt(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp) +{ + g_autoptr(GError) error =3D NULL; + NetClientState *nc; + NetPasstState *s; + GPtrArray *args; + gchar *pidfile; + int pidfd; + + assert(netdev->type =3D=3D NET_CLIENT_DRIVER_PASST); + + pidfd =3D g_file_open_tmp("passt-XXXXXX.pid", &pidfile, &error); + if (pidfd =3D=3D -1) { + error_setg(errp, "Failed to create temporary file: %s", error->mes= sage); + return -1; + } + close(pidfd); + + args =3D net_passt_decode_args(&netdev->u.passt, pidfile, errp); + if (args =3D=3D NULL) { + g_free(pidfile); + return -1; + } + + nc =3D qemu_new_net_client(&net_passt_info, peer, "passt", name); + s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + s->args =3D args; + s->pidfile =3D pidfile; + + if (net_passt_stream_start(s, errp) =3D=3D -1) { + qemu_del_net_client(nc); + return -1; + } + + return 0; +} diff --git a/qapi/net.json b/qapi/net.json index 97ea1839813b..8a8528ba1f47 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -112,6 +112,26 @@ 'data': { 'str': 'str' } } =20 +## +# @NetDevPasstOptions: +# +# Unprivileged user-mode network connectivity using passt +# +# @path: Filename of the passt program to run (by default 'passt', and use= PATH) +# +# @quiet: don't print informational messages (default, passed as '--quiet') +# +# @param: parameter to pass to passt command +# +# Since: 10.1 +## +{ 'struct': 'NetDevPasstOptions', + 'data': { + '*path': 'str', + '*quiet': 'bool', + '*param': ['String'] }, + 'if': 'CONFIG_PASST' } + ## # @NetdevUserOptions: # @@ -729,12 +749,15 @@ # # @af-xdp: since 8.2 # +# @passt: since 10.1 +# # Since: 2.7 ## { 'enum': 'NetClientDriver', 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'stream', 'dgram', 'vde', 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa', + { 'name': 'passt', 'if': 'CONFIG_PASST' }, { 'name': 'af-xdp', 'if': 'CONFIG_AF_XDP' }, { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' }, { 'name': 'vmnet-shared', 'if': 'CONFIG_VMNET' }, @@ -756,6 +779,8 @@ 'discriminator': 'type', 'data': { 'nic': 'NetLegacyNicOptions', + 'passt': { 'type': 'NetDevPasstOptions', + 'if': 'CONFIG_PASST' }, 'user': 'NetdevUserOptions', 'tap': 'NetdevTapOptions', 'l2tpv3': 'NetdevL2TPv3Options', diff --git a/qemu-options.hx b/qemu-options.hx index 1f862b19a676..9855657aa48b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2796,6 +2796,13 @@ DEFHEADING() DEFHEADING(Network options:) =20 DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, +#ifdef CONFIG_PASST + "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off][,param=3Dlist]\= n" + " configure a passt network backend with ID 'str'\n" + " if 'path' is not provided 'passt' will be started acc= ording to PATH\n" + " by default, informational message of passt are not di= splayed (quiet=3Don)\n" + " to display this message, use 'quiet=3Doff'\n" +#endif #ifdef CONFIG_SLIRP "-netdev user,id=3Dstr[,ipv4=3Don|off][,net=3Daddr[/mask]][,host=3Dadd= r]\n" " [,ipv6=3Don|off][,ipv6-net=3Daddr[/int]][,ipv6-host=3Daddr]\= n" @@ -2952,6 +2959,9 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " configure a hub port on the hub with ID 'n'\n", QEMU_= ARCH_ALL) DEF("nic", HAS_ARG, QEMU_OPTION_nic, "-nic [tap|bridge|" +#ifdef CONFIG_PASST + "passt|" +#endif #ifdef CONFIG_SLIRP "user|" #endif @@ -2984,6 +2994,9 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, " configure or create an on-board (or machine default) = NIC and\n" " connect it to hub 0 (please use -nic unless you need = a hub)\n" "-net [" +#ifdef CONFIG_PASST + "passt|" +#endif #ifdef CONFIG_SLIRP "user|" #endif @@ -3005,7 +3018,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, " old way to initialize a host network interface\n" " (use the -netdev option if possible instead)\n", QEMU= _ARCH_ALL) SRST -``-nic [tap|bridge|user|l2tpv3|vde|netmap|af-xdp|vhost-user|socket][,...][= ,mac=3Dmacaddr][,model=3Dmn]`` +``-nic [tap|passt|bridge|user|l2tpv3|vde|netmap|af-xdp|vhost-user|socket][= ,...][,mac=3Dmacaddr][,model=3Dmn]`` This option is a shortcut for configuring both the on-board (default) guest NIC hardware and the host network backend in one go. The host backend options are the same as with the corresponding @@ -3027,6 +3040,33 @@ SRST network backend) which is activated if no other networking options are provided. =20 +``-netdev passt,id=3Dstr[,option][,...]`` + Configure a passt network backend which requires no administrator + privilege to run. Valid options are: + + ``id=3Did`` + Assign symbolic name for use in monitor commands. + + ``path=3Dfile`` + Filename of the passt program to run. If it is not provided, + passt command will be started with the help of the PATH environment + variable. + + ``quiet=3Don|off`` + By default, ``quiet=3Don`` to disable informational message from + passt. ``quiet=3Don`` is passed as ``--quiet`` to passt. + + ``param=3Dstring`` + ``string`` will be passed to passt has a command line parameter, + we can have multiple occurences of the ``param`` parameter to + pass multiple parameters to passt. + + For instance, to pass ``--tcp-ports=3D10001 --tcp-ports=3D10002 --u= dp-ports=3D10001`` to passt: + + .. parsed-literal:: + + |qemu_system| -nic passt,param=3D--tcp-ports=3D10001,param=3D--tcp= -ports=3D10002,param=3D--udp-ports=3D10001 + ``-netdev user,id=3Did[,option][,option][,...]`` Configure user mode host network backend which requires no administrator privilege to run. Valid options are: @@ -3711,7 +3751,7 @@ SRST Use ``-net nic,model=3Dhelp`` for a list of available devices for your target. =20 -``-net user|tap|bridge|socket|l2tpv3|vde[,...][,name=3Dname]`` +``-net user|passt|tap|bridge|socket|l2tpv3|vde[,...][,name=3Dname]`` Configure a host network backend (with the options corresponding to the same ``-netdev`` option) and connect it to the emulated hub 0 (the default hub). Use name to specify the name of the hub port. diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 73e0770f42b9..bb3e34d852a4 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -162,6 +162,7 @@ meson_options_help() { printf "%s\n" ' oss OSS sound support' printf "%s\n" ' pa PulseAudio sound support' printf "%s\n" ' parallels parallels image format support' + printf "%s\n" ' passt passt network backend support' printf "%s\n" ' pipewire PipeWire sound support' printf "%s\n" ' pixman pixman support' printf "%s\n" ' plugins TCG plugins via shared library loading' @@ -422,6 +423,8 @@ _meson_option_parse() { --disable-pa) printf "%s" -Dpa=3Ddisabled ;; --enable-parallels) printf "%s" -Dparallels=3Denabled ;; --disable-parallels) printf "%s" -Dparallels=3Ddisabled ;; + --enable-passt) printf "%s" -Dpasst=3Denabled ;; + --disable-passt) printf "%s" -Dpasst=3Ddisabled ;; --enable-pipewire) printf "%s" -Dpipewire=3Denabled ;; --disable-pipewire) printf "%s" -Dpipewire=3Ddisabled ;; --enable-pixman) printf "%s" -Dpixman=3Denabled ;; --=20 2.49.0 From nobody Sat Dec 13 22:59:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751876294; cv=none; d=zohomail.com; s=zohoarc; b=kjQd1SN/Mx+PN3Y98AoFxX6Y7uz26SaCAM+KHJ9HBFcG3tAzbyKropLkwfjAViWNAEyvV4g16JNVDmQZ6Qj9SSgk6X7gLTuWEAeJGe4x3mlENw5l7SjfQ+MGwJMVzGV8qR6IXc0nVDFlCeuXXEfR9U5FBWY3oHyGLeAZIBSdExM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751876294; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Hslm4SlPXjGaPdW9DtLidQZHv+Z168xrBO2wVg0jhes=; b=YGMIQlwlPFdqYzGjlEp9MyMxrgNnr75MaQ+Gr94sgl9cP6ki9GHJnUinGZcC4sJ7nvnV3yy3Fiq3WVZ55QM1qjPo+NNOG4pAewSnxhZj1e6HC7IXukToZd8cyMmCSZ3+6Un2jshPTzOZhKxSExHWc+ZBR1e0Fi/1Yl1TkASNYAE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751876294112274.2021595325897; Mon, 7 Jul 2025 01:18:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uYh1Z-0000OU-Jt; Mon, 07 Jul 2025 04:16:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh1M-0000Jw-3P for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:17 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uYh1J-0007Vc-MW for qemu-devel@nongnu.org; Mon, 07 Jul 2025 04:16:15 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-493-lhoO8OmtPryPUydSgZoACg-1; Mon, 07 Jul 2025 04:16:08 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6087A19560BE; Mon, 7 Jul 2025 08:16:07 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.45.225.147]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9B964180045B; Mon, 7 Jul 2025 08:16:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751876171; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Hslm4SlPXjGaPdW9DtLidQZHv+Z168xrBO2wVg0jhes=; b=KOIZqsjBDTlSL+To0WzNA9Y9WpwR1ukX6p8M5gMrs/XbZL/isS77LdcHA/yhJVJwiXThfp r2hDBWevCEE5UsNn4FzikwtcSwIGvOjnA7Miwt/S5zn6vzaN6oxXxl2mlcfYUq69VyJrDi zvOznEs13wnsNV2sBlKtPxmoOVVAtHQ= X-MC-Unique: lhoO8OmtPryPUydSgZoACg-1 X-Mimecast-MFC-AGG-ID: lhoO8OmtPryPUydSgZoACg_1751876167 From: Laurent Vivier To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Paolo Bonzini , Eric Blake , Markus Armbruster , "Michael S. Tsirkin" , "Dr. David Alan Gilbert" , Stefan Weil , Stefano Garzarella , Jason Wang , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Laurent Vivier Subject: [PATCH v3 11/11] net/passt: Implement vhost-user backend support Date: Mon, 7 Jul 2025 10:15:05 +0200 Message-ID: <20250707081505.127519-12-lvivier@redhat.com> In-Reply-To: <20250707081505.127519-1-lvivier@redhat.com> References: <20250707081505.127519-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lvivier@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751876296310116600 Content-Type: text/plain; charset="utf-8" This commit adds support for the vhost-user interface to the passt network backend, enabling high-performance, accelerated networking for guests using passt. The passt backend can now operate in a vhost-user mode, where it communicates with the guest's virtio-net device over a socket pair using the vhost-user protocol. This offloads the datapath from the main QEMU loop, significantly improving network performance. When the vhost-user=3Don option is used with -netdev passt, the new vhost initialization path is taken instead of the standard stream-based connection. Signed-off-by: Laurent Vivier --- docs/system/devices/net.rst | 12 +- net/passt.c | 346 ++++++++++++++++++++++++++++++++++++ qapi/net.json | 3 + qemu-options.hx | 12 +- 4 files changed, 370 insertions(+), 3 deletions(-) diff --git a/docs/system/devices/net.rst b/docs/system/devices/net.rst index 255ac9b8d1ed..6cc7dbb34beb 100644 --- a/docs/system/devices/net.rst +++ b/docs/system/devices/net.rst @@ -104,7 +104,7 @@ To use the passt backend interface =20 There is no need to start the daemon as QEMU will do it for you. =20 -passt is started in the socket-based mode. +By default, passt will be started in the socket-based mode. =20 .. parsed-literal:: |qemu_system| [...OPTIONS...] -nic passt @@ -128,6 +128,16 @@ passt is started in the socket-based mode. virtio0: index=3D0,type=3Dnic,model=3Dvirtio-net-pci,macaddr=3D9a:2b:2c= :2d:2e:2f \ netdev0: index=3D0,type=3Dpasst,stream,connected to pid 25428 =20 +To use the vhost-based interface, add the ``vhost-user=3Don`` parameter and +select the virtio-net device: + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -nic passt,model=3Dvirtio,vhost-user=3Don + + (qemu) info network + virtio-net-pci.0: index=3D0,type=3Dnic,model=3Dvirtio-net-pci,macaddr= =3D52:54:00:12:34:56 + \ #net006: index=3D0,type=3Dpasst,vhost-user,connected to pid 25731 + To use socket based passt interface: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ =20 diff --git a/net/passt.c b/net/passt.c index 4936825d681c..3f4f28193b87 100644 --- a/net/passt.c +++ b/net/passt.c @@ -7,18 +7,75 @@ */ #include "qemu/osdep.h" #include +#include "qemu/error-report.h" #include #include "net/net.h" #include "clients.h" #include "qapi/error.h" #include "io/net-listener.h" +#include "chardev/char-fe.h" +#include "net/vhost_net.h" +#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" +#include "standard-headers/linux/virtio_net.h" #include "stream_data.h" =20 +#ifdef CONFIG_VHOST_USER +static const int user_feature_bits[] =3D { + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_NOTIFICATION_DATA, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + + VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_VERSION_1, + VIRTIO_NET_F_CSUM, + VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GSO, + VIRTIO_NET_F_GUEST_TSO4, + VIRTIO_NET_F_GUEST_TSO6, + VIRTIO_NET_F_GUEST_ECN, + VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_HOST_TSO4, + VIRTIO_NET_F_HOST_TSO6, + VIRTIO_NET_F_HOST_ECN, + VIRTIO_NET_F_HOST_UFO, + VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_NET_F_MTU, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_RING_PACKED, + VIRTIO_F_RING_RESET, + VIRTIO_F_IN_ORDER, + VIRTIO_NET_F_RSS, + VIRTIO_NET_F_RSC_EXT, + VIRTIO_NET_F_HASH_REPORT, + VIRTIO_NET_F_GUEST_USO4, + VIRTIO_NET_F_GUEST_USO6, + VIRTIO_NET_F_HOST_USO, + + /* This bit implies RARP isn't sent by QEMU out of band */ + VIRTIO_NET_F_GUEST_ANNOUNCE, + + VIRTIO_NET_F_MQ, + + VHOST_INVALID_FEATURE_BIT +}; +#endif + typedef struct NetPasstState { NetStreamData data; GPtrArray *args; gchar *pidfile; pid_t pid; +#ifdef CONFIG_VHOST_USER + /* vhost user */ + VhostUserState *vhost_user; + VHostNetState *vhost_net; + CharBackend vhost_chr; + guint vhost_watch; + uint64_t acked_features; + bool started; +#endif } NetPasstState; =20 static int net_passt_stream_start(NetPasstState *s, Error **errp); @@ -27,6 +84,24 @@ static void net_passt_cleanup(NetClientState *nc) { NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); =20 +#ifdef CONFIG_VHOST_USER + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); + s->vhost_net =3D NULL; + } + if (s->vhost_watch) { + g_source_remove(s->vhost_watch); + s->vhost_watch =3D 0; + } + qemu_chr_fe_deinit(&s->vhost_chr, true); + if (s->vhost_user) { + vhost_user_cleanup(s->vhost_user); + g_free(s->vhost_user); + s->vhost_user =3D NULL; + } +#endif + kill(s->pid, SIGTERM); g_remove(s->pidfile); g_free(s->pidfile); @@ -60,11 +135,98 @@ static gboolean net_passt_send(QIOChannel *ioc, GIOCon= dition condition, return G_SOURCE_CONTINUE; } =20 +#ifdef CONFIG_VHOST_USER +static int passt_set_vnet_endianness(NetClientState *nc, bool enable) +{ + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + return 0; +} + +static bool passt_has_vnet_hdr(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + return s->vhost_user !=3D NULL; +} + +static bool passt_has_ufo(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + return s->vhost_user !=3D NULL; +} + +static bool passt_check_peer_type(NetClientState *nc, ObjectClass *oc, + Error **errp) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + const char *driver =3D object_class_get_name(oc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + if (s->vhost_user =3D=3D NULL) { + return true; + } + + if (!g_str_has_prefix(driver, "virtio-net-")) { + error_setg(errp, "vhost-user requires frontend driver virtio-net-*= "); + return false; + } + + return true; +} + +static struct vhost_net *passt_get_vhost_net(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + return s->vhost_net; +} + +static uint64_t passt_get_acked_features(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + return s->acked_features; +} + +static void passt_save_acked_features(NetClientState *nc) +{ + NetPasstState *s =3D DO_UPCAST(NetPasstState, data.nc, nc); + + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_PASST); + + if (s->vhost_net) { + uint64_t features =3D vhost_net_get_acked_features(s->vhost_net); + if (features) { + s->acked_features =3D features; + } + } +} +#endif + static NetClientInfo net_passt_info =3D { .type =3D NET_CLIENT_DRIVER_PASST, .size =3D sizeof(NetPasstState), .receive =3D net_passt_receive, .cleanup =3D net_passt_cleanup, +#ifdef CONFIG_VHOST_USER + .has_vnet_hdr =3D passt_has_vnet_hdr, + .has_ufo =3D passt_has_ufo, + .set_vnet_be =3D passt_set_vnet_endianness, + .set_vnet_le =3D passt_set_vnet_endianness, + .check_peer_type =3D passt_check_peer_type, + .get_vhost_net =3D passt_get_vhost_net, +#endif }; =20 static void net_passt_client_connected(QIOTask *task, gpointer opaque) @@ -163,6 +325,177 @@ static int net_passt_stream_start(NetPasstState *s, E= rror **errp) return 0; } =20 +#ifdef CONFIG_VHOST_USER +static gboolean passt_vhost_user_watch(void *do_not_use, GIOCondition cond, + void *opaque) +{ + NetPasstState *s =3D opaque; + + qemu_chr_fe_disconnect(&s->vhost_chr); + + return G_SOURCE_CONTINUE; +} + +static void passt_vhost_user_event(void *opaque, QEMUChrEvent event); + +static void chr_closed_bh(void *opaque) +{ + NetPasstState *s =3D opaque; + + passt_save_acked_features(&s->data.nc); + + net_client_set_link(&(NetClientState *){ &s->data.nc }, 1, false); + + qemu_chr_fe_set_handlers(&s->vhost_chr, NULL, NULL, passt_vhost_user_e= vent, + NULL, s, NULL, true); +} + +static void passt_vhost_user_stop(NetPasstState *s) +{ + passt_save_acked_features(&s->data.nc); + vhost_net_cleanup(s->vhost_net); +} + +static int passt_vhost_user_start(NetPasstState *s, VhostUserState *be) +{ + struct vhost_net *net =3D NULL; + VhostNetOptions options; + + options.backend_type =3D VHOST_BACKEND_TYPE_USER; + options.net_backend =3D &s->data.nc; + options.opaque =3D be; + options.busyloop_timeout =3D 0; + options.nvqs =3D 2; + options.feature_bits =3D user_feature_bits; + options.max_tx_queue_size =3D VIRTQUEUE_MAX_SIZE; + options.get_acked_features =3D passt_get_acked_features; + options.save_acked_features =3D passt_save_acked_features; + options.is_vhost_user =3D true; + + net =3D vhost_net_init(&options); + if (!net) { + error_report("failed to init passt vhost_net"); + goto err; + } + + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); + } + s->vhost_net =3D net; + + return 0; +err: + if (net) { + vhost_net_cleanup(net); + g_free(net); + } + passt_vhost_user_stop(s); + return -1; +} + +static void passt_vhost_user_event(void *opaque, QEMUChrEvent event) +{ + NetPasstState *s =3D opaque; + Error *err =3D NULL; + + switch (event) { + case CHR_EVENT_OPENED: + if (passt_vhost_user_start(s, s->vhost_user) < 0) { + qemu_chr_fe_disconnect(&s->vhost_chr); + return; + } + s->vhost_watch =3D qemu_chr_fe_add_watch(&s->vhost_chr, G_IO_HUP, + passt_vhost_user_watch, s); + net_client_set_link(&(NetClientState *){ &s->data.nc }, 1, true); + s->started =3D true; + break; + case CHR_EVENT_CLOSED: + if (s->vhost_watch) { + AioContext *ctx =3D qemu_get_current_aio_context(); + + g_source_remove(s->vhost_watch); + s->vhost_watch =3D 0; + qemu_chr_fe_set_handlers(&s->vhost_chr, NULL, NULL, NULL, NUL= L, + NULL, NULL, false); + + aio_bh_schedule_oneshot(ctx, chr_closed_bh, s); + } + break; + case CHR_EVENT_BREAK: + case CHR_EVENT_MUX_IN: + case CHR_EVENT_MUX_OUT: + /* Ignore */ + break; + } + + if (err) { + error_report_err(err); + } +} + +static int net_passt_vhost_user_init(NetPasstState *s, Error **errp) +{ + Chardev *chr; + int sv[2]; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) =3D=3D -1) { + error_setg_errno(errp, errno, "socketpair() failed"); + return -1; + } + + /* connect to passt */ + qemu_set_info_str(&s->data.nc, "connecting to passt"); + + /* create chardev */ + + chr =3D CHARDEV(object_new(TYPE_CHARDEV_SOCKET)); + if (!chr || qemu_chr_add_client(chr, sv[0]) =3D=3D -1) { + object_unref(OBJECT(chr)); + error_setg(errp, "Failed to make socket chardev"); + goto err; + } + + s->vhost_user =3D g_new0(struct VhostUserState, 1); + if (!qemu_chr_fe_init(&s->vhost_chr, chr, errp) || + !vhost_user_init(s->vhost_user, &s->vhost_chr, errp)) { + goto err; + } + + /* start passt */ + if (net_passt_start_daemon(s, sv[1], errp) =3D=3D -1) { + goto err; + } + + do { + if (qemu_chr_fe_wait_connected(&s->vhost_chr, errp) < 0) { + goto err; + } + + qemu_chr_fe_set_handlers(&s->vhost_chr, NULL, NULL, + passt_vhost_user_event, NULL, s, NULL, + true); + } while (!s->started); + + qemu_set_info_str(&s->data.nc, "vhost-user,connected to pid %d", s->pi= d); + + close(sv[1]); + return 0; +err: + close(sv[0]); + close(sv[1]); + + return -1; +} +#else +static int net_passt_vhost_user_init(NetPasstState *s, Error **errp) +{ + error_setg(errp, "vhost-user support has not been built"); + + return -1; +} +#endif + static GPtrArray *net_passt_decode_args(const NetDevPasstOptions *passt, gchar *pidfile, Error **errp) { @@ -174,6 +507,10 @@ static GPtrArray *net_passt_decode_args(const NetDevPa= sstOptions *passt, g_ptr_array_add(args, g_strdup("passt")); } =20 + if (passt->has_vhost_user && passt->vhost_user) { + g_ptr_array_add(args, g_strdup("--vhost-user")); + } + /* by default, be quiet */ if (!passt->has_quiet || passt->quiet) { g_ptr_array_add(args, g_strdup("--quiet")); @@ -232,6 +569,15 @@ int net_init_passt(const Netdev *netdev, const char *n= ame, s->args =3D args; s->pidfile =3D pidfile; =20 + if (netdev->u.passt.has_vhost_user && netdev->u.passt.vhost_user) { + if (net_passt_vhost_user_init(s, errp) =3D=3D -1) { + qemu_del_net_client(nc); + return -1; + } + + return 0; + } + if (net_passt_stream_start(s, errp) =3D=3D -1) { qemu_del_net_client(nc); return -1; diff --git a/qapi/net.json b/qapi/net.json index 8a8528ba1f47..8e4fee923fdf 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -121,6 +121,8 @@ # # @quiet: don't print informational messages (default, passed as '--quiet') # +# @vhost-user: enable vhost-user +# # @param: parameter to pass to passt command # # Since: 10.1 @@ -129,6 +131,7 @@ 'data': { '*path': 'str', '*quiet': 'bool', + '*vhost-user': 'bool', '*param': ['String'] }, 'if': 'CONFIG_PASST' } =20 diff --git a/qemu-options.hx b/qemu-options.hx index 9855657aa48b..5c468e9cd58e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2797,11 +2797,13 @@ DEFHEADING(Network options:) =20 DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_PASST - "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off][,param=3Dlist]\= n" + "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off][,vhost-user=3Do= n|off][,param=3Dlist]\n" " configure a passt network backend with ID 'str'\n" " if 'path' is not provided 'passt' will be started acc= ording to PATH\n" " by default, informational message of passt are not di= splayed (quiet=3Don)\n" " to display this message, use 'quiet=3Doff'\n" + " by default, passt will be started in socket-based mod= e, to enable vhost-mode,\n" + " use 'vhost-user=3Don'\n" #endif #ifdef CONFIG_SLIRP "-netdev user,id=3Dstr[,ipv4=3Don|off][,net=3Daddr[/mask]][,host=3Dadd= r]\n" @@ -3056,6 +3058,12 @@ SRST By default, ``quiet=3Don`` to disable informational message from passt. ``quiet=3Don`` is passed as ``--quiet`` to passt. =20 + ``vhost-user=3Don|off`` + By default, ``vhost-user=3Doff`` and QEMU uses the stream network + backend to communicate with passt. If ``vhost-user=3Don``, passt is + started with ``--vhost-user`` and QEMU uses the vhost-user network + backend to communicate with passt. + ``param=3Dstring`` ``string`` will be passed to passt has a command line parameter, we can have multiple occurences of the ``param`` parameter to @@ -3065,7 +3073,7 @@ SRST =20 .. parsed-literal:: =20 - |qemu_system| -nic passt,param=3D--tcp-ports=3D10001,param=3D--tcp= -ports=3D10002,param=3D--udp-ports=3D10001 + |qemu_system| -nic passt,vhost-user=3Don,param=3D--tcp-ports=3D100= 01,param=3D--tcp-ports=3D10002,param=3D--udp-ports=3D10001 =20 ``-netdev user,id=3Did[,option][,option][,...]`` Configure user mode host network backend which requires no --=20 2.49.0