From nobody Sun Dec 14 02:06:19 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=1752471335; cv=none; d=zohomail.com; s=zohoarc; b=i26Jw7WNHhZMY0nyxxMT77q34WxS833Wes6QK7ky5H/RKJ31XIdwDR8Do77g0a9KXlWmgVBeV0rgHtx1AW2Lt8792PWDjfxAntMTRINjyjozQjKPZlWbqe3caaGcescXuNSifXoRL7B5HhxsDg9iUhh9rr8+nghXKNCIsmligCE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471335; h=Content-Type: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=aE/wKQGzoh4jWmtAUGCBzWi5yGD7I8dxBOHfLcHtRck=; b=HD7rn5IYOJUTOZzMS9tHYsBpwSiEaz3z8CBJGltsQyiq7HKdihNzrZQn6EC6EMc97j1l2LzHEk8B4riP0NhjCCsyVmlnDiktBhpz74i56Zn07xr/AGWmOVLsrJgrms/qsZ+H/z0IEE4+0fay3rWkFLYjSnlh+iVDNRMx0e9VvFs= 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 1752471335251120.15023522854835; Sun, 13 Jul 2025 22:35:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBq4-0001Wb-Oi; Mon, 14 Jul 2025 01:34:56 -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 1ubBpp-000102-JS for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:41 -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 1ubBpo-000362-3a for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:41 -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-364-_RWvesbGOkO2Cy90mU4sFQ-1; Mon, 14 Jul 2025 01:34:35 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 C0D9F1800290; Mon, 14 Jul 2025 05:34:33 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AC31F19560A3; Mon, 14 Jul 2025 05:34:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471279; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aE/wKQGzoh4jWmtAUGCBzWi5yGD7I8dxBOHfLcHtRck=; b=FspeL2YScgg3swIP/Dyd7oxUXj1PmR7FPKZmxxcoex2CKBV64G9qNmw3A3rZrrZnGRzn/M 4G7FPFYgx+Klq08d+/UP1Xmi+fcX5vfjdtwWI3iyi73yYF063YWYpdyObeHWx1K5WmSnGs fYK48CN7fR7mYYZdC5rakkzPlb6Qe4g= X-MC-Unique: _RWvesbGOkO2Cy90mU4sFQ-1 X-Mimecast-MFC-AGG-ID: _RWvesbGOkO2Cy90mU4sFQ_1752471274 From: Jason Wang To: qemu-devel@nongnu.org Cc: Anastasia Belova , qemu-stable@nongnu.org, Ilya Maximets , Jason Wang Subject: [PULL 01/13] net: fix buffer overflow in af_xdp_umem_create() Date: Mon, 14 Jul 2025 13:34:11 +0800 Message-ID: <20250714053423.10415-2-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471336887116600 Content-Type: text/plain; charset="utf-8" From: Anastasia Belova s->pool has n_descs elements so maximum i should be n_descs - 1. Fix the upper bound. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: cb039ef3d9 ("net: add initial support for AF_XDP network backend") Cc: qemu-stable@nongnu.org Reviewed-by: Ilya Maximets Signed-off-by: Anastasia Belova Signed-off-by: Jason Wang --- net/af-xdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/af-xdp.c b/net/af-xdp.c index 01c5fb914e..d022534d76 100644 --- a/net/af-xdp.c +++ b/net/af-xdp.c @@ -323,7 +323,7 @@ static int af_xdp_umem_create(AFXDPState *s, int sock_f= d, Error **errp) =20 s->pool =3D g_new(uint64_t, n_descs); /* Fill the pool in the opposite order, because it's a LIFO queue. */ - for (i =3D n_descs; i >=3D 0; i--) { + for (i =3D n_descs - 1; i >=3D 0; i--) { s->pool[i] =3D i * XSK_UMEM__DEFAULT_FRAME_SIZE; } s->n_pool =3D n_descs; --=20 2.42.0 From nobody Sun Dec 14 02:06:19 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=1752471403; cv=none; d=zohomail.com; s=zohoarc; b=VyxQfXKo735+263gUyFKz3H+Z1UC3LV/sZp8HOqltLhin7+sNP9NuWMlMNhbBwLAF1n+AQNKYOZEx3+a+Qmb9RgzbxxOXNa6xg/7OazclD9AoV2s/MjDPMFOwLH/sGqgjDgB3jeWfeMMF8I5znXjIJaturORtQeztzEnqAAILps= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471403; h=Content-Type: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=781Vd1RCDVNzKBhruVItGkuo2QXETHPOcYRirLtEix0=; b=KREJlf83UxxtRVb1x/UtM40Dx8N/Dxuxgg5Y4FASOKDn/Yyo28IoEa809DptW8Lylbpwxbg9340wfOxlhy8jhT9Ja1gxWqOqMbMXLvrlpS3S5XCwlZopp4f/6WwBbGtmFDAnysuCBmDIf2RmRJ7l9Y4ForDciHZX4l0qqdI2MGU= 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 1752471403591968.4864622350954; Sun, 13 Jul 2025 22:36:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBps-00017g-Hx; Mon, 14 Jul 2025 01:34:44 -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 1ubBpq-00013n-QP for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:43 -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 1ubBpo-00036F-VG for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:42 -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-196-bYCz6XarMSmHZMUjjSaoaQ-1; Mon, 14 Jul 2025 01:34:38 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 6F11619560B0; Mon, 14 Jul 2025 05:34:37 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8F7FE19560A3; Mon, 14 Jul 2025 05:34:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471280; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=781Vd1RCDVNzKBhruVItGkuo2QXETHPOcYRirLtEix0=; b=bLRkn5eROSSG5ARSUWfoy0BcU80oSGOIoz2+qEl8QlorBAaUz9eja+fydJbWiW5fkdZDzd rOIJtM223PbielH6djWyuYGRBYI53qZABpeVZZRN1meMq9Zv+iyxqGCZlly+ZDCy4QisBS h9M4fKCmp7HV7d6f+KKy2jbtmjBO8vE= X-MC-Unique: bYCz6XarMSmHZMUjjSaoaQ-1 X-Mimecast-MFC-AGG-ID: bYCz6XarMSmHZMUjjSaoaQ_1752471277 From: Jason Wang To: qemu-devel@nongnu.org Cc: Akihiko Odaki , Lei Yang , qemu-stable@nongnu.org, Jason Wang Subject: [PULL 02/13] virtio-net: Add queues for RSS during migration Date: Mon, 14 Jul 2025 13:34:12 +0800 Message-ID: <20250714053423.10415-3-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471405415116600 Content-Type: text/plain; charset="utf-8" From: Akihiko Odaki virtio_net_pre_load_queues() inspects vdev->guest_features to tell if VIRTIO_NET_F_RSS or VIRTIO_NET_F_MQ is enabled to infer the required number of queues. This works for VIRTIO_NET_F_MQ but it doesn't for VIRTIO_NET_F_RSS because only the lowest 32 bits of vdev->guest_features is set at the point and VIRTIO_NET_F_RSS uses bit 60 while VIRTIO_NET_F_MQ uses bit 22. Instead of inferring the required number of queues from vdev->guest_features, use the number loaded from the vm state. This change also has a nice side effect to remove a duplicate peer queue pair change by circumventing virtio_net_set_multiqueue(). Also update the comment in include/hw/virtio/virtio.h to prevent an implementation of pre_load_queues() from refering to any fields being loaded during migration by accident in the future. Fixes: 8c49756825da ("virtio-net: Add only one queue pair when realizing") Tested-by: Lei Yang Cc: qemu-stable@nongnu.org Signed-off-by: Akihiko Odaki Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 11 ++++------- hw/virtio/virtio.c | 14 +++++++------- include/hw/virtio/virtio.h | 10 ++++++++-- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index eb93607b8c..351377c025 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3022,11 +3022,10 @@ static void virtio_net_del_queue(VirtIONet *n, int = index) virtio_del_queue(vdev, index * 2 + 1); } =20 -static void virtio_net_change_num_queue_pairs(VirtIONet *n, int new_max_qu= eue_pairs) +static void virtio_net_change_num_queues(VirtIONet *n, int new_num_queues) { VirtIODevice *vdev =3D VIRTIO_DEVICE(n); int old_num_queues =3D virtio_get_num_queues(vdev); - int new_num_queues =3D new_max_queue_pairs * 2 + 1; int i; =20 assert(old_num_queues >=3D 3); @@ -3062,16 +3061,14 @@ static void virtio_net_set_multiqueue(VirtIONet *n,= int multiqueue) int max =3D multiqueue ? n->max_queue_pairs : 1; =20 n->multiqueue =3D multiqueue; - virtio_net_change_num_queue_pairs(n, max); + virtio_net_change_num_queues(n, max * 2 + 1); =20 virtio_net_set_queue_pairs(n); } =20 -static int virtio_net_pre_load_queues(VirtIODevice *vdev) +static int virtio_net_pre_load_queues(VirtIODevice *vdev, uint32_t n) { - virtio_net_set_multiqueue(VIRTIO_NET(vdev), - virtio_has_feature(vdev->guest_features, VIR= TIO_NET_F_RSS) || - virtio_has_feature(vdev->guest_features, VIR= TIO_NET_F_MQ)); + virtio_net_change_num_queues(VIRTIO_NET(vdev), n); =20 return 0; } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 82a285a31d..7e38b1ca97 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3270,13 +3270,6 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int ver= sion_id) config_len--; } =20 - if (vdc->pre_load_queues) { - ret =3D vdc->pre_load_queues(vdev); - if (ret) { - return ret; - } - } - num =3D qemu_get_be32(f); =20 if (num > VIRTIO_QUEUE_MAX) { @@ -3284,6 +3277,13 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int ver= sion_id) return -1; } =20 + if (vdc->pre_load_queues) { + ret =3D vdc->pre_load_queues(vdev, num); + if (ret) { + return ret; + } + } + for (i =3D 0; i < num; i++) { vdev->vq[i].vring.num =3D qemu_get_be32(f); if (k->has_variable_vring_alignment) { diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 214d4a77e9..c594764f23 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -210,8 +210,14 @@ struct VirtioDeviceClass { void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); int (*start_ioeventfd)(VirtIODevice *vdev); void (*stop_ioeventfd)(VirtIODevice *vdev); - /* Called before loading queues. Useful to add queues before loading. = */ - int (*pre_load_queues)(VirtIODevice *vdev); + /* + * Called before loading queues. + * If the number of queues change at runtime, use @n to know the + * number and add or remove queues accordingly. + * Note that this function is called in the middle of loading vmsd; + * no assumption should be made on states being loaded from vmsd. + */ + int (*pre_load_queues)(VirtIODevice *vdev, uint32_t n); /* Saving and loading of a device; trying to deprecate save/load * use vmsd for new devices. */ --=20 2.42.0 From nobody Sun Dec 14 02:06:19 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=1752471348; cv=none; d=zohomail.com; s=zohoarc; b=lKTtqid2EZeI/ow4x3+Fka4Kv/oGPbx+Upnyeed5MNdCx6qWKZt4HKIP1/0JAsQ6IGXWuS+RFxWSbb0qeSthAPavyJepnmnns3EJGehnwmLlzNk5gNRNq2IciMLomzifv1fzG1GvXj2O8VIJWjLf89t2VPcdGj4f9zVGb3xRcx4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471348; h=Content-Type: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=01NUvw0ZJlHXFkftpgQ5s2vtgM+qyaS0xCjJIBcuPOE=; b=ZsXBzJyICH7HcyMZTmHFnCRoy0EOZHs+PvL2EYNThcV7xjVIFVsZWL6g98qd/hugzDP56kjZOmPNlNkNgAIttjPt0jXJoJg6UP6K1wkM8DPWflHo/dFpiHao67lOZ0iSYlRzTHRNRvEg0X0nAejQObYPKWRXJDeg73w9MXdLDPE= 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 1752471347920314.96367605058003; Sun, 13 Jul 2025 22:35:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBpw-0001LP-Ux; Mon, 14 Jul 2025 01:34: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 1ubBpu-0001FG-MN for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:46 -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 1ubBpr-000371-VK for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:46 -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-217-4kC_lVloPUOwxn7NTuPFnw-1; Mon, 14 Jul 2025 01:34:41 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 77E9F1956080 for ; Mon, 14 Jul 2025 05:34:40 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2FD7B19560B3; Mon, 14 Jul 2025 05:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471283; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=01NUvw0ZJlHXFkftpgQ5s2vtgM+qyaS0xCjJIBcuPOE=; b=flG4KAhKBVdbub47n4I0y3xSwBU726xFFuHQp0gQHsUjqXVSMzJL2srL9fc6pgZ2IPu0uz OKk4N6GWTMsbPorkq0oGygsHv0jYETo8jeTMGRxYdNPQZxZXJe6XvktWFsBpi8yOveA2jM 6weoIo1Hnrn8o+7auQjICM/sSGkt4eA= X-MC-Unique: 4kC_lVloPUOwxn7NTuPFnw-1 X-Mimecast-MFC-AGG-ID: 4kC_lVloPUOwxn7NTuPFnw_1752471280 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 03/13] net: Refactor stream logic for reuse in '-net passt' Date: Mon, 14 Jul 2025 13:34:13 +0800 Message-ID: <20250714053423.10415-4-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471349222116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 bb97b4dcbe..bb3c011e5a 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 6152d2a05e..d893f02cab 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 0000000000..5af27e0d1d --- /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 0000000000..b868625665 --- /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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471352; cv=none; d=zohomail.com; s=zohoarc; b=AZtgiUKHLGpIByEl88HBy+MqFcSH6tAleHCHN5xnoJgV6dsOsq2mTJYbnnoC3BV8vrw8M4z7PzgPlAHKLkbiTUrwJo3y2BAyaqiwuN6Q8kfdMVBIDPLIfKI504r/ZNppRRbh+RNnc6Bq4Xg/oLnqlXQW5QyyDC8BBtqPF86tdqw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471352; h=Content-Type: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=8j2jAdERTAzzT+hAJO41i8nD2nVsFsy3T4/6QKXE/18=; b=cNrMMv+GjZGXbPddpvL4eTSqOXhwF6XbWgr0lBELhOSxPvac7F3MRGejcU1hxR5wUj92MQVRQih/fWZFPzIoGDQ3vqT2jsgQXeIq18p6gI16q6XDLPJNFkdUsoQRu7ueLIrFRcEn/iYw2f2JV4NIFRxBan+Z7QjhdzGN1mbFcPo= 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 1752471352330203.02910597122604; Sun, 13 Jul 2025 22:35:52 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBq4-0001X6-Qd; Mon, 14 Jul 2025 01:34:57 -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 1ubBpw-0001KC-EB for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:48 -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 1ubBpu-00037K-Nw for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:48 -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-657-TSAQvT3wMQee60K1aE9A0Q-1; Mon, 14 Jul 2025 01:34:44 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 2597419560AA for ; Mon, 14 Jul 2025 05:34:43 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 36D1D19560A3; Mon, 14 Jul 2025 05:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471285; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8j2jAdERTAzzT+hAJO41i8nD2nVsFsy3T4/6QKXE/18=; b=eiI3/TLe/LLoSg73nYMliad/ATkeQt8+n0WD5ar2OXf1j30FJ2KpKHx8OSkwQAqZnvEHR8 9rteGfAATj8BBGkZaQ83efdGzg7xIIAhyjCIskvxBap/9t8+8J1CFOpum4LwfzU84PoocJ gGbVaHbUfAdNfGGxfJO7LJ19REsmltw= X-MC-Unique: TSAQvT3wMQee60K1aE9A0Q-1 X-Mimecast-MFC-AGG-ID: TSAQvT3wMQee60K1aE9A0Q_1752471283 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 04/13] net: Define net_client_set_link() Date: Mon, 14 Jul 2025 13:34:14 +0800 Message-ID: <20250714053423.10415-5-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471352823116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 cdd5b109b0..ac59b593ba 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 39d6f28158..cfa2d8e958 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 0b235e50c6..10ac8dc0b3 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471335; cv=none; d=zohomail.com; s=zohoarc; b=ZZ82BGOBGpklnE8nS9pej1SF/RwEifPDXyVeWQSK94GN0T1LZ6IZSakMZ8tbQ3sTH5Jcm0TmXjb77alwUqxdeiPnzzkMyAUftJvp4HCz+epR/1V7RRzJJ1SHNmYYAhcj6U+N1YYZuuYbnGvdJ/WXFMkL7w9+Z5rfnjgdO3l0ryE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471335; h=Content-Type: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=laFMsXjPX7O68lbIAUeLXEKXJjWAGRkz3AA9ARpj9Ac=; b=KlTyOTgIXGjk7WBSGZeIxoJBFcqzLipMlYdxU/wlOohRb5AxX7vjTJGIYlAe/JQ1gn5RSZyJ+hlBoN3B+tiMT5V7bHD4P2u3268jcPnZTDUEaz1vXgeBiom2DjzbG2HPBx3D1SJrb3bZqlzn63JY0MOvEbJEu+6LYbEy10TdEkM= 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 1752471335471419.66093735727156; Sun, 13 Jul 2025 22:35:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBq9-0001bo-J7; Mon, 14 Jul 2025 01:35:01 -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 1ubBq1-0001XC-T6 for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:56 -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 1ubBq0-00037r-9E for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:53 -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-665-PFXaukU6NwmkM7cT5z5Mcg-1; Mon, 14 Jul 2025 01:34:46 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 1850519560AD for ; Mon, 14 Jul 2025 05:34:46 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 01FC419560A3; Mon, 14 Jul 2025 05:34:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471290; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=laFMsXjPX7O68lbIAUeLXEKXJjWAGRkz3AA9ARpj9Ac=; b=MJ9tM+pk6XrKBj4/ZtipFp67o5iDILKO6rFCudCRQVo3ygjLOasMsn+1DY7pN10gEfYhnG KMmsGTa4QrdN8lNsuZNx2jARYpw8QmkU5N/MxKydJL051N5IjaKhoZLmKDkhNqSyij9WL2 tYcDtRPo8qn00blRgj7V8HI5VRCD4eA= X-MC-Unique: PFXaukU6NwmkM7cT5z5Mcg-1 X-Mimecast-MFC-AGG-ID: PFXaukU6NwmkM7cT5z5Mcg_1752471286 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 05/13] vhost_net: Rename vhost_set_vring_enable() for clarity Date: Mon, 14 Jul 2025 13:34:15 +0800 Message-ID: <20250714053423.10415-6-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471336858116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 72df6d757e..7bed0bf92b 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 891f235a0a..cb87056397 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 351377c025..e3400f18c8 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 c6a5361a2a..0f40049f34 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471363; cv=none; d=zohomail.com; s=zohoarc; b=LZhmGYblbRDy2FHQ2MWa7OZTfgDjoKQHp0Lwo6aSaI5YxwJTCWTG4ApZzxwt5uCwXUZ5Vu9jZtVXBmebNmSvAmkAj/fQovg981d9ccoOaFBAxPyWGB8tX83ZoAMmK3yN1fXrOxHIDbGcH7+yredTUrU8D+BKxKODPm8qzajTdY8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471363; h=Content-Type: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=M8+fF7SH0OZ4mxMevN3C0CPeMRnFs+jK4vsOAwAbjhU=; b=IXt2/CkQp3dxs0JN4V0nQ+QiikafMCQE8GG1U9Ta2vA4g0hxPyOrGpPyYTjsqTSA2JPzKsuXdOS+qhoPdyqVi6q55xOndM6x8B/LwRFf3vqkMs7IR3IPm7+RqA2tsFKTDEdxIs2ep5KslAHff6j9DRmTMoUUcP0GkRuVxb6gRHA= 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 1752471363214795.204200725574; Sun, 13 Jul 2025 22:36:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqD-0001jG-UI; Mon, 14 Jul 2025 01:35:05 -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 1ubBq2-0001XD-3x for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:55 -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 1ubBq0-00037y-9B for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:53 -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-512-_6nMTaKAO2CA3ssMSerWqA-1; Mon, 14 Jul 2025 01:34:49 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 E7CE31800368 for ; Mon, 14 Jul 2025 05:34:48 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CD62E19560A3; Mon, 14 Jul 2025 05:34:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471291; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=M8+fF7SH0OZ4mxMevN3C0CPeMRnFs+jK4vsOAwAbjhU=; b=B3Z4F1s/bq/K/oATScMK7/F1581vbXl2T04SAhcS9atP21rbiGCJ15Dh7PZ/lXyurfVrSP qarGxJv2CCh6SWoZyt2NpYiRPYiOcD7cAoy3qdkW1HLtyvcE5y+BG3E+oVFgZdb4Ibb7xG dkFAJAFHmR77jMcP12Znn1Y/iZ0277o= X-MC-Unique: _6nMTaKAO2CA3ssMSerWqA-1 X-Mimecast-MFC-AGG-ID: _6nMTaKAO2CA3ssMSerWqA_1752471289 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 06/13] net: Add get_vhost_net callback to NetClientInfo Date: Mon, 14 Jul 2025 13:34:16 +0800 Message-ID: <20250714053423.10415-7-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471365357116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 cb87056397..db8b97b753 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 ac59b593ba..e67b375626 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 5d585515f9..6f34f13eae 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 35bf619709..0b233a2673 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 b81f9a6f2a..916ead3793 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 671dee970f..38baf90e0b 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 ae1c7e3983..4beba6d7a7 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 10ac8dc0b3..b7bf0d2042 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 58d738945d..0b86c917ed 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471409; cv=none; d=zohomail.com; s=zohoarc; b=ahsjMMB8LIwx+IF9UGEfDY2GmQHARUjOlib0JdPWwhFb5rNPL6QFg0L2grh6XB3pVwDjTPgD5ecBbwng9Q9bVmjHQdKBrLLRqEMLolDN7oY3Rncn3XJ4yk1WbN8p76wkB3MfmhGkV/G+VojiIk8R7DlOYgUTrE9+yrO/JnRVs/8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471409; h=Content-Type: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=apblGgxR/LIinQq+FfZt/vuCFJn9keINA6Xhovd5WeI=; b=N3Z3Vk5nNsYgBwUaHOGioMqN7ya8wK6SlqnO2z1zWXN0VIwoF32JVPC/gHAWTz1sTZBXEZnYcKyvzIZSLr+bqQrJSscB9PWQmRkgi+aTyO3QncE8vl/Y6mT1ZRjhnAgpkyetbusQataYLU4h9DGdcVnnPcVnYh8bZZffW7aocFk= 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 1752471409677753.7702128138759; Sun, 13 Jul 2025 22:36:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqK-0001rs-7w; Mon, 14 Jul 2025 01:35:12 -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 1ubBq5-0001Ym-1r for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:57 -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 1ubBq3-00038I-4Z for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:34:56 -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-441-Fcl4-dpFPcuifQplXUvXIw-1; Mon, 14 Jul 2025 01:34:52 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 AFE64195608E for ; Mon, 14 Jul 2025 05:34:51 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B2E1719560A3; Mon, 14 Jul 2025 05:34:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471294; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=apblGgxR/LIinQq+FfZt/vuCFJn9keINA6Xhovd5WeI=; b=ezsLUpbPIKHAdR1O/w8rqXlS4+lNk7h4Swb80JsaSFejSEscJaOOvcPIjYTzf2JhLRzrke 5OGn2JZGinz8T2b7JYh/XeppanfafXxQasV5NtOky6+Up6v1NRbuFn3I4ZI9aBJ4rWAzpw WkbwUKaxZULItf/g2O8vwKRoiIPkHPA= X-MC-Unique: Fcl4-dpFPcuifQplXUvXIw-1 X-Mimecast-MFC-AGG-ID: Fcl4-dpFPcuifQplXUvXIw_1752471291 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 07/13] net: Consolidate vhost feature bits into vhost_net structure Date: Mon, 14 Jul 2025 13:34:17 +0800 Message-ID: <20250714053423.10415-8-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471411858116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 db8b97b753..787c769ccc 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 38800a7156..6a75fdc021 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 916ead3793..f8d7d6c904 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 0f40049f34..fbed37385a 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 4beba6d7a7..a33eb23212 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 b7bf0d2042..bc8e82a092 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 0b86c917ed..cbbea0eb71 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471462; cv=none; d=zohomail.com; s=zohoarc; b=We/4KaZBnUXNStvX7TkNf8ZhzL335cfMKvSu2Df/TLKviTejO9rW2IB7djxcclIjYrHAh4JPHM0epME9kD77iM0cqmyezyFhbf6eMHM2wqgrMEjMfR6lxQWNsAfsccWRzRHwat5u5tU0i9CzkoVJ0dbfIyye6i+YVbX3drdNtD8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471462; h=Content-Type: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=t5V/l3Azbas7jiQylywA3mzzUCzgI0GaPktcMBeaTx0=; b=My4Gl91E/7Ngz8aa7BYzld+aiUB6u8nDOaYFj7GzCR937qI8l+lYTfeC1oMAOsKNKRSVRexfVAa0BgFNXlqUKp3SaN1qJhuyuoreY33/G/s2vHTUjd40z7bxId1oQDzKbgYIWGs6ipAdxx+p8wxhmJ/Wpsz3oS6A1TYOXRxEPBY= 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 1752471462621106.45402875205434; Sun, 13 Jul 2025 22:37:42 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqL-0001xE-KR; Mon, 14 Jul 2025 01:35:13 -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 1ubBqA-0001f1-4B for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:03 -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 1ubBq8-00038Y-D4 for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:01 -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-379-3B8Hk9UCPk-OebMZMPDjwQ-1; Mon, 14 Jul 2025 01:34:55 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 7571D19560B4 for ; Mon, 14 Jul 2025 05:34:54 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7041E19560A3; Mon, 14 Jul 2025 05:34:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471299; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t5V/l3Azbas7jiQylywA3mzzUCzgI0GaPktcMBeaTx0=; b=AxzuwscKIJlRUfFICC00/jhaYuO4ECSwtfWV0eZEZJrcxgxO2ijO+2q+mMiEB8tU9lRby3 aqzG4ThN+0dLPxEktySwYK1QqeqaHbVHP5CQesJhoM9XVUNjq101A4snei0CRmQAniQDeD gBdpop/RPlZhNEBFbVSk3J168EIYLjc= X-MC-Unique: 3B8Hk9UCPk-OebMZMPDjwQ-1 X-Mimecast-MFC-AGG-ID: 3B8Hk9UCPk-OebMZMPDjwQ_1752471294 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 08/13] net: Add get_acked_features callback to VhostNetOptions Date: Mon, 14 Jul 2025 13:34:18 +0800 Message-ID: <20250714053423.10415-9-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471464518116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 787c769ccc..fb169af0e8 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 0b233a2673..a4d0ce4b8d 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 fbed37385a..a8d281c8f7 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 a33eb23212..acd77f816f 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 bc8e82a092..93b413b49f 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 cbbea0eb71..a3980d1fb5 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471385; cv=none; d=zohomail.com; s=zohoarc; b=mHUPdzJWj15hBuRjAp5+7tcjsfRgiZuwiG71s8KKbyO4NaJMh/e+SiWBRRnq1aWngsJTvS+P4k7XL15d7zfCVTnQy4ED81rFqYvkLLwQhfNa+nTYMijPrVszC4Evishbx420CtFnM9tfPYqK1tf8120vQ5z6Tmgugy/59ua++Bw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471385; h=Content-Type: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=DT3HyA+iTPKd58MpBzGj1uOVAOgY7hfIfQe5e1fRid4=; b=Qdo3J5mjJiIogyvgHRosME3P+6BmPGvNwi9q8l6rEhpSdeIR8o8pdkNdfzXpAN4Ci/Nb32tkiPRecLl+WDwNRxJQb4rlI1coFEReGsKuzUDNmrsA+pBhQA606hSZJPCigQtN+SKBovHfjldNq70ph+FORwONaWaLxlT0C3lODDU= 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 1752471385639691.7150313162473; Sun, 13 Jul 2025 22:36:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqG-0001lf-So; Mon, 14 Jul 2025 01:35:08 -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 1ubBqA-0001f9-CJ for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:03 -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 1ubBq8-00038a-H7 for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:02 -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-656-ZxDbGg_zMvK2TuRpQxxFiA-1; Mon, 14 Jul 2025 01:34:57 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 3325119560AA for ; Mon, 14 Jul 2025 05:34:57 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3ACC819560A3; Mon, 14 Jul 2025 05:34:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471300; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DT3HyA+iTPKd58MpBzGj1uOVAOgY7hfIfQe5e1fRid4=; b=hNousxvry9rSo0Q4woJCrVJaIn1EoB8yrw1NURB+mxJ1/qK48PFn8XV61tvIeRjOFGlm/L vVNQ31Nf75iUaYlTQpFMdm+2AZHhANhbXreJFjp9gbfOjT6EDVfwA5WKZeot4mo5cWuenq 9NJjOAFXxiqmmjFtHa5a4Bfy12s4oa4= X-MC-Unique: ZxDbGg_zMvK2TuRpQxxFiA-1 X-Mimecast-MFC-AGG-ID: ZxDbGg_zMvK2TuRpQxxFiA_1752471297 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 09/13] net: Add save_acked_features callback to vhost_net Date: Mon, 14 Jul 2025 13:34:19 +0800 Message-ID: <20250714053423.10415-10-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471387429116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 7bed0bf92b..7d49f82906 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 fb169af0e8..976d2b315a 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 6a75fdc021..b0830bac79 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 a4d0ce4b8d..0000000000 --- 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 a8d281c8f7..eb26ed9bdc 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 acd77f816f..79fa02a65c 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 52ab4e13f1..283dee87db 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 93b413b49f..8a3df27b02 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 a3980d1fb5..c63225d3d2 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471394; cv=none; d=zohomail.com; s=zohoarc; b=aRwZKI310STp3OlKDZEQWBP9ppS8iO8iA8f2hZRGsLmz9v/16VpnAQfFZjMuhjYo4/RVKEtcjsbgFxeu2Y5fLbDy++B7I16iNICOGczBl2xO+Tz0SwqPNemOLwsbLauA3hWV4UCLkVCuvDChK0pV0si+em66Ft3pCr/cZekrfrs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471394; h=Content-Type: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=m+YvooSYZgdxo1YSHG8Ogjlc2B/r4R8Tf/zQP9kdvCs=; b=Ja/D1WmjSXzMhvERm9hzJcEy4OKleNK3MBlCdl09OGWvXuRFsPszMr9f7rLpv2I6eAfUYGWSQBvaN5DI/+ihOtt9AL8Fc/bzjBjTmLPnyxH4RzQjNz5VQ9UQd2QoVhAwsARlfMZwwE6may7/EpsgCjqVglCSHSP7ka9wMqSwvEM= 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 175247139431914.994675329611482; Sun, 13 Jul 2025 22:36:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqK-0001tH-Pk; Mon, 14 Jul 2025 01:35:12 -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 1ubBqD-0001jh-Pi for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:05 -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 1ubBqC-00039C-0w for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:05 -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-27-QP4UQ8omNy-B71opC0ypGQ-1; Mon, 14 Jul 2025 01:35:00 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 3468A19560AA for ; Mon, 14 Jul 2025 05:35:00 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 08F2819560A3; Mon, 14 Jul 2025 05:34:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471303; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=m+YvooSYZgdxo1YSHG8Ogjlc2B/r4R8Tf/zQP9kdvCs=; b=P7amEbwUj5Re5HRQaifJARvs/hez1hns0fPMd8eZfzfCWxE1/COn/Q9Y6jqV9P63riADVo olFicy5FNS64mSmYjkzU3AQ5vaKgMOtfmMpk96r3e0bgGbK3opBtbayjrLm4dAMYRLak+I GOCbrlZMGBH73eCMlop2iNs9iMvbYd8= X-MC-Unique: QP4UQ8omNy-B71opC0ypGQ-1 X-Mimecast-MFC-AGG-ID: QP4UQ8omNy-B71opC0ypGQ_1752471300 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 10/13] net: Allow network backends to advertise max TX queue size Date: Mon, 14 Jul 2025 13:34:20 +0800 Message-ID: <20250714053423.10415-11-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471395276116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 976d2b315a..74d2e3ed90 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 e3400f18c8..39fc280839 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 b0830bac79..a62992c819 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 eb26ed9bdc..8f4fddfb69 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 79fa02a65c..2f0cb55c9a 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 8a3df27b02..bf892915de 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 c63225d3d2..353392b3d7 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471384; cv=none; d=zohomail.com; s=zohoarc; b=OERGgUm3cOJzNq4m9zg321EkrPrAm0liorUbzt08xu52oY57yUZ7n2GAqR9qwyQTQMqClxHd4ivSA+aewxLz/1OBD4RvpmcWdQRKzekrLnpKojZ9jQNEfcbt46Kib3axipkzlTGekqE3nfSM4NIgL5SoejQQZ1fmSl0thhP5uro= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471384; h=Content-Type: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=tQv5wmeY0GaWezx9NXctHKJ6I7SkofkcbyXSQD2bNxc=; b=J7cNxUzRh2b3vorCUOpWe7u+CvRyI6H7//PZ5xmnsr2xn0TimC4tofimyrVpKb+SJU/gW1nvbKhqMiyRxNQbTPn7vNtHv5UUctwkLc1PE3MxlHi6z9CN9n8YMe+LyFJmO3jexRcqF5S2s2TrQmUf14I9IIrAybDLvFyrWfsVVM0= 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 175247138473166.32275074388372; Sun, 13 Jul 2025 22:36:24 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqM-00021U-Nf; Mon, 14 Jul 2025 01:35:14 -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 1ubBqG-0001m7-RZ for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:08 -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 1ubBqE-00039j-HU for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:08 -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-680-gswrU8e7OUe86gqquJbFpA-1; Mon, 14 Jul 2025 01:35:03 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 0CF4318011EF for ; Mon, 14 Jul 2025 05:35:03 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id ED26A19560A3; Mon, 14 Jul 2025 05:35:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471305; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tQv5wmeY0GaWezx9NXctHKJ6I7SkofkcbyXSQD2bNxc=; b=CM/GR2jXfIyWB6SgQ1DYhwBEqzaUaM/j4LtfcT2tznbGuvplWHbkSIhTMbl9TLaN7un8yg 6IB9iuA/lt0O7LoSqHRK9IX7R8tyxCZPtq27IzTwstiXA77+sdS5tMkY/dj7jR9GwlU2sC uHTqTR84/fxROZoOIs9umIu64z6ruwE= X-MC-Unique: gswrU8e7OUe86gqquJbFpA-1 X-Mimecast-MFC-AGG-ID: gswrU8e7OUe86gqquJbFpA_1752471303 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 11/13] net: Add is_vhost_user flag to vhost_net struct Date: Mon, 14 Jul 2025 13:34:21 +0800 Message-ID: <20250714053423.10415-12-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471395442116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 74d2e3ed90..540492b37d 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 39fc280839..00df5fd6cd 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 a62992c819..f178cf9e1d 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 8f4fddfb69..879781dad7 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 2f0cb55c9a..23536c09b4 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 bf892915de..1c3b8b36f3 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 353392b3d7..943e9c585c 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471407; cv=none; d=zohomail.com; s=zohoarc; b=LlIACuiYFDFdAWhyeJrYozQU3wUHFRUcIGxsnDtLBVXj7GNKQUP6mceWjufb2anLa/XIaixvqpFCCjrtFrU/IKqcPYfaLjMmrI/6bCvp9mZIZfB5/w5sguzCTbO7RxMtu1cXAUdIi2wSIWaqy2wqVw++qbPY31ok39nPCr+uP5s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471407; h=Content-Type: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=B5iq3qsfCDAZaD5pZTO5DVYweQHF21wDsk5wz5whWyU=; b=O5sAFYUGFPr1F2zCsnbsO9aKANdvAdPLNG1KKFFxt+og0EdjnwQn9N00xOq1OwiwSOeERg11xaH+qA627TO9pMMXA4RrtQNU6QAICNpmbKbhAf7QjqCkHyKTNU4slSjYpjDkb1Ej89LE0uQ3sS0i4vyid+Og1EFW/PduoPg9Anc= 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 1752471407244580.9843025958456; Sun, 13 Jul 2025 22:36:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqN-00025S-J1; Mon, 14 Jul 2025 01:35:15 -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 1ubBqL-0001yR-SF for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:13 -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 1ubBqI-0003AP-Bt for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:13 -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-22-l_MXXDWeOuuTG4snK15aUA-1; Mon, 14 Jul 2025 01:35:06 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 D1B5619560AA for ; Mon, 14 Jul 2025 05:35:05 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D539719560A3; Mon, 14 Jul 2025 05:35:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B5iq3qsfCDAZaD5pZTO5DVYweQHF21wDsk5wz5whWyU=; b=enVwMvkqmZvCo9kLm5EXNxSJiLpw6amo+mSuWxI3lT4CQ+2Z3l2MJzVjVSBPooaLr12gBa vkZHUtLBMVFG31Bf9jN9gdJ+AGHXgZF1iii0XPCA1Hzch8oU7myatCbnhx7Ur0Xy7dXT+z vEwiV4uqMb9y4uSY67+pOymLTCYU2rw= X-MC-Unique: l_MXXDWeOuuTG4snK15aUA-1 X-Mimecast-MFC-AGG-ID: l_MXXDWeOuuTG4snK15aUA_1752471305 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 12/13] net: Add passt network backend Date: Mon, 14 Jul 2025 13:34:22 +0800 Message-ID: <20250714053423.10415-13-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471409482116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- 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 | 407 ++++++++++++++++++++++++++++++++++ qapi/net.json | 115 ++++++++++ qemu-options.hx | 145 +++++++++++- scripts/meson-buildoptions.sh | 3 + 12 files changed, 731 insertions(+), 4 deletions(-) create mode 100644 net/passt.c diff --git a/docs/system/devices/net.rst b/docs/system/devices/net.rst index a3efbdcabd..c586ee0f40 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,tcp-ports=3D10001,udp= -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 06746f0afc..d0e4f35a30 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 b5f74aa37a..2adb22f198 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') @@ -4926,6 +4931,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 a442be2995..3146eec194 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 be53794582..e786ab4203 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 cba20ebd87..e3b58b1c4f 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 bb3c011e5a..da6ea635e9 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 cfa2d8e958..90f69fdf39 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 0000000000..0a4a1ba6aa --- /dev/null +++ b/net/passt.c @@ -0,0 +1,407 @@ +/* + * 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_mtu) { + g_ptr_array_add(args, g_strdup("--mtu")); + g_ptr_array_add(args, g_strdup_printf("%"PRId64, passt->mtu)); + } + + if (passt->address) { + g_ptr_array_add(args, g_strdup("--address")); + g_ptr_array_add(args, g_strdup(passt->address)); + } + + if (passt->netmask) { + g_ptr_array_add(args, g_strdup("--netmask")); + g_ptr_array_add(args, g_strdup(passt->netmask)); + } + + if (passt->mac) { + g_ptr_array_add(args, g_strdup("--mac-addr")); + g_ptr_array_add(args, g_strdup(passt->mac)); + } + + if (passt->gateway) { + g_ptr_array_add(args, g_strdup("--gateway")); + g_ptr_array_add(args, g_strdup(passt->gateway)); + } + + if (passt->interface) { + g_ptr_array_add(args, g_strdup("--interface")); + g_ptr_array_add(args, g_strdup(passt->interface)); + } + + if (passt->outbound) { + g_ptr_array_add(args, g_strdup("--outbound")); + g_ptr_array_add(args, g_strdup(passt->outbound)); + } + + if (passt->outbound_if4) { + g_ptr_array_add(args, g_strdup("--outbound-if4")); + g_ptr_array_add(args, g_strdup(passt->outbound_if4)); + } + + if (passt->outbound_if6) { + g_ptr_array_add(args, g_strdup("--outbound-if6")); + g_ptr_array_add(args, g_strdup(passt->outbound_if6)); + } + + if (passt->dns) { + g_ptr_array_add(args, g_strdup("--dns")); + g_ptr_array_add(args, g_strdup(passt->dns)); + } + if (passt->fqdn) { + g_ptr_array_add(args, g_strdup("--fqdn")); + g_ptr_array_add(args, g_strdup(passt->fqdn)); + } + + if (passt->has_dhcp_dns && !passt->dhcp_dns) { + g_ptr_array_add(args, g_strdup("--no-dhcp-dns")); + } + + if (passt->has_dhcp_search && !passt->dhcp_search) { + g_ptr_array_add(args, g_strdup("--no-dhcp-search")); + } + + if (passt->map_host_loopback) { + g_ptr_array_add(args, g_strdup("--map-host-loopback")); + g_ptr_array_add(args, g_strdup(passt->map_host_loopback)); + } + + if (passt->map_guest_addr) { + g_ptr_array_add(args, g_strdup("--map-guest-addr")); + g_ptr_array_add(args, g_strdup(passt->map_guest_addr)); + } + + if (passt->dns_forward) { + g_ptr_array_add(args, g_strdup("--dns-forward")); + g_ptr_array_add(args, g_strdup(passt->dns_forward)); + } + + if (passt->dns_host) { + g_ptr_array_add(args, g_strdup("--dns-host")); + g_ptr_array_add(args, g_strdup(passt->dns_host)); + } + + if (passt->has_tcp && !passt->tcp) { + g_ptr_array_add(args, g_strdup("--no-tcp")); + } + + if (passt->has_udp && !passt->udp) { + g_ptr_array_add(args, g_strdup("--no-udp")); + } + + if (passt->has_icmp && !passt->icmp) { + g_ptr_array_add(args, g_strdup("--no-icmp")); + } + + if (passt->has_dhcp && !passt->dhcp) { + g_ptr_array_add(args, g_strdup("--no-dhcp")); + } + + if (passt->has_ndp && !passt->ndp) { + g_ptr_array_add(args, g_strdup("--no-ndp")); + } + if (passt->has_dhcpv6 && !passt->dhcpv6) { + g_ptr_array_add(args, g_strdup("--no-dhcpv6")); + } + + if (passt->has_ra && !passt->ra) { + g_ptr_array_add(args, g_strdup("--no-ra")); + } + + if (passt->has_freebind && passt->freebind) { + g_ptr_array_add(args, g_strdup("--freebind")); + } + + if (passt->has_ipv4 && !passt->ipv4) { + g_ptr_array_add(args, g_strdup("--ipv6-only")); + } + + if (passt->has_ipv6 && !passt->ipv6) { + g_ptr_array_add(args, g_strdup("--ipv4-only")); + } + + if (passt->has_search && passt->search) { + const StringList *list =3D passt->search; + GString *domains =3D g_string_new(list->value->str); + + list =3D list->next; + while (list) { + g_string_append(domains, " "); + g_string_append(domains, list->value->str); + list =3D list->next; + } + + g_ptr_array_add(args, g_strdup("--search")); + g_ptr_array_add(args, g_string_free(domains, FALSE)); + } + + if (passt->has_tcp_ports && passt->tcp_ports) { + const StringList *list =3D passt->tcp_ports; + GString *tcp_ports =3D g_string_new(list->value->str); + + list =3D list->next; + while (list) { + g_string_append(tcp_ports, ","); + g_string_append(tcp_ports, list->value->str); + list =3D list->next; + } + + g_ptr_array_add(args, g_strdup("--tcp-ports")); + g_ptr_array_add(args, g_string_free(tcp_ports, FALSE)); + } + + if (passt->has_udp_ports && passt->udp_ports) { + const StringList *list =3D passt->udp_ports; + GString *udp_ports =3D g_string_new(list->value->str); + + list =3D list->next; + while (list) { + g_string_append(udp_ports, ","); + g_string_append(udp_ports, list->value->str); + list =3D list->next; + } + + g_ptr_array_add(args, g_strdup("--udp-ports")); + g_ptr_array_add(args, g_string_free(udp_ports, FALSE)); + } + + 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 97ea183981..24999f6752 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -112,6 +112,116 @@ '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') +# +# @mtu: assign MTU via DHCP/NDP +# +# @address: IPv4 or IPv6 address +# +# @netmask: IPv4 mask +# +# @mac: source MAC address +# +# @gateway: IPv4 or IPv6 address as gateway +# +# @interface: interface for addresses and routes +# +# @outbound: bind to address as outbound source +# +# @outbound-if4: bind to outbound interface for IPv4 +# +# @outbound-if6: bind to outbound interface for IPv6 +# +# @dns: IPv4 or IPv6 address as DNS +# +# @search: search domains +# +# @fqdn: FQDN to configure client with +# +# @dhcp-dns: enable/disable DNS list in DHCP/DHCPv6/NDP +# +# @dhcp-search: enable/disable list in DHCP/DHCPv6/NDP +# +# @map-host-loopback: addresse to refer to host +# +# @map-guest-addr: addr to translate to guest's address +# +# @dns-forward: forward DNS queries sent to +# +# @dns-host: host nameserver to direct queries to +# +# @tcp: enable/disable TCP +# +# @udp: enable/disable UDP +# +# @icmp: enable/disable ICMP +# +# @dhcp: enable/disable DHCP +# +# @ndp: enable/disable NDP +# +# @dhcpv6: enable/disable DHCPv6 +# +# @ra: enable/disable route advertisements +# +# @freebind: bind to any address for forwarding +# +# @ipv4: enable/disable IPv4 +# +# @ipv6: enable/disable IPv6 +# +# @tcp-ports: TCP ports to forward +# +# @udp-ports: UDP ports to forward +# +# @param: parameter to pass to passt command +# +# Since: 10.1 +## +{ 'struct': 'NetDevPasstOptions', + 'data': { + '*path': 'str', + '*quiet': 'bool', + '*mtu': 'int', + '*address': 'str', + '*netmask': 'str', + '*mac': 'str', + '*gateway': 'str', + '*interface': 'str', + '*outbound': 'str', + '*outbound-if4': 'str', + '*outbound-if6': 'str', + '*dns': 'str', + '*search': ['String'], + '*fqdn': 'str', + '*dhcp-dns': 'bool', + '*dhcp-search': 'bool', + '*map-host-loopback': 'str', + '*map-guest-addr': 'str', + '*dns-forward': 'str', + '*dns-host': 'str', + '*tcp': 'bool', + '*udp': 'bool', + '*icmp': 'bool', + '*dhcp': 'bool', + '*ndp': 'bool', + '*dhcpv6': 'bool', + '*ra': 'bool', + '*freebind': 'bool', + '*ipv4': 'bool', + '*ipv6': 'bool', + '*tcp-ports': ['String'], + '*udp-ports': ['String'], + '*param': ['String'] }, + 'if': 'CONFIG_PASST' } + ## # @NetdevUserOptions: # @@ -729,12 +839,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 +869,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 1f862b19a6..e8252cd5e8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2796,6 +2796,24 @@ DEFHEADING() DEFHEADING(Network options:) =20 DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, +#ifdef CONFIG_PASST + "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off]\n" + "[,mtu=3Dmtu][,address=3Daddr][,netmask=3Dmask][,mac=3Daddr][,gateway= =3Daddr]\n" + " [,interface=3Dname][,outbound=3Daddress][,outbound-if4=3Dna= me]\n" + " [,outbound-if6=3Dname][,dns=3Daddr][,search=3Dlist][,fqdn= =3Dname]\n" + " [,dhcp-dns=3Don|off][,dhcp-search=3Don|off][,map-host-loopb= ack=3Daddr]\n" + " [,map-guest-addr=3Daddr][,dns-forward=3Daddr][,dns-host=3Da= ddr]\n" + " [,tcp=3Don|off][,udp=3Don|off][,icmp=3Don|off][,dhcp=3Don|o= ff]\n" + " [,ndp=3Don|off][,dhcpv6=3Don|off][,ra=3Don|off][,freebind= =3Don|off]\n" + " [,ipv4=3Don|off][,ipv6=3Don|off][,tcp-ports=3Dspec][,udp-po= rts=3Dspec]\n" + " [,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" + " for details on other options, refer to passt(1)\n" + " 'param' allows to pass any option defined by passt(1)= \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 +2970,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 +3005,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 +3029,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 +3051,123 @@ 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. + + ``@mtu`` + Assign MTU via DHCP/NDP + + ``address`` + IPv4 or IPv6 address + + ``netmask`` + IPv4 mask + + ``mac`` + source MAC address + + ``gateway`` + IPv4 or IPv6 address as gateway + + ``interface`` + Interface for addresses and routes + + ``outbound`` + Bind to address as outbound source + + ``outbound-if4`` + Bind to outbound interface for IPv4 + + ``outbound-if6`` + Bind to outbound interface for IPv6 + + ``dns`` + IPv4 or IPv6 address as DNS + + ``search`` + Search domains + + ``fqdn`` + FQDN to configure client with + + ``dhcp-dns`` + Enable/disable DNS list in DHCP/DHCPv6/NDP + + ``dhcp-search`` + Enable/disable list in DHCP/DHCPv6/NDP + + ``map-host-loopback`` + Addresse to refer to host + + ``map-guest-addr`` + Addr to translate to guest's address + + ``dns-forward`` + Forward DNS queries sent to + + ``dns-host`` + Host nameserver to direct queries to + + ``tcp`` + Enable/disable TCP + + ``udp`` + Enable/disable UDP + + ``icmp`` + Enable/disable ICMP + + ``dhcp`` + Enable/disable DHCP + + ``ndp`` + Enable/disable NDP + + ``dhcpv6`` + Enable/disable DHCPv6 + + ``ra`` + Enable/disable route advertisements + + ``freebind`` + Bind to any address for forwarding + + ``ipv4`` + Enable/disable IPv4 + + ``ipv6`` + Enable/disable IPv6 + + ``tcp-ports`` + TCP ports to forward + + ``udp-ports`` + UDP ports to forward + + ``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 ``--trace --log=3Dtrace.log``: + + .. parsed-literal:: + + |qemu_system| -nic passt,param=3D--trace,param=3D--log=3Dtrace.log + ``-netdev user,id=3Did[,option][,option][,...]`` Configure user mode host network backend which requires no administrator privilege to run. Valid options are: @@ -3711,7 +3852,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 73e0770f42..bb3e34d852 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.42.0 From nobody Sun Dec 14 02:06:19 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=1752471437; cv=none; d=zohomail.com; s=zohoarc; b=oCdkNq7AGxKYe5Z4I/C3i23gwqXUbfukMtQY1XSoTMvjyhvemuLLjyc+vNiVPzVbiHaHcx4nNtdycj/T2iPdkXPAfexbt4KVTxe11EhaFhyFrdgEhANWi+icloAvOWT8vOQQHYylw9sSW7iIHsIUe9vnBMxuGzYH00MyiTg19jc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752471437; h=Content-Type: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=LdiPW3wvLdAwBJP9AfH96pQgfA4+CWfpXQpvVGOOuyA=; b=IkHDuWOJ2/3c97EUHFcBXKF7I+jtBbThns6HtMKbDrtsUuS7ieKIx350d81bqOLtjKVpwhWmlYPoU8+cNBzYCS0D9WElNVtKYZ9Zexv5PhTEB1C1/SE+wvudWP8NoqqHdoh1bQnwjl0+t2+F5G389xJtBuV0zYfpxBdujwNiTG0= 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 1752471437206224.6993328383004; Sun, 13 Jul 2025 22:37:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubBqY-0002bt-I6; Mon, 14 Jul 2025 01:35:26 -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 1ubBqN-00023W-3K for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:15 -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 1ubBqK-0003Bf-If for qemu-devel@nongnu.org; Mon, 14 Jul 2025 01:35:14 -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-65-r8v9PKJaMDKD9-v_e95Acw-1; Mon, 14 Jul 2025 01:35:09 -0400 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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 903821800343 for ; Mon, 14 Jul 2025 05:35:08 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.55]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9BDC919560A3; Mon, 14 Jul 2025 05:35:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752471311; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LdiPW3wvLdAwBJP9AfH96pQgfA4+CWfpXQpvVGOOuyA=; b=Z4k2YlAsQfu6pNvUpjcQ0ubFx3ccEqO35Q1Um875uwUE6pV0e3gUWvuahjsrsomN6/K/+T d4TPNi+/TdqedEBw3ZdGXUUo0QJqYyL/fmxKyDTBQWiACTCaaySmNAWW/s4r2Xl/BrnN2s GFW2ky4pNNdXzxfg5zJdVWodlfPtbuU= X-MC-Unique: r8v9PKJaMDKD9-v_e95Acw-1 X-Mimecast-MFC-AGG-ID: r8v9PKJaMDKD9-v_e95Acw_1752471308 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL 13/13] net/passt: Implement vhost-user backend support Date: Mon, 14 Jul 2025 13:34:23 +0800 Message-ID: <20250714053423.10415-14-jasowang@redhat.com> In-Reply-To: <20250714053423.10415-1-jasowang@redhat.com> References: <20250714053423.10415-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 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=jasowang@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_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_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: 1752471438158116600 Content-Type: text/plain; charset="utf-8" From: Laurent Vivier 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 Signed-off-by: Jason Wang --- docs/system/devices/net.rst | 12 +- net/passt.c | 346 ++++++++++++++++++++++++++++++++++++ qapi/net.json | 3 + qemu-options.hx | 10 +- 4 files changed, 369 insertions(+), 2 deletions(-) diff --git a/docs/system/devices/net.rst b/docs/system/devices/net.rst index c586ee0f40..4d787c3aeb 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 0a4a1ba6aa..6f616ba3c2 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")); @@ -398,6 +735,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 24999f6752..0f766041a3 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 +# # @mtu: assign MTU via DHCP/NDP # # @address: IPv4 or IPv6 address @@ -189,6 +191,7 @@ 'data': { '*path': 'str', '*quiet': 'bool', + '*vhost-user': 'bool', '*mtu': 'int', '*address': 'str', '*netmask': 'str', diff --git a/qemu-options.hx b/qemu-options.hx index e8252cd5e8..a3c066c678 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2797,7 +2797,7 @@ DEFHEADING(Network options:) =20 DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_PASST - "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off]\n" + "-netdev passt,id=3Dstr[,path=3Dfile][,quiet=3Don|off][,vhost-user=3Do= n|off]\n" "[,mtu=3Dmtu][,address=3Daddr][,netmask=3Dmask][,mac=3Daddr][,gateway= =3Daddr]\n" " [,interface=3Dname][,outbound=3Daddress][,outbound-if4=3Dna= me]\n" " [,outbound-if6=3Dname][,dns=3Daddr][,search=3Dlist][,fqdn= =3Dname]\n" @@ -2811,6 +2811,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " 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" " for details on other options, refer to passt(1)\n" " 'param' allows to pass any option defined by passt(1)= \n" #endif @@ -3067,6 +3069,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. + ``@mtu`` Assign MTU via DHCP/NDP =20 --=20 2.42.0