From nobody Sat Nov 15 10:52:52 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=1752554530; cv=none; d=zohomail.com; s=zohoarc; b=g+7pJDa5lYDuuk6HrkEbLlfFhVNjWq6EGv+zp4zOsU2+qNZmTsG3UC90OnnuHJjviQbOsaYZBMKsja8Q0yssKkofSpcQcPy3HEEdUTQRaRdv0wvNlyAj3eBf39mw5l25matu4T6b07E/9Gi0kExZAidhwKba2/RKaetO/pzBkxA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554530; 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=fw8nHTwWtRr9QMC/kHyRJc7TdVh7lijrg5VsDstCi8lSacEDNTdk8TAlvxHQhWRu4cEhL6qWNUZ7TRITKB5kH0X2gw45yFoTcU48m9A0FHlV3iZ8JiZ6YPgPwXY2wyL4ZFrgHU1J6ZEOjSj+ZMeC2TLhvprPqAEjQQ3M7dcyHVU= 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 1752554530531340.0705971747989; Mon, 14 Jul 2025 21:42:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPI-0001rK-TA; Tue, 15 Jul 2025 00:36: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 1ubXOH-0001IA-HN for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:42 -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 1ubXOF-0005yX-Mf for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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-541-67LQGCXROf68Xra4YuJIgw-1; Tue, 15 Jul 2025 00:35:35 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 D36541800289; Tue, 15 Jul 2025 04:35:33 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E74511977029; Tue, 15 Jul 2025 04:35:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554138; 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=eHs606nD+7gyLjXNwhLxeGqVs6KWSL54Ut7yAld5fJFooEVTVvauPDWtiSm6G9yIsxQJ3T /W4DskHlbxX1rW9N9PRAV/gDp7tVgZ9dx4KthImYDiZ5rOI9V9SbgTd8LpU6wLLutl2X2S KmMfB7h+DzGxv4CUR/4ThdB8tGlKT9c= X-MC-Unique: 67LQGCXROf68Xra4YuJIgw-1 X-Mimecast-MFC-AGG-ID: 67LQGCXROf68Xra4YuJIgw_1752554134 From: Jason Wang To: qemu-devel@nongnu.org Cc: Anastasia Belova , qemu-stable@nongnu.org, Ilya Maximets , Jason Wang Subject: [PULL V2 01/16] net: fix buffer overflow in af_xdp_umem_create() Date: Tue, 15 Jul 2025 12:35:09 +0800 Message-ID: <20250715043524.21719-2-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: 1752554532524116600 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 Sat Nov 15 10:52:52 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=1752554240; cv=none; d=zohomail.com; s=zohoarc; b=LhLSzEtMFgSEVepDhEGIrnZHABk44bS0fw7VPfflBoLRLBMCz64Nh3koVGbBLH9qxXpMZPkJLGW4Bdk/jwlKmvpnn7E1oFxmjKPux4jwbG1221hYPCj8lXXvzsIkdgSdHRCMfBwHzkhJSI/Gy20WA7YcdJYHMl2iE8J+MsYR0gw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554240; 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=DTgnLFuekaJdr4vjpDTHP1XxFY5gi0AYZSht4rmsq3BpnFNIOY2k0FgpKpYMZCKYL6pd5/WNi8fetrbP1shbL6SHC1UriXADmYcRKXOufi7xYhS4HSQLoCB7IA76xeS2aT4Ne1xpf3DgLKaxebh53clycvawCxPJ5PK5SCS7+Os= 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 1752554240878431.8996154731018; Mon, 14 Jul 2025 21:37:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPM-0001tf-G6; Tue, 15 Jul 2025 00:36: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 1ubXOL-0001K8-2u for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:45 -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 1ubXOJ-0005zL-1l for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:44 -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-618-1u7LW3FBOymmOLJB2bMHoQ-1; Tue, 15 Jul 2025 00:35:38 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 852C818002E4; Tue, 15 Jul 2025 04:35:37 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 92EF21977000; Tue, 15 Jul 2025 04:35:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554142; 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=Tzb1lSwyt8Mwl3iqScY/RxHMYThjrr1d3ZZUKTJpf3DBVTzqpQ7XOAZx0qmFt6pPAU4QPr lKB3lBow++q8y83XFAK9cTblqGOrqo3fsFrHq7FQ3Y7ieGaBX70h3lLlUsrTxjOr2Uqryi JfL4RWeDXla9qbMQbefO7mWoXjzrA2U= X-MC-Unique: 1u7LW3FBOymmOLJB2bMHoQ-1 X-Mimecast-MFC-AGG-ID: 1u7LW3FBOymmOLJB2bMHoQ_1752554137 From: Jason Wang To: qemu-devel@nongnu.org Cc: Akihiko Odaki , Lei Yang , qemu-stable@nongnu.org, Jason Wang Subject: [PULL V2 02/16] virtio-net: Add queues for RSS during migration Date: Tue, 15 Jul 2025 12:35:10 +0800 Message-ID: <20250715043524.21719-3-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: 1752554241983116600 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 Sat Nov 15 10:52:52 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=1752554264; cv=none; d=zohomail.com; s=zohoarc; b=RF4fkJxBcN7BUZAQaExpMsqMZ9xFhB6pKB3TxEYj+ljiNK/hvmNC0lv+mWrZXqkM9oaGBdp/mKpwxx/pMmeUNI/jc4fLpulNU4YsOaYXVpYEXeR1WyNOt6/dNLUJZqBh/wDypvvihaEs0YtRJ3WVWit399YQQYB9V3y5UGUMRE0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554264; 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=D7vaVhf7K5PirCqwxG0gOYBF1z9sLle3dFihfYiZXK5ZN5xxlVzxTMZBoH1xp4J/uUAUOuRkqm5VwMc5DOhLym4s4LLfP9VGbX51S0UduohOGS6iCIl82e5IRGY1rDlYMiXAVFgILaPepwiIGM85Lq9+uYUVxkD62+nHYF8a+ZQ= 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 1752554264235466.22706751023384; Mon, 14 Jul 2025 21:37:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPK-0001s9-1i; Tue, 15 Jul 2025 00:36:46 -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 1ubXOO-0001MB-IM for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:52 -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 1ubXOL-0005zn-8t for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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-370-a9Nux4TDMiauThWqUJw3Cg-1; Tue, 15 Jul 2025 00:35:41 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 6A6CF19560B6 for ; Tue, 15 Jul 2025 04:35:40 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6E12A1977000; Tue, 15 Jul 2025 04:35:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554144; 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=ZLQJyzeW/p0Mx73pWd09iZxjDvoh7pq5IxE8ZndPZ6jKcekyp2u2s+B1JKrFn9tVkfkGTR RsnT+YB0X9mfHG1kaqb0422iGQ2YpfzSNorL2a4MivWc1XaLVmrZ3Mva5Vqjqc9L3vxYiG q0OKfFgMjqzhHvICatalxaWuXVf9qEw= X-MC-Unique: a9Nux4TDMiauThWqUJw3Cg-1 X-Mimecast-MFC-AGG-ID: a9Nux4TDMiauThWqUJw3Cg_1752554140 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 03/16] net: Refactor stream logic for reuse in '-net passt' Date: Tue, 15 Jul 2025 12:35:11 +0800 Message-ID: <20250715043524.21719-4-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554265980116600 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 Sat Nov 15 10:52:52 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=1752554352; cv=none; d=zohomail.com; s=zohoarc; b=nsytxUGe6BoiIvBasYVMU5thL6GCNaQ63zW8TLNh8cizg/vsodJvmL29IUaY4E+r2NR0vZCq/fCEteaSiHJJLo2L0HWKR5vSwbZ3jsdMR4KNnCxMaLn4lW4bbLjH9EeEdqKV7XjREN16ziX9naVB8JZZACUdry5JpIUeLRSMlt4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554352; 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=ZbLAlO2Vb0QsjWxWaHA7gQDoM7Lr6xJco/iYpDGbd4gSqFJEY7hpPwGCqNTxzxH6VA0JEfKiumv2sC8NOBG1NMQZIU/NWyHhnrp4xEqa85zr86OGTqWcyc+T6HXvcsi8FspDBRZ/lH/hBm9eP70V/Ht17zQ1FnpWM/a5x/rZxj4= 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 1752554352571260.69212812528826; Mon, 14 Jul 2025 21:39:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPL-0001sz-9g; Tue, 15 Jul 2025 00:36:47 -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 1ubXOQ-0001Mf-1S for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:53 -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 1ubXOM-00060F-MT for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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-621-WUbWppeyN5eOb1G9gHh7Hw-1; Tue, 15 Jul 2025 00:35:43 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 3377F19560B6 for ; Tue, 15 Jul 2025 04:35:43 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 29D9D1977000; Tue, 15 Jul 2025 04:35:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554145; 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=Nz9MquxxepnoZMxKo3y1v9ufJecmfppxLrR7MtZ/5JizOsT5C2KgZSQRGOy16vKn7ktoPY 5SoPY98kgeOzmuRTgAQyTVOJfIa2qsbSL7aQpU1Dku0hpE7fptSvIwBEnWW2sWrwXqTAyw 82WBno2//WKLbOwjP8qPLPgSWRdlG9Q= X-MC-Unique: WUbWppeyN5eOb1G9gHh7Hw-1 X-Mimecast-MFC-AGG-ID: WUbWppeyN5eOb1G9gHh7Hw_1752554143 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 04/16] net: Define net_client_set_link() Date: Tue, 15 Jul 2025 12:35:12 +0800 Message-ID: <20250715043524.21719-5-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554354625116600 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 Sat Nov 15 10:52:52 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=1752554607; cv=none; d=zohomail.com; s=zohoarc; b=DoLbJYpVsYNKsxXzi50ZOHXanAgy30afPUkXhhgBORb0ybZd8lGre+F+R5DK6WyVTAxXTTOcrnRxamdWZ9XAQ4z/EVB+oqKda2holu4C8yzIYKRPS8Z87PL1yLmSI/RGKHUTeZUaHGWD2MOHTzJBPnoimh6bEzv+Sr+NBvi8Gao= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554607; 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=UHuOZcs2nSmucYqyJA5pIZqWr1/0mK525LhCdix0tPxPZJFAlT6Dyed5CPyXhWnRlfySk35MaaFHBDvFy+CRhldbRz27HR1C7goCUwj1z+xHmIuXhXp2dsLEOngmq+XunRzq/DgnonMEuvV/+ZPKfwhBIgq5hhL910cM60qgkpg= 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 1752554607310250.0050498875538; Mon, 14 Jul 2025 21:43:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPN-0001uS-QQ; Tue, 15 Jul 2025 00:36:49 -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 1ubXOS-0001NU-3a for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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 1ubXOQ-000610-8q for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:51 -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-86-dD3pCPJRNtS0R12RVJSh3w-1; Tue, 15 Jul 2025 00:35:46 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 CBE2E19560A6 for ; Tue, 15 Jul 2025 04:35:45 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CCF981977000; Tue, 15 Jul 2025 04:35:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554148; 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=aIBaeBAQkik9amDo68jf1m7roKxsXQPTReSmO8cEqjt7ABQUMG18QchPjHmZgfwqez/LSV 44/cOjgnPv0y7IeBHIxhQeyysimbCngcNdVQFkZVXN7u1frV3EBfWH5ZNjxtUfYGP+88E2 liUsFcw68myPVL4dN9F/QJuidMCk9NI= X-MC-Unique: dD3pCPJRNtS0R12RVJSh3w-1 X-Mimecast-MFC-AGG-ID: dD3pCPJRNtS0R12RVJSh3w_1752554145 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 05/16] vhost_net: Rename vhost_set_vring_enable() for clarity Date: Tue, 15 Jul 2025 12:35:13 +0800 Message-ID: <20250715043524.21719-6-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554609011116600 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 Sat Nov 15 10:52:52 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=1752554312; cv=none; d=zohomail.com; s=zohoarc; b=T5KET0gWU1wCvvDN/KCNuWbFClcn5dDM9XNbpe+yZqYuwjOvP6W7JEwhGt4FDaBcdTDJPj6uX2H8Tu/AUDA7/gFY7HavEJ8YvQfXXFTuaBR6PS0yUxRJYasMDhsQeD9hOtT+swMDXdI9Wkis3OZrPd1NBKaASjFC9fZ94tjSlJE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554312; 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=iCbnK9FblmA3unXODdgFApmXufggajiGyb7aH6dAluD0qBEQ9gq5CnVdEpH6pWvaP2d5c9Emy8FlvoMPUW9ZRkax2Stx4/V8KFBOMxXXV3GmlGHxQakhqfYsXlwyL9CjsDgtxHH4wMA0a5CAbWW9Wy+Hc8J7j0jO3MgUaUOrzoM= 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 1752554312762126.45815622089435; Mon, 14 Jul 2025 21:38:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPE-0001ok-Om; Tue, 15 Jul 2025 00:36:42 -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 1ubXOU-0001OP-CD for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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 1ubXOR-00061E-L2 for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35: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-199-ZKMKdFjINFCenyAlOm6wYA-1; Tue, 15 Jul 2025 00:35:49 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 7C5501809C86 for ; Tue, 15 Jul 2025 04:35:48 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 934C61977000; Tue, 15 Jul 2025 04:35:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554150; 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=aFYFw7pQu7n1D+3SL9h4arF1uSir83y77BTdeAlp9q3uoJmVYHcZyTmDP3SZ6dp8djA1G/ FjIkJxyAsgMMK4Y9/8l+1XRCS3lxHPus02ZyT0STAZ+iGdzSGDo+ZpvSi2UFw2Iqfmwg3G 3xAjhVJCdRn1JQqXpu1hU0Jb2tJQ0P0= X-MC-Unique: ZKMKdFjINFCenyAlOm6wYA-1 X-Mimecast-MFC-AGG-ID: ZKMKdFjINFCenyAlOm6wYA_1752554148 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 06/16] net: Add get_vhost_net callback to NetClientInfo Date: Tue, 15 Jul 2025 12:35:14 +0800 Message-ID: <20250715043524.21719-7-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554314505116600 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 Sat Nov 15 10:52:52 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=1752554510; cv=none; d=zohomail.com; s=zohoarc; b=nrg2x0AY5gNOxmyhLnyKwjn4oIyeN0DBZYCVcgrkp8rsmKlLGbfnGrBP3ATQ/QAJjaUCpAb3piwwp3XeCECt1wzjBo7//ozzHoEG0kOFLdUPCCv3HpYl5BU3VwUUgA5btMlOW7cE0TMo3cCrHSM+aKbtpIFqNP1TJTAJNjJm4is= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554510; 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=boC6F0ikWxJWE88BDzh8af+WxmZMTDQ+yBamt8+sLHXjqe5Az4N58VuOYRUk5Z97/8H+h7pRmR6yZSa04nX8y0g9vFTYh1dEuEpITN0GWPEvP9ItZ7RmHGSgsJtYBEFK/bGNng5QYOsNPDOhJnJRmpUrGePb0QJxFNsFCKN8PU0= 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 175255451045692.45604491196752; Mon, 14 Jul 2025 21:41:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPO-0001us-Fv; Tue, 15 Jul 2025 00:36:50 -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 1ubXOY-0001QB-B3 for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:01 -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 1ubXOW-00061W-3N for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:58 -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-671-qHaDEonFOOGZZenOnO-jpA-1; Tue, 15 Jul 2025 00:35:51 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 2B9211800290 for ; Tue, 15 Jul 2025 04:35:51 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3B4BC1977000; Tue, 15 Jul 2025 04:35:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554153; 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=K/NJyaYtluwslWu9+JprW83r6RA5zK1EG4xpfc/i3lgYMLvIpIGpGwF3qN7X4YDh54SB09 YNLqLgEQlMgALtQDo4uA8jZqaTgkvy5wVfShDmtqyb3MQr4ssjXU3s3LpDzOWQwRy3cWbE TwbV+coOs+wnENFHfX3FO7RbLQ/nXD0= X-MC-Unique: qHaDEonFOOGZZenOnO-jpA-1 X-Mimecast-MFC-AGG-ID: qHaDEonFOOGZZenOnO-jpA_1752554151 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 07/16] net: Consolidate vhost feature bits into vhost_net structure Date: Tue, 15 Jul 2025 12:35:15 +0800 Message-ID: <20250715043524.21719-8-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554512799116600 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 Sat Nov 15 10:52:52 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=1752554494; cv=none; d=zohomail.com; s=zohoarc; b=avRBKcv617u5gTQT487JWkkZbYNj3GLrAI2D/aLAdI4QkmKeOQ+car5QxV5rt20samhEFZaCsaDhnpUfVONUL17s4O+oBrbNJn5hYiwtMx40PQ66JtSbBEZM0wreF8T2IOHeieiv/iOvaBLf9bjrTBvjch51DDU9EOitKA8gpCA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554494; 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=K1WCWxkDbVsmz97lgz80TukT7FaxbyAGAHcMWE7HM1W/rpLy7MLC7YiyIkq0Q9l+L/hCH1oeHQgOUmdwbGyajXYtDJKvipjC6P+VZw2U4abhnYYE2wlwgB/mzuoTtlXEA2ESHGKzVLrDfJv81MNtTFheDE558srFFqXnNlRgrUA= 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 1752554494582304.10147486918447; Mon, 14 Jul 2025 21:41:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPO-0001ur-FD; Tue, 15 Jul 2025 00:36:50 -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 1ubXOZ-0001QN-Gu for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36: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 1ubXOX-00061l-Gu for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:35:59 -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-537-cpIGUZ6XNlSk4-Iup7XFyA-1; Tue, 15 Jul 2025 00:35:54 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 18D5D180029F for ; Tue, 15 Jul 2025 04:35:54 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E2FFF1977000; Tue, 15 Jul 2025 04:35:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554156; 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=A9MMChdawPB3lbyc7/AVYunUtoN8YpFfON6TBxKFXxAUuZGkRGxUSm/kRm+pbP/SW/TvrK 9GK+iaFguXT8T2PYPD5sRCB05/wOvd68ipkKSkmyMd2EKFSQv5kQPRaUWkVB8zOKMFCNVd 1HPP2LlMQCXFMv/l1yyWkxjAEFUNWO8= X-MC-Unique: cpIGUZ6XNlSk4-Iup7XFyA-1 X-Mimecast-MFC-AGG-ID: cpIGUZ6XNlSk4-Iup7XFyA_1752554154 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 08/16] net: Add get_acked_features callback to VhostNetOptions Date: Tue, 15 Jul 2025 12:35:16 +0800 Message-ID: <20250715043524.21719-9-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554496175116600 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 Sat Nov 15 10:52:52 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=1752554484; cv=none; d=zohomail.com; s=zohoarc; b=U/tc82bMJvOg/irweO65tkbRdpSki3qKIWiINskO0WzZXCmnJTKUjEPhkzsk3PJTDf3AceuBSQrgCTbDoFN3yv7vTABC54hLCaGas9MtQKEWqFoQKtBGykk69dpvw74176065VLEoQbcbxzecLJWNCeVfjSKNOTBLMfEc7o7JVw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554484; 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=QV+WJuK7jLmXauQD+8c7NkilcU3xdnLsvmnJQ4rChfnDXympdWdrPFDUhd/S4sSrJNXgEGXeIR2RSbOa2+petBuXfMMR81osJ9r+kmhH3bHRDPvYUQ9ght06P65u53Muzz2RR5sydP72C5Srq2N5m9VrQMF6Oum7UHIZBG8L92Q= 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 1752554483942260.93587269559816; Mon, 14 Jul 2025 21:41:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPN-0001uV-RX; Tue, 15 Jul 2025 00:36:49 -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 1ubXOe-0001Ra-7C for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubXOc-00062N-3s for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:03 -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-682-CZZyJFxwPQugW04ysMGI_Q-1; Tue, 15 Jul 2025 00:35:57 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 B9457180120C for ; Tue, 15 Jul 2025 04:35:56 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CC4C61977000; Tue, 15 Jul 2025 04:35:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554159; 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=cmd6J3D4luNKYicYJHpfbrLLfHGjT99sZSKGL1aSMZfawAuMtWmSIiVsIODq1sX5FlyMCT CeSq+E5SxwmVGsxaWCdwSiPU76fYWH8fn6hw0LXXQjMORttS9KTBC4IyPGzA8Dym2tgDWC 1H/uDRfKvFk9LKvAoKUqW5KFugvF6Ok= X-MC-Unique: CZZyJFxwPQugW04ysMGI_Q-1 X-Mimecast-MFC-AGG-ID: CZZyJFxwPQugW04ysMGI_Q_1752554156 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 09/16] net: Add save_acked_features callback to vhost_net Date: Tue, 15 Jul 2025 12:35:17 +0800 Message-ID: <20250715043524.21719-10-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554486115116600 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 Sat Nov 15 10:52:52 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=1752554308; cv=none; d=zohomail.com; s=zohoarc; b=CD0HTEYT0i39mPFQYMl6ii2bWmidVjkNn5Lo4XRU1LzDYKg0YiFiuVTeECn0Mhd/bO1HUFkJTmp6dWJPt+UzSfcdIjGOpLcLOoJt3dOsblA27etOIFyASDBxMaFxZ47+zH+NhQCJ/zIpVcI6Z5D5dkWICXlazVbJyafB0gI+rhw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554308; 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=c2fyxJaxX3/ctThBon+a2PnTmvPiKfilmRya3ReSuJLRAxRzpQiKgBDXjmQ7T7CpuR32eZNW7a1OzwG7UTWPUFLDZavEKzJ89Ld92ZY8QI+5x83jCW64sI5cFbkAo7FZtBw12KEybnkouTzRwYaavkwiaDZEjzfcsxPK/T81stE= 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 1752554308416713.7280801561528; Mon, 14 Jul 2025 21:38:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPQ-0001wm-LQ; Tue, 15 Jul 2025 00:36:53 -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 1ubXOh-0001TC-Vu for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubXOf-00062z-NH for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:07 -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-92-DxzeGwNtNpGAMYLZ9VHllg-1; Tue, 15 Jul 2025 00:36:00 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 84B49180029E for ; Tue, 15 Jul 2025 04:35:59 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 905F41977000; Tue, 15 Jul 2025 04:35:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554164; 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=jGH7bHw52LZ2bo+pQSozk6+vW7NT+Kw04M3Rs8tftaPfim82NLDtyQA8hARdASOhePxGMl mxnQYOzGBT+KT+xv8PJHUOG6rcY5L1i3Js3S1YvPX5AhKxf2oNYGBYsJGKn96HNScSDwd1 CSAQZABromZpJgwg7hJJB0ArnomcyHM= X-MC-Unique: DxzeGwNtNpGAMYLZ9VHllg-1 X-Mimecast-MFC-AGG-ID: DxzeGwNtNpGAMYLZ9VHllg_1752554159 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 10/16] net: Allow network backends to advertise max TX queue size Date: Tue, 15 Jul 2025 12:35:18 +0800 Message-ID: <20250715043524.21719-11-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554310428116600 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 Sat Nov 15 10:52:52 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=1752554241; cv=none; d=zohomail.com; s=zohoarc; b=LDINQUX+pnnUU4938Jr65kd6lFlyLX2Kgeg8F65Y27ewu4cH+Q6x4cWTfZ/EXGC7xO61FSV1LTWHZZUkmvJ2jKBvT7nQDen+sBqAU+wwihvgaTBKHf+wtfL77fvnCk467de5stusaRkc8FG8yqTxZyMQ3Ps6IcLlYBsM4bjMOQs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554241; 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=R4lwk9DAhS9C3GeDftUPiXSxIbNemTk3lipzdJROeNBs7VaW/rXau1je0ztDtoIYIZ0litn1kNaulWWLXgJ/owl4ZZjn5OLfswAKZcRPKwegYyJBEBFT/AivtD+N/S3lG8Lm9lRJ+fWBPMnESwhj9/+dRgyfbWNIz5npjkqsUuM= 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 1752554241651149.7312471688158; Mon, 14 Jul 2025 21:37:21 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPK-0001sq-TW; Tue, 15 Jul 2025 00:36:46 -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 1ubXOj-0001Tn-Jk for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ubXOh-000633-QG for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:09 -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-206-COqRQ68iOrWdyELG6s8DzQ-1; Tue, 15 Jul 2025 00:36:04 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 39F461809C8B for ; Tue, 15 Jul 2025 04:36:03 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 44F161977000; Tue, 15 Jul 2025 04:35:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554166; 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=Gbiuh+cKPTbHEEbZl6qQiVx4P2u0dolPESF7p7SktqOlFIOOq/Y8EqlZWjpXNm4RIed2oj NXCry5fP2UNlDAk3Y2aU1RQLfFr367NlG3kMuU8V6bBk0BrpFsfj6lTveoJTsBMI1SatSB UPPkrCiOZpR/9fZOC2ly0tS16HPY2k0= X-MC-Unique: COqRQ68iOrWdyELG6s8DzQ-1 X-Mimecast-MFC-AGG-ID: COqRQ68iOrWdyELG6s8DzQ_1752554163 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 11/16] net: Add is_vhost_user flag to vhost_net struct Date: Tue, 15 Jul 2025 12:35:19 +0800 Message-ID: <20250715043524.21719-12-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554243838116600 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 Sat Nov 15 10:52:52 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=1752554531; cv=none; d=zohomail.com; s=zohoarc; b=RKoAaLyQqe6Evyx9Vymocf2AAjEnAtrK2DLX/H2et3sI45fZ2gnwXRH7pvYe0anlAuf7NP4uwCzBkzdkitEtoELTZ/8KjYf+YJ54TAYQ1nW5mzgdvDrUhgAoa8B3l/FV82Po4D2yCoVaL0S+eqKdg445fGLieQ2sagGBXghS85U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554531; 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=AGxl5dtdyYkXCj2la8L4LTkBpYBglxDjB6U6aDyivX3A9FilV/8egu1GO7Yuu/HPkXE/O//G4axqSksKg6QA7ASvyVVrWxSkA7g6Wxsas4QyCfJxtJbpD8gNFfBofHScjV54pui108behCVC7O8iRIJyiv4ss4CkNpW/B8jiWEk= 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 1752554531603558.4112746948015; Mon, 14 Jul 2025 21:42:11 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPI-0001r7-AU; Tue, 15 Jul 2025 00:36: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 1ubXOp-0001XD-4g for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:16 -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 1ubXOk-00063c-Jf for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:14 -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-408-TCmAYDLZOTKgwLtWieW6BQ-1; Tue, 15 Jul 2025 00:36:06 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 BCFB319560AA for ; Tue, 15 Jul 2025 04:36:05 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D10221977000; Tue, 15 Jul 2025 04:36:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554169; 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=Y3s6X7hFG0dTrc3n09IkxerAA/B6d/bHRnZ7acJ21VwfAuJkLu3kUfvvT6sbbcPAf36whL WamTibYd/JUPsQLEA+3oGUbbzMvH7in13REvg9xu2qsilMj8JLDYL4tvuSb1uc7sBe9E82 4Pzv1LnDOhi58YYnjxkMIXMp3i0e2qI= X-MC-Unique: TCmAYDLZOTKgwLtWieW6BQ-1 X-Mimecast-MFC-AGG-ID: TCmAYDLZOTKgwLtWieW6BQ_1752554165 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 12/16] net: Add passt network backend Date: Tue, 15 Jul 2025 12:35:20 +0800 Message-ID: <20250715043524.21719-13-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: 0 X-Spam_score: -0.1 X-Spam_bar: / X-Spam_report: (-0.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554532512116600 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 Sat Nov 15 10:52:52 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=1752554240; cv=none; d=zohomail.com; s=zohoarc; b=G+XsK7xCmjAOOmFBHf3Spcv3x8YM1FXEciYvYqKTjYsKaTxWVzRIokTc1eWRp5fS+QbK2G7dBscX9scXn8a9tnnUYRLHVUut/oZ+/md7PGGJkBTaixBgS7kW0V/+2spBFK/2xBRFbCOp7QdJ1jhj/vc7S6dfPnjhK536edwRl1A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554240; 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=Gn8KReqs0KVWarhC++r7b+jh1vtIh+Xp/iBkeMsyktPKQbQ/wVwi/CItqzFUnd1Ie2TePLLd+5EvV6whpp6okedy/J9YwchkPmcn0mMI2yyl5DeB2OSMKLR2ka0WxG8QbaUrR2F4FT1isBsnzZwF5YhtJy9ymDgymTvDgyMZM/Q= 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 1752554240824879.4179879718162; Mon, 14 Jul 2025 21:37:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPS-0001xI-0R; Tue, 15 Jul 2025 00:36:54 -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 1ubXOp-0001XM-Lj for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:16 -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 1ubXOl-00063g-O4 for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:15 -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-410-1e-924IDPLa_-4uIBILf8g-1; Tue, 15 Jul 2025 00:36:09 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 6448C180028B for ; Tue, 15 Jul 2025 04:36:08 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7C8391977000; Tue, 15 Jul 2025 04:36:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554171; 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=YF6X7MuwzMQ/PWDzZrrSi2eNxMPoMgVwPD4NywF/iqARdsn1X2pPQtW9O/S+s3jki8j/bp df2f6silTGT61Jf+QAclV8Dke30dLRTsJ1EWfnsYGrDYmZFBjJDD2J1cE7QUCqywJbo8fp O8CktWV3BBEx11gtA3UHJbKiCfab01Y= X-MC-Unique: 1e-924IDPLa_-4uIBILf8g-1 X-Mimecast-MFC-AGG-ID: 1e-924IDPLa_-4uIBILf8g_1752554168 From: Jason Wang To: qemu-devel@nongnu.org Cc: Laurent Vivier , Jason Wang Subject: [PULL V2 13/16] net/passt: Implement vhost-user backend support Date: Tue, 15 Jul 2025 12:35:21 +0800 Message-ID: <20250715043524.21719-14-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554242267116600 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 From nobody Sat Nov 15 10:52:52 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=1752554456; cv=none; d=zohomail.com; s=zohoarc; b=L0eMiVJnfiNdCelqz49h/xemB/PZ94GaLFyEQUqGP4msO/sAzZH9paG5RFk8gkxSK6/oKuxDdLcb4TqQrDQMTZrERXrR8RAPICge1FcN0Aoj4bvwc9Jy3JG8Ksjpu3/MvDxLqI+izEZvo3Zyg36EgASUrtBGm2k7UL6ZMM7NpI4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554456; 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=BDqO+8Rqs4+HyIcE4v6ujqTUDnN0150WYetqM62Wi6Q=; b=gRniQ9k2c5LyaZtjHVG7+3eC4KtdBC0fScjqZFbtV0m2UgsC4379Uv2yz77bXspqF4ggI8ZyyFZf/cuDbsvp9Ucv8sO8k8/hYMa5xZK1eCtuu98Z589yXUItnfoXbUPvwqs2yoPNcsK7/bIJC5WspYwqvn+8dC1unMW+4pXPyk0= 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 1752554456837587.113336456118; Mon, 14 Jul 2025 21:40:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPT-0001xd-4i; Tue, 15 Jul 2025 00:36:55 -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 1ubXOu-0001ZP-FG for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:20 -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 1ubXOs-00064U-He for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:20 -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-173-iAs9QhQ4Nz6u1hdTATNq7w-1; Tue, 15 Jul 2025 00:36:13 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 2FDCE18089B5; Tue, 15 Jul 2025 04:36:12 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2486B1977000; Tue, 15 Jul 2025 04:36:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554177; 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=BDqO+8Rqs4+HyIcE4v6ujqTUDnN0150WYetqM62Wi6Q=; b=WeBPWvWMV6qje/4Liu3o0g0D059OpmRv7eP3255DwzAFDY6iV6ZjhHr2k+CvwrYablNVFE P3NPmwmI07fkUaFZzARDVt8nQRs90Ih7e3lIaHGbrIl6UtmBxMDREeTvqzxrjpP8ceFUqQ x50bLS7nlbo06nYUnXvr8VUqrQC7ess= X-MC-Unique: iAs9QhQ4Nz6u1hdTATNq7w-1 X-Mimecast-MFC-AGG-ID: iAs9QhQ4Nz6u1hdTATNq7w_1752554172 From: Jason Wang To: qemu-devel@nongnu.org Cc: Daniel Borkmann , Ilya Maximets , Jason Wang , Anton Protopopov Subject: [PULL V2 14/16] net/af-xdp: Remove XDP program cleanup logic Date: Tue, 15 Jul 2025 12:35:22 +0800 Message-ID: <20250715043524.21719-15-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554457714116600 Content-Type: text/plain; charset="utf-8" From: Daniel Borkmann There are two issues with the XDP program removal in af_xdp_cleanup(): 1) Starting from libxdp 1.3.0 [0] the XDP program gets automatically detached when we call xsk_socket__delete() for the last successfully configured queue. libxdp internally keeps track of that. For QEMU we require libxdp >=3D 1.4.0. Given QEMU is not loading the program, lets also not attempt to remove it and delegate this instead. 2) The removal logic is incorrect anyway because we are setting n_queues into the last queue that never has xdp_flags on failure, so the logic is always skipped since the non-zero test for s->xdp_flags in af_xdp_cleanup() fails. Fixes: cb039ef3d9e3 ("net: add initial support for AF_XDP network backend") Suggested-by: Ilya Maximets Signed-off-by: Daniel Borkmann Reviewed-by: Ilya Maximets Cc: Ilya Maximets Cc: Jason Wang Cc: Anton Protopopov Link: https://github.com/xdp-project/xdp-tools/commit/38c2914988fd5c1ef65f2= 381fc8af9f3e8404e2b [0] Signed-off-by: Jason Wang --- net/af-xdp.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/af-xdp.c b/net/af-xdp.c index d022534d76..3d3268e18b 100644 --- a/net/af-xdp.c +++ b/net/af-xdp.c @@ -49,7 +49,6 @@ typedef struct AFXDPState { char *buffer; struct xsk_umem *umem; =20 - uint32_t n_queues; uint32_t xdp_flags; bool inhibit; } AFXDPState; @@ -274,14 +273,6 @@ static void af_xdp_cleanup(NetClientState *nc) s->umem =3D NULL; qemu_vfree(s->buffer); s->buffer =3D NULL; - - /* Remove the program if it's the last open queue. */ - if (!s->inhibit && nc->queue_index =3D=3D s->n_queues - 1 && s->xdp_fl= ags - && bpf_xdp_detach(s->ifindex, s->xdp_flags, NULL) !=3D 0) { - fprintf(stderr, - "af-xdp: unable to remove XDP program from '%s', ifindex: = %d\n", - s->ifname, s->ifindex); - } } =20 static int af_xdp_umem_create(AFXDPState *s, int sock_fd, Error **errp) @@ -490,12 +481,9 @@ int net_init_af_xdp(const Netdev *netdev, =20 pstrcpy(s->ifname, sizeof(s->ifname), opts->ifname); s->ifindex =3D ifindex; - s->n_queues =3D queues; =20 if (af_xdp_umem_create(s, sock_fds ? sock_fds[i] : -1, errp) || af_xdp_socket_create(s, opts, errp)) { - /* Make sure the XDP program will be removed. */ - s->n_queues =3D i; error_propagate(errp, err); goto err; } --=20 2.42.0 From nobody Sat Nov 15 10:52:52 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=1752554409; cv=none; d=zohomail.com; s=zohoarc; b=mqkwu/GtDAUKjAy3lrxGtw5n5jbqXYRBCw0CxWg1NCrf5Hj2iq5L0RnWpKEf5eH7WIpyrkEmBmZQrD8u5AWFcswvip2+30KgwSYwrGs4LyYx0vfaGcuSwU6Wf76hPRvTkBN+4ljHiCWcWxRnABR2iUHkYGfr3jl5gf13mrJW4+M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554409; 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=XGCsCUL5qF6MIXdaUO7UwSCz3GEaEBI9T7XGpaS+VSQ=; b=kuqbTjbG5hiKFn2F0OaLGiRqnOJ0WpXuM8epVNbApom6X0Wxc4o273mjZiyxNUYRtUKUOy+GNodjNHSkDDsK3wEBKLG3V6paCulQziARh2ONXxf05PlGJhgvxvuf71SUTVxEgh0C3geZj+FQ8hhU2HtU2bJXHHDwTgZhSAEe3Qs= 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 175255440922415.285937264997642; Mon, 14 Jul 2025 21:40:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPT-0001yL-Qn; Tue, 15 Jul 2025 00:36:55 -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 1ubXOv-0001ar-QE for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:21 -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 1ubXOt-00064g-W6 for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:21 -0400 Received: from mx-prod-mc-02.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-94-wf6_gl3XPZWtV_ArOR4Fhg-1; Tue, 15 Jul 2025 00:36:17 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0BB0A195608F; Tue, 15 Jul 2025 04:36:16 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2AE4C1977029; Tue, 15 Jul 2025 04:36:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554179; 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=XGCsCUL5qF6MIXdaUO7UwSCz3GEaEBI9T7XGpaS+VSQ=; b=LpOSona/Y1xdisVNOIloKfUgtx7ki0yWADFpi8+8xrUGES1ScBe2ucVB/61RMFtPU3j0iG V0AEb0FXb5PhEkatQeCs0gTwvxDYOCtHreeVxrspHqHiyE1Y3Rz97UEDeKeu9h4vpch9d1 SU2iJg5sLOTDQ8EuV7XvZLt+hZ3I0zk= X-MC-Unique: wf6_gl3XPZWtV_ArOR4Fhg-1 X-Mimecast-MFC-AGG-ID: wf6_gl3XPZWtV_ArOR4Fhg_1752554176 From: Jason Wang To: qemu-devel@nongnu.org Cc: Daniel Borkmann , Ilya Maximets , Jason Wang , Anton Protopopov Subject: [PULL V2 15/16] net/af-xdp: Fix up cleanup path upon failure in queue creation Date: Tue, 15 Jul 2025 12:35:23 +0800 Message-ID: <20250715043524.21719-16-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554411287116600 Content-Type: text/plain; charset="utf-8" From: Daniel Borkmann While testing, it turned out that upon error in the queue creation loop, we never trigger the af_xdp_cleanup() handler. This is because we pass errp instead of a local err pointer into the various AF_XDP setup functions instead of a scheme like: bool fn(..., Error **errp) { Error *err =3D NULL; foo(arg, &err); if (err) { handle the error... error_propagate(errp, err); return false; } ... } The same is true for the attachment probing with bpf_xdp_query_id(). With a conversion into the above format, the af_xdp_cleanup() handler is called as expected. Note the error_propagate() handles a NULL err internally. Fixes: cb039ef3d9e3 ("net: add initial support for AF_XDP network backend") Reviewed-by: Ilya Maximets Signed-off-by: Daniel Borkmann Cc: Ilya Maximets Cc: Jason Wang Cc: Anton Protopopov Signed-off-by: Jason Wang --- net/af-xdp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/af-xdp.c b/net/af-xdp.c index 3d3268e18b..cbe1cae700 100644 --- a/net/af-xdp.c +++ b/net/af-xdp.c @@ -482,9 +482,8 @@ int net_init_af_xdp(const Netdev *netdev, pstrcpy(s->ifname, sizeof(s->ifname), opts->ifname); s->ifindex =3D ifindex; =20 - if (af_xdp_umem_create(s, sock_fds ? sock_fds[i] : -1, errp) - || af_xdp_socket_create(s, opts, errp)) { - error_propagate(errp, err); + if (af_xdp_umem_create(s, sock_fds ? sock_fds[i] : -1, &err) || + af_xdp_socket_create(s, opts, &err)) { goto err; } } @@ -492,7 +491,7 @@ int net_init_af_xdp(const Netdev *netdev, if (nc0) { s =3D DO_UPCAST(AFXDPState, nc, nc0); if (bpf_xdp_query_id(s->ifindex, s->xdp_flags, &prog_id) || !prog_= id) { - error_setg_errno(errp, errno, + error_setg_errno(&err, errno, "no XDP program loaded on '%s', ifindex: %d", s->ifname, s->ifindex); goto err; @@ -506,6 +505,7 @@ int net_init_af_xdp(const Netdev *netdev, err: if (nc0) { qemu_del_net_client(nc0); + error_propagate(errp, err); } =20 return -1; --=20 2.42.0 From nobody Sat Nov 15 10:52:52 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=1752554322; cv=none; d=zohomail.com; s=zohoarc; b=NPlIAL3k5Ut+tagXwM+c69poXQtil6b97n9BAZzIfBfHqEmGHrErQFX0LLeLa/jLPVFZSuyacPcvnuD80TFI+0P/XaVSltQ1JyIVPLTM78NL6YdofgC5ezgkrEjCSK4Lf0YFuwZ7VNYyN2hJSNsoGYHWKp9PlJpo+uRHdCDG/Yk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1752554322; 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=YnGInowHDQM/yx6IqGBLQtzOS1Z+AVF+jDgTvgR0Jaw=; b=V71ygQOd99TAdRdHwrDD5euiubpUykVAbDdSh8IFQEqKGuX1QiEdPPDhodOSAzQhuoNBhPu7NklBv9o7GJKP73JAsNqWot4ZMEaoFFONU9zVrkmCVm/QHOilGWXdnU/P0cs9WtyWuVHVKbqEUtXGvWvixggOqeTnkML0uhXSfU4= 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 1752554322101523.4603157217324; Mon, 14 Jul 2025 21:38:42 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ubXPJ-0001ry-Ms; Tue, 15 Jul 2025 00:36:45 -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 1ubXP2-0001f5-HE for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:28 -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 1ubXOz-00065R-Sy for qemu-devel@nongnu.org; Tue, 15 Jul 2025 00:36:28 -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-501-6GaNIZb4MaqWi4C5palRww-1; Tue, 15 Jul 2025 00:36:21 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (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 B0117195608C; Tue, 15 Jul 2025 04:36:19 +0000 (UTC) Received: from localhost.localdomain (unknown [10.72.112.42]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C75981977000; Tue, 15 Jul 2025 04:36:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752554185; 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=YnGInowHDQM/yx6IqGBLQtzOS1Z+AVF+jDgTvgR0Jaw=; b=H4HfLWRbbQ6wn8m5tn2wnLwQer294k7OibuAx7xyB8pCxTWu/DDL6DP7VYwXGoZqGtppWa C70IWSwWW4Kg6xWtImhLNvemgbCXUUN49m0OfHUgEIT04xfvhTybIY3eIDcSa6ZEXHBYTQ bF0KCZDTGj/enhRZAv5Op+UDy7GQvgc= X-MC-Unique: 6GaNIZb4MaqWi4C5palRww-1 X-Mimecast-MFC-AGG-ID: 6GaNIZb4MaqWi4C5palRww_1752554180 From: Jason Wang To: qemu-devel@nongnu.org Cc: Daniel Borkmann , Ilya Maximets , Jason Wang , Anton Protopopov Subject: [PULL V2 16/16] net/af-xdp: Support pinned map path for AF_XDP sockets Date: Tue, 15 Jul 2025 12:35:24 +0800 Message-ID: <20250715043524.21719-17-jasowang@redhat.com> In-Reply-To: <20250715043524.21719-1-jasowang@redhat.com> References: <20250715043524.21719-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.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=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1752554322652116600 Content-Type: text/plain; charset="utf-8" From: Daniel Borkmann Extend 'inhibit=3Don' setting with the option to specify a pinned XSK map path along with a starting index (default 0) to push the created XSK sockets into. Example usage: # ./build/qemu-system-x86_64 [...] \ -netdev af-xdp,ifname=3Denp2s0f0np0,id=3Dnet0,mode=3Dnative,queues=3D2,s= tart-queue=3D14,inhibit=3Don,map-path=3D/sys/fs/bpf/xsks_map,map-start-inde= x=3D14 \ -device virtio-net-pci,netdev=3Dnet0 [...] This is useful for the case where an existing XDP program with XSK map is present on the AF_XDP supported phys device and the XSK map is not yet populated. For example, the former could have been pre-loaded onto the netdevice by a control plane, which later launches QEMU to populate it with XSK sockets. Normally, the main idea behind 'inhibit=3Don' is that the QEMU instance doesn't need to have a lot of privileges to use the pre-loaded program and the pre-created sockets, but this mentioned use-case here is different where QEMU still needs privileges to create the sockets. The 'map-start-index' parameter is optional and defaults to 0. It allows flexible placement of the XSK sockets, and is up to the user to specify when the XDP program with XSK map was already preloaded. In the simplest case the queue-to-map-slot mapping is just 1:1 based on ctx->rx_queue_index but the user might as well have a different scheme (or smaller map size, e.g. ctx->rx_queue_index % max_size) to push the inbound traffic to one of the XSK sockets. Note that the bpf_xdp_query_id() is now only tested for 'inhibit=3Doff' since only in the latter case the libxdp takes care of installing the XDP program which was installed based on the s->xdp_flags pointing to either driver or skb mode. For 'inhibit=3Don' we don't make any assumptions and neither go down the path of probing all possible options in which way the user installed the XDP program. Reviewed-by: Ilya Maximets Signed-off-by: Daniel Borkmann Cc: Ilya Maximets Cc: Jason Wang Cc: Anton Protopopov Signed-off-by: Jason Wang --- net/af-xdp.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++--- qapi/net.json | 29 +++++++++++------ qemu-options.hx | 23 ++++++++++++-- 3 files changed, 118 insertions(+), 17 deletions(-) diff --git a/net/af-xdp.c b/net/af-xdp.c index cbe1cae700..14f302ea21 100644 --- a/net/af-xdp.c +++ b/net/af-xdp.c @@ -51,6 +51,10 @@ typedef struct AFXDPState { =20 uint32_t xdp_flags; bool inhibit; + + char *map_path; + int map_fd; + uint32_t map_start_index; } AFXDPState; =20 #define AF_XDP_BATCH_SIZE 64 @@ -260,6 +264,7 @@ static void af_xdp_send(void *opaque) static void af_xdp_cleanup(NetClientState *nc) { AFXDPState *s =3D DO_UPCAST(AFXDPState, nc, nc); + int idx; =20 qemu_purge_queued_packets(nc); =20 @@ -273,6 +278,18 @@ static void af_xdp_cleanup(NetClientState *nc) s->umem =3D NULL; qemu_vfree(s->buffer); s->buffer =3D NULL; + + if (s->map_fd >=3D 0) { + idx =3D nc->queue_index + s->map_start_index; + if (bpf_map_delete_elem(s->map_fd, &idx)) { + fprintf(stderr, "af-xdp: unable to remove AF_XDP socket from m= ap" + " %s\n", s->map_path); + } + close(s->map_fd); + s->map_fd =3D -1; + } + g_free(s->map_path); + s->map_path =3D NULL; } =20 static int af_xdp_umem_create(AFXDPState *s, int sock_fd, Error **errp) @@ -336,7 +353,6 @@ static int af_xdp_socket_create(AFXDPState *s, }; int queue_id, error =3D 0; =20 - s->inhibit =3D opts->has_inhibit && opts->inhibit; if (s->inhibit) { cfg.libxdp_flags |=3D XSK_LIBXDP_FLAGS__INHIBIT_PROG_LOAD; } @@ -387,6 +403,35 @@ static int af_xdp_socket_create(AFXDPState *s, return 0; } =20 +static int af_xdp_update_xsk_map(AFXDPState *s, Error **errp) +{ + int xsk_fd, idx, error =3D 0; + + if (!s->map_path) { + return 0; + } + + s->map_fd =3D bpf_obj_get(s->map_path); + if (s->map_fd < 0) { + error =3D errno; + } else { + xsk_fd =3D xsk_socket__fd(s->xsk); + idx =3D s->nc.queue_index + s->map_start_index; + if (bpf_map_update_elem(s->map_fd, &idx, &xsk_fd, 0)) { + error =3D errno; + } + } + + if (error) { + error_setg_errno(errp, error, + "failed to insert AF_XDP socket into map %s", + s->map_path); + return -1; + } + + return 0; +} + /* NetClientInfo methods. */ static NetClientInfo net_af_xdp_info =3D { .type =3D NET_CLIENT_DRIVER_AF_XDP, @@ -435,12 +480,14 @@ int net_init_af_xdp(const Netdev *netdev, { const NetdevAFXDPOptions *opts =3D &netdev->u.af_xdp; NetClientState *nc, *nc0 =3D NULL; + int32_t map_start_index; unsigned int ifindex; uint32_t prog_id =3D 0; g_autofree int *sock_fds =3D NULL; int64_t i, queues; Error *err =3D NULL; AFXDPState *s; + bool inhibit; =20 ifindex =3D if_nametoindex(opts->ifname); if (!ifindex) { @@ -456,8 +503,28 @@ int net_init_af_xdp(const Netdev *netdev, return -1; } =20 - if ((opts->has_inhibit && opts->inhibit) !=3D !!opts->sock_fds) { - error_setg(errp, "'inhibit=3Don' requires 'sock-fds' and vice vers= a"); + inhibit =3D opts->has_inhibit && opts->inhibit; + if (inhibit && !opts->sock_fds && !opts->map_path) { + error_setg(errp, "'inhibit=3Don' requires 'sock-fds' or 'map-path'= "); + return -1; + } + if (!inhibit && (opts->sock_fds || opts->map_path)) { + error_setg(errp, "'sock-fds' and 'map-path' require 'inhibit=3Don'= "); + return -1; + } + if (opts->sock_fds && opts->map_path) { + error_setg(errp, "'sock-fds' and 'map-path' are mutually exclusive= "); + return -1; + } + if (!opts->map_path && opts->has_map_start_index) { + error_setg(errp, "'map-start-index' requires 'map-path'"); + return -1; + } + + map_start_index =3D opts->has_map_start_index ? opts->map_start_index = : 0; + if (map_start_index < 0) { + error_setg(errp, "'map-start-index' cannot be negative (%d)", + map_start_index); return -1; } =20 @@ -481,14 +548,20 @@ int net_init_af_xdp(const Netdev *netdev, =20 pstrcpy(s->ifname, sizeof(s->ifname), opts->ifname); s->ifindex =3D ifindex; + s->inhibit =3D inhibit; + + s->map_path =3D g_strdup(opts->map_path); + s->map_start_index =3D map_start_index; + s->map_fd =3D -1; =20 if (af_xdp_umem_create(s, sock_fds ? sock_fds[i] : -1, &err) || - af_xdp_socket_create(s, opts, &err)) { + af_xdp_socket_create(s, opts, &err) || + af_xdp_update_xsk_map(s, &err)) { goto err; } } =20 - if (nc0) { + if (nc0 && !inhibit) { s =3D DO_UPCAST(AFXDPState, nc, nc0); if (bpf_xdp_query_id(s->ifindex, s->xdp_flags, &prog_id) || !prog_= id) { error_setg_errno(&err, errno, diff --git a/qapi/net.json b/qapi/net.json index 0f766041a3..1f40bf46bb 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -567,25 +567,34 @@ # (default: 0). # # @inhibit: Don't load a default XDP program, use one already loaded -# to the interface (default: false). Requires @sock-fds. +# to the interface (default: false). Requires @sock-fds or @map-path. # # @sock-fds: A colon (:) separated list of file descriptors for # already open but not bound AF_XDP sockets in the queue order. # One fd per queue. These descriptors should already be added -# into XDP socket map for corresponding queues. Requires -# @inhibit. +# into XDP socket map for corresponding queues. @sock-fds and +# @map-path are mutually exclusive. Requires @inhibit. +# +# @map-path: The path to a pinned xsk map to push file descriptors +# for bound AF_XDP sockets into. @map-path and @sock-fds are +# mutually exclusive. Requires @inhibit. (Since 10.1) +# +# @map-start-index: Use @map-path to insert xsk sockets starting from +# this index number (default: 0). Requires @map-path. (Since 10.1) # # Since: 8.2 ## { 'struct': 'NetdevAFXDPOptions', 'data': { - 'ifname': 'str', - '*mode': 'AFXDPMode', - '*force-copy': 'bool', - '*queues': 'int', - '*start-queue': 'int', - '*inhibit': 'bool', - '*sock-fds': 'str' }, + 'ifname': 'str', + '*mode': 'AFXDPMode', + '*force-copy': 'bool', + '*queues': 'int', + '*start-queue': 'int', + '*inhibit': 'bool', + '*sock-fds': 'str', + '*map-path': 'str', + '*map-start-index': 'int32' }, 'if': 'CONFIG_AF_XDP' } =20 ## diff --git a/qemu-options.hx b/qemu-options.hx index a3c066c678..bf19987cb0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2929,6 +2929,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #ifdef CONFIG_AF_XDP "-netdev af-xdp,id=3Dstr,ifname=3Dname[,mode=3Dnative|skb][,force-copy= =3Don|off]\n" " [,queues=3Dn][,start-queue=3Dm][,inhibit=3Don|off][,sock-fds= =3Dx:y:...:z]\n" + " [,map-path=3D/path/to/socket/map][,map-start-index=3Di]\n" " attach to the existing network interface 'name' with = AF_XDP socket\n" " use 'mode=3DMODE' to specify an XDP program attach mo= de\n" " use 'force-copy=3Don|off' to force XDP copy mode even= if device supports zero-copy (default: off)\n" @@ -2936,6 +2937,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " with inhibit=3Don,\n" " use 'sock-fds' to provide file descriptors for alre= ady open AF_XDP sockets\n" " added to a socket map in XDP program. One socket p= er queue.\n" + " use 'map-path' to provide the socket map location t= o populate AF_XDP sockets with,\n" + " and use 'map-start-index' to specify the starting i= ndex for the map (default: 0) (Since 10.1)\n" " use 'queues=3Dn' to specify how many queues of a mult= iqueue interface should be used\n" " use 'start-queue=3Dm' to specify the first queue that= should be used\n" #endif @@ -3759,7 +3762,7 @@ SRST # launch QEMU instance |qemu_system| linux.img -nic vde,sock=3D/tmp/myswitch =20 -``-netdev af-xdp,id=3Dstr,ifname=3Dname[,mode=3Dnative|skb][,force-copy=3D= on|off][,queues=3Dn][,start-queue=3Dm][,inhibit=3Don|off][,sock-fds=3Dx:y:.= ..:z]`` +``-netdev af-xdp,id=3Dstr,ifname=3Dname[,mode=3Dnative|skb][,force-copy=3D= on|off][,queues=3Dn][,start-queue=3Dm][,inhibit=3Don|off][,sock-fds=3Dx:y:.= ..:z][,map-path=3D/path/to/socket/map][,map-start-index=3Di]`` Configure AF_XDP backend to connect to a network interface 'name' using AF_XDP socket. A specific program attach mode for a default XDP program can be forced with 'mode', defaults to best-effort, @@ -3799,7 +3802,8 @@ SRST -netdev af-xdp,id=3Dn1,ifname=3Deth0,queues=3D1,start-queue=3D1 =20 XDP program can also be loaded externally. In this case 'inhibit' opt= ion - should be set to 'on' and 'sock-fds' provided with file descriptors for + should be set to 'on'. Either 'sock-fds' or 'map-path' can be used wi= th + 'inhibit' enabled. 'sock-fds' can be provided with file descriptors f= or already open but not bound XDP sockets already added to a socket map f= or corresponding queues. One socket per queue. =20 @@ -3808,6 +3812,21 @@ SRST |qemu_system| linux.img -device virtio-net-pci,netdev=3Dn1 \\ -netdev af-xdp,id=3Dn1,ifname=3Deth0,queues=3D3,inhibit=3Don,s= ock-fds=3D15:16:17 =20 + For the 'inhibit' option set to 'on' used together with 'map-path' it = is + expected that the XDP program with the socket map is already loaded on + the networking device and the map pinned into BPF file system. The pa= th + to the pinned map is then passed to QEMU which then creates the file + descriptors and inserts them into the existing socket map. + + .. parsed-literal:: + + |qemu_system| linux.img -device virtio-net-pci,netdev=3Dn1 \\ + -netdev af-xdp,id=3Dn1,ifname=3Deth0,queues=3D2,inhibit=3Don,m= ap-path=3D/sys/fs/bpf/xsks_map + + Additionally, 'map-start-index' can be used to specify the start offset + for insertion into the socket map. The combination of 'map-path' and + 'sock-fds' together is not supported. + ``-netdev vhost-user,chardev=3Did[,vhostforce=3Don|off][,queues=3Dn]`` Establish a vhost-user netdev, backed by a chardev id. The chardev should be a unix domain socket backed one. The vhost-user uses a --=20 2.42.0