From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909159; cv=none; d=zohomail.com; s=zohoarc; b=SBO4Ls5HwI+8yqReFTH3Hy6sdkiHY8SGHFJEY+VkZA9tzrNH7t8gVXo0jPpXaL1WkaoTsousS0KNt4H/OWR8fRAqF4Ft+d3uXhKc2d54IJDoXgrb+DgbvXFTgFyrwj5fwozpmkAv4l4ns3YiWL9/7b+IpUDf9RuodjvUUm7PASs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909159; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=DkBQ+3UK9HWOhVq6Ht+r7CrNRq1WQFFe3oGX/Jg2oPM=; b=VRCKrTOC5GkPyxW9audbgOvNw+X225cj2fSDibLH+odMoJu1l5VYN/bbsamsotIKRdEJoigjExnD+dtJNg15QGT47juuG6xw0E31VjHHe+8q0yLYePq7QFdtUVoS7VGfX1FOLlXZMJ9ViKoOy+TYHX7/hKegTaZk5yNX2GuF5uM= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909158957358.5990176978713; Wed, 27 May 2026 12:12:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfs-0006Zw-MP; Wed, 27 May 2026 15:12:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfg-0006Wb-Fa for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:05 -0400 Received: from forwardcorp1a.mail.yandex.net ([2a02:6b8:c0e:500:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfb-0000ZZ-9H for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:04 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1a.mail.yandex.net (Yandex) with ESMTPS id E64D8C047E; Wed, 27 May 2026 22:11:54 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-c8yOarQc; Wed, 27 May 2026 22:11:54 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909114; bh=DkBQ+3UK9HWOhVq6Ht+r7CrNRq1WQFFe3oGX/Jg2oPM=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=o4yTz5n5peYFm4fFSn2srnan3XnxtM+PV73/6h8yP1i0qSPAJnCCEomlb8+9owdK1 Gxkdqw7RMxrkpUQ7eH4hPGLmdb32HX7oOeyO++xK0F/IzSjV3nXT6+fAq9JA/GoXfx VkZ/0rwfevh0AtX1uCXeM7IiYpwjbcVhNXxW3gIw= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 01/10] net/tap: move vhost-net open() calls to tap_parse_vhost_fds() Date: Wed, 27 May 2026 22:11:40 +0300 Message-ID: <20260527191150.250333-2-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c0e:500:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1a.mail.yandex.net X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909164909154100 Content-Type: text/plain; charset="utf-8" 1. Simplify code path: get vhostfds for all cases in one function. 2. Prepare for further tap-fd-migraton feature, when we'll need to postpone vhost initialization up to post-load stage. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Ben Chaney --- net/tap.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/net/tap.c b/net/tap.c index 57ffb09885c..d941c67895e 100644 --- a/net/tap.c +++ b/net/tap.c @@ -736,8 +736,7 @@ static bool net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, } } =20 - if (tap->has_vhost ? tap->vhost : - (vhostfd !=3D -1) || (tap->has_vhostforce && tap->vhostforce)) { + if (vhostfd !=3D -1) { VhostNetOptions options; =20 options.backend_type =3D VHOST_BACKEND_TYPE_KERNEL; @@ -747,17 +746,6 @@ static bool net_init_tap_one(const NetdevTapOptions *t= ap, NetClientState *peer, } else { options.busyloop_timeout =3D 0; } - - if (vhostfd =3D=3D -1) { - vhostfd =3D open("/dev/vhost-net", O_RDWR); - if (vhostfd < 0) { - error_setg_file_open(errp, errno, "/dev/vhost-net"); - goto failed; - } - if (!qemu_set_blocking(vhostfd, false, errp)) { - goto failed; - } - } options.opaque =3D (void *)(uintptr_t)vhostfd; options.nvqs =3D 2; options.feature_bits =3D kernel_feature_bits; @@ -843,14 +831,31 @@ static int tap_parse_fds_and_queues(const NetdevTapOp= tions *tap, int **fds, static bool tap_parse_vhost_fds(const NetdevTapOptions *tap, int **vhost_f= ds, int queues, Error **errp) { - if (!(tap->vhostfd || tap->vhostfds)) { + bool need_vhost =3D tap->has_vhost ? tap->vhost : + ((tap->vhostfd || tap->vhostfds) || + (tap->has_vhostforce && tap->vhostforce)); + + if (!need_vhost) { *vhost_fds =3D NULL; return true; } =20 - if (net_parse_fds(tap->vhostfd ?: tap->vhostfds, - vhost_fds, queues, errp) < 0) { - return false; + if (tap->vhostfd || tap->vhostfds) { + if (net_parse_fds(tap->vhostfd ?: tap->vhostfds, + vhost_fds, queues, errp) < 0) { + return false; + } + } else { + *vhost_fds =3D g_new(int, queues); + for (int i =3D 0; i < queues; i++) { + int vhostfd =3D open("/dev/vhost-net", O_RDWR); + if (vhostfd < 0) { + error_setg_file_open(errp, errno, "/dev/vhost-net"); + net_free_fds(*vhost_fds, i); + return false; + } + (*vhost_fds)[i] =3D vhostfd; + } } =20 if (!unblock_fds(*vhost_fds, queues, errp)) { --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909272; cv=none; d=zohomail.com; s=zohoarc; b=TAnuYVvwyR0/yLvQN0tl7Ge3wyP9rZ55RsqD9/KMQWadu+1Ah/9V72a49OtuSVsUOehCvWZjl9ecDwlCO0WUiLirAnYlA11Y1pAk9MES2SGSqnQHBN3qC8UWsjs+07T9NzsGAi20+Xup6TXel0awawC1UNXacI8MvPWDauH6e4c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909272; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MHNHKpsaKxEG/HXJGV9pieljiEBGn7ao27riAn99Abw=; b=BMwDihGLcM4Y+AeTX1GZ0bHNpCuWmVz0CAARvPKxfaCY0q8QO1rPqpQNGHNWXorHjtRHRtOQK5C73oGiDfGv/TAnG9UfvYUOtVbMqlJMLSrm6ViamNry01qqvH3fGR6LjX5Rz9McZWLVa0vM1N98MDWTk3sbS+LnOfECYRRz6dc= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909272081483.09485902388735; Wed, 27 May 2026 12:14:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJft-0006a0-9p; Wed, 27 May 2026 15:12:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfg-0006Wf-Nw for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:06 -0400 Received: from forwardcorp1a.mail.yandex.net ([2a02:6b8:c0e:500:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfb-0000Zp-5K for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:04 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1a.mail.yandex.net (Yandex) with ESMTPS id B0C1CC047F; Wed, 27 May 2026 22:11:55 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-Q1Rv4Iu3; Wed, 27 May 2026 22:11:55 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909115; bh=MHNHKpsaKxEG/HXJGV9pieljiEBGn7ao27riAn99Abw=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=J3dAx510Ei0jXLMTk5sSa2VyzqM1DagnOEXZDBNnJjZwYu9z1cDcBpe50ISTnkQmy s270D06bT2teg/2KdkJ5ua9r4Zh2M3dH35hzdElw5Mm1c1LM0UkZ5CUnKBhOA8PF6V cjIqHiIX0+hqDZYNjUjdZdUNODjZ+TsdTEdG87TM= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 02/10] net/tap: move vhost initialization to tap_setup_vhost() Date: Wed, 27 May 2026 22:11:41 +0300 Message-ID: <20260527191150.250333-3-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c0e:500:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1a.mail.yandex.net X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909274462158500 Content-Type: text/plain; charset="utf-8" Make a new helper function in a way it can be reused later for TAP fd-migration feature: we'll need to initialize vhost in a later point when we doesn't have access to QAPI parameters. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Ben Chaney --- net/tap.c | 62 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/net/tap.c b/net/tap.c index d941c67895e..9d6213fc3e5 100644 --- a/net/tap.c +++ b/net/tap.c @@ -71,6 +71,8 @@ static const int kernel_feature_bits[] =3D { typedef struct TAPState { NetClientState nc; int fd; + int vhostfd; + uint32_t vhost_busyloop_timeout; char down_script[1024]; char down_script_arg[128]; uint8_t buf[NET_BUFSIZE]; @@ -702,6 +704,38 @@ static int net_tap_init(const NetdevTapOptions *tap, i= nt *vnet_hdr, return fd; } =20 +static bool tap_setup_vhost(TAPState *s, Error **errp) +{ + VhostNetOptions options; + + if (s->vhostfd =3D=3D -1) { + return true; + } + + options.backend_type =3D VHOST_BACKEND_TYPE_KERNEL; + options.net_backend =3D &s->nc; + options.busyloop_timeout =3D s->vhost_busyloop_timeout; + options.opaque =3D (void *)(uintptr_t)s->vhostfd; + options.nvqs =3D 2; + 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; + options.is_vhost_user =3D false; + + s->vhost_net =3D vhost_net_init(&options); + if (!s->vhost_net) { + error_setg(errp, + "vhost-net requested but could not be initialized"); + return false; + } + + /* vhostfd ownership is passed to s->vhost_net */ + s->vhostfd =3D -1; + + return true; +} + static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *= peer, const char *name, const char *ifname, const char *script, @@ -736,30 +770,10 @@ static bool net_init_tap_one(const NetdevTapOptions *= tap, NetClientState *peer, } } =20 - if (vhostfd !=3D -1) { - VhostNetOptions options; - - options.backend_type =3D VHOST_BACKEND_TYPE_KERNEL; - options.net_backend =3D &s->nc; - if (tap->has_poll_us) { - options.busyloop_timeout =3D tap->poll_us; - } else { - options.busyloop_timeout =3D 0; - } - options.opaque =3D (void *)(uintptr_t)vhostfd; - options.nvqs =3D 2; - 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; - options.is_vhost_user =3D false; - - s->vhost_net =3D vhost_net_init(&options); - if (!s->vhost_net) { - error_setg(errp, - "vhost-net requested but could not be initialized"); - goto failed; - } + s->vhostfd =3D vhostfd; + s->vhost_busyloop_timeout =3D tap->has_poll_us ? tap->poll_us : 0; + if (!tap_setup_vhost(s, errp)) { + return false; } =20 return true; --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909164; cv=none; d=zohomail.com; s=zohoarc; b=hUb7KAhUD7lOS2rf1uDj+IQa/+tUo/ClmWAyUDaqPUjKa9ZbcIZWSq1MYuMp/XxDCDZYaeNytSxBP9GmGFimdlS3w/wdejJiMJ82g+CSen9Yz9bY3dknN505Xwd3S48xa+NlSOdipE6kbYFMNk7HG68nMu1Jjc4hm81kB1zHyCY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909164; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=FkJ+39JJrZL2MMO7uZCWxmwVVuaXC3dV0286OG0vwuY=; b=YKERLpuBXCJa/QnI+l4cPZhBx9sLifSWPUbpb4pb/djSTv3XAprDe63p5lVyhp4fwq3DuzUETDZs73vn0sV9yXvS57DEV/6lOLhSDoRJ9tSt2veeTNrWxaC9YQkf10aJcjirVQLrq9isbKLZy8qe472bbNT4+/9q/DFlf6CKpYk= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909163397589.0233585586352; Wed, 27 May 2026 12:12:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfg-0006WQ-DB; Wed, 27 May 2026 15:12:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfe-0006W6-GF for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:02 -0400 Received: from forwardcorp1b.mail.yandex.net ([178.154.239.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfb-0000a0-1k for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:02 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 909FF80821; Wed, 27 May 2026 22:11:56 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-WuODTbjc; Wed, 27 May 2026 22:11:55 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909115; bh=FkJ+39JJrZL2MMO7uZCWxmwVVuaXC3dV0286OG0vwuY=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=PNnnp/i7SJEvVZTlAM8tV2Jd0014SzblA7UAAQuqp9ZCm5h5KctcIxiD+wJaqKMbH STvL14RNA6690T7oxxIzs3LaZ0KRhA/T4WAq+OHMssau/LF++NYWiEljljtQf3nhIJ TzWw3zLapBJmtjSciLJUmJtSJq8OKuz2PY13KrMM= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 03/10] net/tap: use container_of instead of DO_UPCAST Date: Wed, 27 May 2026 22:11:42 +0300 Message-ID: <20260527191150.250333-4-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=178.154.239.136; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909167647158500 Content-Type: text/plain; charset="utf-8" We are going to QOMify tap backend, which includes deriving TAPState from Object. So "NetClientState nc" will not be a first member. Let's parepare for this change, and use container_of(), which will work regardless position of "nc" field. Signed-off-by: Vladimir Sementsov-Ogievskiy --- net/tap.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/net/tap.c b/net/tap.c index 9d6213fc3e5..5f45f2c6a31 100644 --- a/net/tap.c +++ b/net/tap.c @@ -155,7 +155,7 @@ static ssize_t tap_write_packet(TAPState *s, const stru= ct iovec *iov, int iovcnt static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); const struct iovec *iovp =3D iov; g_autofree struct iovec *iov_copy =3D NULL; struct virtio_net_hdr hdr =3D { }; @@ -191,7 +191,7 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int ma= xlen) =20 static void tap_send_completed(NetClientState *nc, ssize_t len) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); tap_read_poll(s, true); } =20 @@ -251,7 +251,7 @@ static void tap_send(void *opaque) =20 static bool tap_has_ufo(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); =20 @@ -260,7 +260,7 @@ static bool tap_has_ufo(NetClientState *nc) =20 static bool tap_has_uso(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); =20 @@ -269,7 +269,7 @@ static bool tap_has_uso(NetClientState *nc) =20 static bool tap_has_tunnel(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); return s->has_tunnel; @@ -277,7 +277,7 @@ static bool tap_has_tunnel(NetClientState *nc) =20 static bool tap_has_vnet_hdr(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); =20 @@ -291,7 +291,7 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, in= t len) =20 static void tap_set_vnet_hdr_len(NetClientState *nc, int len) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); =20 @@ -302,21 +302,21 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, = int len) =20 static int tap_set_vnet_le(NetClientState *nc, bool is_le) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 return tap_fd_set_vnet_le(s->fd, is_le); } =20 static int tap_set_vnet_be(NetClientState *nc, bool is_be) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 return tap_fd_set_vnet_be(s->fd, is_be); } =20 static void tap_set_offload(NetClientState *nc, const NetOffloads *ol) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); if (s->fd < 0) { return; } @@ -337,7 +337,7 @@ static void tap_exit_notify(Notifier *notifier, void *d= ata) =20 static void tap_cleanup(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); =20 if (s->vhost_net) { vhost_net_cleanup(s->vhost_net); @@ -361,14 +361,14 @@ static void tap_cleanup(NetClientState *nc) =20 static void tap_poll(NetClientState *nc, bool enable) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); tap_read_poll(s, enable); tap_write_poll(s, enable); } =20 static bool tap_set_steering_ebpf(NetClientState *nc, int prog_fd) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); =20 return tap_fd_set_steering_ebpf(s->fd, prog_fd) =3D=3D 0; @@ -376,7 +376,7 @@ static bool tap_set_steering_ebpf(NetClientState *nc, i= nt prog_fd) =20 int tap_get_fd(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); return s->fd; } @@ -388,7 +388,7 @@ int tap_get_fd(NetClientState *nc) */ static VHostNetState *tap_get_vhost_net(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); return s->vhost_net; } @@ -427,7 +427,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, =20 nc =3D qemu_new_net_client(&net_tap_info, peer, model, name); =20 - s =3D DO_UPCAST(TAPState, nc, nc); + s =3D container_of(nc, TAPState, nc); =20 s->fd =3D fd; s->host_vnet_hdr_len =3D vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; @@ -995,7 +995,7 @@ fail: =20 int tap_enable(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); int ret; =20 if (s->enabled) { @@ -1012,7 +1012,7 @@ int tap_enable(NetClientState *nc) =20 int tap_disable(NetClientState *nc) { - TAPState *s =3D DO_UPCAST(TAPState, nc, nc); + TAPState *s =3D container_of(nc, TAPState, nc); int ret; =20 if (s->enabled =3D=3D 0) { --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909159; cv=none; d=zohomail.com; s=zohoarc; b=RTIARrP5vixqdD0hsCpCIsKfJkmiqWEEnNJqgiNDT9+dGoj+Jin5dRHPJ+Z9JvlRTwxQ3Ii4dRSYoilhYnhf1VuBWHf3ZksZaqCSlse+zW22BQo77hFxc78Cqe2clG8C9uHSbf+7UhqN846XpKJrxlkYUMSJinjjhMgpwpMBii0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909159; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Tn6iBugiY55tK7Bw4pOLXlFAkxZ5yUtg5/3SvT5MguY=; b=RBtWKWs4PbHalUrn89z3eCCUj80Cj4PgJuCrCK0SgH6hQd2zQgZpC1bPjo25Bj76ByMRxV7iqk4Grtw2npf1pQi8gRhumz+BO5mFMDEb+p7w4xBRsDItYkKIHwCdpJEnCCH+3iQx9+SUOIt6Fl7Nui070wykK8t5BuPQLXth1cI= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909159117684.1652765567984; Wed, 27 May 2026 12:12:39 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfq-0006Z4-CV; Wed, 27 May 2026 15:12:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfg-0006Wd-KD for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:06 -0400 Received: from forwardcorp1b.mail.yandex.net ([178.154.239.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfc-0000aB-08 for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:04 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 6957A8084A; Wed, 27 May 2026 22:11:57 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-tNANKpqA; Wed, 27 May 2026 22:11:56 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909116; bh=Tn6iBugiY55tK7Bw4pOLXlFAkxZ5yUtg5/3SvT5MguY=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=xDKVe0jIKM1N4CpFKYvxtvb2r2qGvEBnTfZSqtf3fYnbcputx6r0s2O9QvPE4vdlm 2tqRWjUhvbJrYirkJRTuVBsVtER2U0DuQ7P5pMGtVM6EDUtT9xdcp5aSLwTokI2HW/ fZiogOErYGTAsuhec22XrDzJCwkrZR6YwYIB/+6o= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 04/10] net/tap: QOMify tap backend Date: Wed, 27 May 2026 22:11:43 +0300 Message-ID: <20260527191150.250333-5-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=178.154.239.136; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909163521158501 Content-Type: text/plain; charset="utf-8" We prepare for being able to migrate TAP backend. We'll need a user change-able property for it, which can be set from machine type. So, let's QOMify it first. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/net/net.h | 7 +++++++ include/net/tap.h | 2 ++ net/net.c | 14 +++++++------- net/tap.c | 48 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index 45bc86fc86b..bdf16bb3e64 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -160,6 +160,13 @@ char *qemu_mac_strdup_printf(const uint8_t *macaddr); NetClientState *qemu_find_netdev(const char *id); int qemu_find_net_clients_except(const char *id, NetClientState **ncs, NetClientDriver type, int max); +void qemu_net_client_setup(NetClientState *nc, + NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name, + NetClientDestructor *destructor, + bool is_datapath); NetClientState *qemu_new_net_client(NetClientInfo *info, NetClientState *peer, const char *model, diff --git a/include/net/tap.h b/include/net/tap.h index 6f34f13eae4..268570571f4 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -28,6 +28,8 @@ =20 #include "standard-headers/linux/virtio_net.h" =20 +#define TYPE_TAP_NETDEV "tap-netdev" + int tap_enable(NetClientState *nc); int tap_disable(NetClientState *nc); =20 diff --git a/net/net.c b/net/net.c index 2892f1730d1..a06558b75bf 100644 --- a/net/net.c +++ b/net/net.c @@ -261,13 +261,13 @@ static ssize_t qemu_deliver_packet_iov(NetClientState= *sender, int iovcnt, void *opaque); =20 -static void qemu_net_client_setup(NetClientState *nc, - NetClientInfo *info, - NetClientState *peer, - const char *model, - const char *name, - NetClientDestructor *destructor, - bool is_datapath) +void qemu_net_client_setup(NetClientState *nc, + NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name, + NetClientDestructor *destructor, + bool is_datapath) { nc->info =3D info; nc->model =3D g_strdup(model); diff --git a/net/tap.c b/net/tap.c index 5f45f2c6a31..9c04cd4770b 100644 --- a/net/tap.c +++ b/net/tap.c @@ -43,6 +43,7 @@ #include "qemu/main-loop.h" #include "qemu/sockets.h" #include "hw/virtio/vhost.h" +#include "qom/object.h" =20 #include "net/tap.h" #include "net/util.h" @@ -68,7 +69,11 @@ static const int kernel_feature_bits[] =3D { VHOST_INVALID_FEATURE_BIT }; =20 -typedef struct TAPState { +OBJECT_DECLARE_SIMPLE_TYPE(TAPState, TAP_NETDEV) + +struct TAPState { + Object parent_obj; + NetClientState nc; int fd; int vhostfd; @@ -86,7 +91,7 @@ typedef struct TAPState { VHostNetState *vhost_net; unsigned host_vnet_hdr_len; Notifier exit; -} TAPState; +}; =20 static void launch_script(const char *setup_script, const char *ifname, int fd, Error **errp); @@ -393,6 +398,19 @@ static VHostNetState *tap_get_vhost_net(NetClientState= *nc) return s->vhost_net; } =20 + +static const TypeInfo tap_netdev_info =3D { + .name =3D TYPE_TAP_NETDEV, + .parent =3D TYPE_OBJECT, + .instance_size =3D sizeof(TAPState), +}; + +static void tap_net_client_destructor(NetClientState *nc) +{ + TAPState *s =3D container_of(nc, TAPState, nc); + object_unref(OBJECT(s)); +} + /* fd support */ =20 static NetClientInfo net_tap_info =3D { @@ -415,6 +433,18 @@ static NetClientInfo net_tap_info =3D { .get_vhost_net =3D tap_get_vhost_net, }; =20 +static TAPState *new_tap(NetClientState *peer, + const char *model, + const char *name) +{ + TAPState *s =3D TAP_NETDEV(object_new(TYPE_TAP_NETDEV)); + + qemu_net_client_setup(&s->nc, &net_tap_info, peer, model, name, + tap_net_client_destructor, true); + + return s; +} + static TAPState *net_tap_fd_init(NetClientState *peer, const char *model, const char *name, @@ -422,12 +452,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, int vnet_hdr) { NetOffloads ol =3D {}; - NetClientState *nc; - TAPState *s; - - nc =3D qemu_new_net_client(&net_tap_info, peer, model, name); - - s =3D container_of(nc, TAPState, nc); + TAPState *s =3D new_tap(peer, model, name); =20 s->fd =3D fd; s->host_vnet_hdr_len =3D vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; @@ -1027,3 +1052,10 @@ int tap_disable(NetClientState *nc) return ret; } } + +static void tap_register_types(void) +{ + type_register_static(&tap_netdev_info); +} + +type_init(tap_register_types) --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909159; cv=none; d=zohomail.com; s=zohoarc; b=FO97DbzWgKmuIquUmIsrdBIjswbj4GIe2iMUm/lHnNreU6uQ7kBABKFcaavN7md0jpjClRV/fcXw1FQ3TRc6FInZ3Nnvonx8t1bkqkKpjRocrvlzjmGZkqOCwb3v8XeippZHsxnuB8oYxNhqacVH7MBXL3753mlD/isd5GMVeTo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909159; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=RfxqEWeC5J3TOrUYoue0YXr866vhpXJeCI5NgyUxaA4=; b=Oev6obWsvUWOgkc20hJ8MCHIBBChJcqr6eb+UWsx/8maYdfTGzcLkeXkJoOoRz9uV+gUu0r9xIdpMHwLNFkajuSNFAOV+CI/8mpHugnqxVRqRuqZXROKdCi4gXuWR7GmpdWDJuVDMECwLLZHTHQbotMg3hdIe5LV3ajLHV5VwwM= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909158957447.27231035775685; Wed, 27 May 2026 12:12:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfq-0006ZU-U5; Wed, 27 May 2026 15:12:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfg-0006We-KD for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:05 -0400 Received: from forwardcorp1a.mail.yandex.net ([2a02:6b8:c0e:500:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfb-0000aP-W9 for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:04 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1a.mail.yandex.net (Yandex) with ESMTPS id 3C585C0480; Wed, 27 May 2026 22:11:58 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-vixGv8dV; Wed, 27 May 2026 22:11:57 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909117; bh=RfxqEWeC5J3TOrUYoue0YXr866vhpXJeCI5NgyUxaA4=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=xhCN2TTXH4xAwDBobjtxPXzoT2Ezmj2dYGVZGgrdJ4dOnVZLq2thmDS1bfZ+d8hQD I87zmaOp5FbvJK/NBXSnSsGgxBPSDE++QptaOwI5v6KDZbDb80NZ3Ucb7mrW6DObq7 ZFh8kDU3v8m/seWRcdeTOgAO8qbm+WgPy9F9iWIo= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 05/10] net/tap: add TYPE_VMSTATE_IF interface Date: Wed, 27 May 2026 22:11:44 +0300 Message-ID: <20260527191150.250333-6-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c0e:500:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1a.mail.yandex.net X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909164946154100 Content-Type: text/plain; charset="utf-8" We'll need it to implement TAP backend live migration. Signed-off-by: Vladimir Sementsov-Ogievskiy --- net/tap.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/net/tap.c b/net/tap.c index 9c04cd4770b..529ed4b0f5b 100644 --- a/net/tap.c +++ b/net/tap.c @@ -43,7 +43,6 @@ #include "qemu/main-loop.h" #include "qemu/sockets.h" #include "hw/virtio/vhost.h" -#include "qom/object.h" =20 #include "net/tap.h" #include "net/util.h" @@ -91,6 +90,8 @@ struct TAPState { VHostNetState *vhost_net; unsigned host_vnet_hdr_len; Notifier exit; + + int queue_index; }; =20 static void launch_script(const char *setup_script, const char *ifname, @@ -399,10 +400,29 @@ static VHostNetState *tap_get_vhost_net(NetClientStat= e *nc) } =20 =20 +static char *tap_vmstate_if_get_id(VMStateIf *obj) +{ + TAPState *s =3D TAP_NETDEV(obj); + char *res =3D g_strdup_printf("%s/%d", s->nc.name, s->queue_index); + return res; +} + +static void tap_class_init(ObjectClass *klass, const void *data) +{ + VMStateIfClass *vc =3D VMSTATE_IF_CLASS(klass); + + vc->get_id =3D tap_vmstate_if_get_id; +} + static const TypeInfo tap_netdev_info =3D { .name =3D TYPE_TAP_NETDEV, .parent =3D TYPE_OBJECT, .instance_size =3D sizeof(TAPState), + .class_init =3D tap_class_init, + .interfaces =3D (const InterfaceInfo[]) { + { TYPE_VMSTATE_IF }, + { } + }, }; =20 static void tap_net_client_destructor(NetClientState *nc) @@ -435,13 +455,16 @@ static NetClientInfo net_tap_info =3D { =20 static TAPState *new_tap(NetClientState *peer, const char *model, - const char *name) + const char *name, + int queue_index) { TAPState *s =3D TAP_NETDEV(object_new(TYPE_TAP_NETDEV)); =20 qemu_net_client_setup(&s->nc, &net_tap_info, peer, model, name, tap_net_client_destructor, true); =20 + s->queue_index =3D queue_index; + return s; } =20 @@ -449,10 +472,11 @@ static TAPState *net_tap_fd_init(NetClientState *peer, const char *model, const char *name, int fd, - int vnet_hdr) + int vnet_hdr, + int queue_index) { NetOffloads ol =3D {}; - TAPState *s =3D new_tap(peer, model, name); + TAPState *s =3D new_tap(peer, model, name, queue_index); =20 s->fd =3D fd; s->host_vnet_hdr_len =3D vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; @@ -689,7 +713,7 @@ int net_init_bridge(const Netdev *netdev, const char *n= ame, close(fd); return -1; } - s =3D net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); + s =3D net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0); =20 qemu_set_info_str(&s->nc, "helper=3D%s,br=3D%s", helper, br); =20 @@ -765,10 +789,11 @@ static bool net_init_tap_one(const NetdevTapOptions *= tap, NetClientState *peer, const char *name, const char *ifname, const char *script, const char *downscript, int vhostfd, - int vnet_hdr, int fd, Error **errp) + int vnet_hdr, int fd, int queue_index, + Error **errp) { TAPState *s =3D net_tap_fd_init(peer, tap->helper ? "bridge" : "tap", - name, fd, vnet_hdr); + name, fd, vnet_hdr, queue_index); bool sndbuf_required =3D tap->has_sndbuf; int sndbuf =3D (tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT= _MAX; @@ -969,7 +994,7 @@ int net_init_tap(const Netdev *netdev, const char *name, if (!net_init_tap_one(tap, peer, name, ifname, NULL, NULL, vhost_fds ? vhost_fds[i] : -1, - vnet_hdr, fds[i], errp)) { + vnet_hdr, fds[i], i, errp)) { goto fail; } } @@ -1003,7 +1028,7 @@ int net_init_tap(const Netdev *netdev, const char *na= me, i >=3D 1 ? NULL : script, i >=3D 1 ? NULL : downscript, vhost_fds ? vhost_fds[i] : -1, - vnet_hdr, fd, errp)) { + vnet_hdr, fd, i, errp)) { goto fail; } } --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909201; cv=none; d=zohomail.com; s=zohoarc; b=hKLXcCtrj9cgEqEHLVESyXGUwQyJc2Vn/15ICDJ36B04CyKDq7M/dfnaJXIFwNEd6JRcWZVdIqHVcPJUts0nb0HfSdUjszXOoT1+56pDwEPJzk8qWkkoiK+d0A4C1ESmiDRGra92X1mpLJ701v3YASKAWV76xFfWznXX2GemxwI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909201; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KTp/pPAQgqp/zvkDHuiMwunwW4/ajjuB2DC44LrntNM=; b=cfFZZJh+pBsBLGfP4uGe4WR4g374Fhijgp9te02U8qPW/JrFJcXOc9vyqIIYZUVNys2/Ere7mi2Pp5sd202WdVXv005rWEUAgyL8wbxymKhYheyvouBYKNfZ3iY3iHOxXmqz0FtsQ46b2kDYVgOXG9Iuc39x6L9kXQHWvLBCs+U= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909201581555.1214563271349; Wed, 27 May 2026 12:13:21 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfm-0006Xt-3Q; Wed, 27 May 2026 15:12:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfi-0006Wo-0a for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:06 -0400 Received: from forwardcorp1b.mail.yandex.net ([178.154.239.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfc-0000ab-Ii for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:05 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 205588080A; Wed, 27 May 2026 22:11:59 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-VC5gNUvB; Wed, 27 May 2026 22:11:58 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909118; bh=KTp/pPAQgqp/zvkDHuiMwunwW4/ajjuB2DC44LrntNM=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=k6OUtrpmw2WD1WmTJF57YEwpPJIw4vtd+N1akarXjNIrkmYYVN6RH4eAIZa9LgRgF L44Oal9ir6QA6QdqHuYwJ+2xKq9jpO0XL1/PqPqaqXsteKICFHYK6FAodREA7aS3za DCwNC3VVaOeeEVi31T8pslSn0eTSOfdZZvB33zT8= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com, Eric Blake Subject: [PATCH v17 06/10] qapi: add local migration parameter Date: Wed, 27 May 2026 22:11:45 +0300 Message-ID: <20260527191150.250333-7-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=178.154.239.136; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909203560158500 Content-Type: text/plain; charset="utf-8" We are going to implement local-migration feature: some devices will be able to transfer open file descriptors through migration stream (which must UNIX domain socket for that purpose). This allows to transfer the whole backend state without reconnecting and restarting the backend service. For example, virtio-net will migrate its attached TAP netdev, together with its connected file descriptors. In this commit we introduce a migration parameter, which enables the feature for devices that support it (none at the moment). Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Markus Armbruster Acked-by: Peter Xu Reviewed-by: Ben Chaney --- include/migration/misc.h | 2 ++ migration/options.c | 18 +++++++++++++++++- qapi/migration.json | 12 ++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/migration/misc.h b/include/migration/misc.h index 3159a5e53c3..b14dc70ea3d 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -156,4 +156,6 @@ bool multifd_device_state_save_thread_should_exit(void); void multifd_abort_device_state_save_threads(void); bool multifd_join_device_state_save_threads(void); =20 +bool migrate_local(void); + #endif diff --git a/migration/options.c b/migration/options.c index 5cbfd29099b..ba5f9440a08 100644 --- a/migration/options.c +++ b/migration/options.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/units.h" +#include "qapi/util.h" #include "exec/target_page.h" #include "qapi/clone-visitor.h" #include "qapi/error.h" @@ -25,6 +26,7 @@ #include "migration/colo.h" #include "migration/cpr.h" #include "migration/misc.h" +#include "migration/options.h" #include "migration.h" #include "migration-stats.h" #include "qemu-file.h" @@ -348,6 +350,12 @@ bool migrate_mapped_ram(void) return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM]; } =20 +bool migrate_local(void) +{ + MigrationState *s =3D migrate_get_current(); + return s->parameters.local; +} + bool migrate_ignore_shared(void) { MigrationState *s =3D migrate_get_current(); @@ -1076,7 +1084,7 @@ static void migrate_mark_all_params_present(Migration= Parameters *p) &p->has_announce_step, &p->has_block_bitmap_mapping, &p->has_x_vcpu_dirty_limit_period, &p->has_vcpu_dirty_limit, &p->has_mode, &p->has_zero_page_detection, &p->has_direct_io, - &p->has_x_rdma_chunk_size, &p->has_cpr_exec_command, + &p->has_x_rdma_chunk_size, &p->has_cpr_exec_command, &p->has_local, }; =20 len =3D ARRAY_SIZE(has_fields); @@ -1424,6 +1432,10 @@ static void migrate_params_test_apply(MigrationParam= eters *params, qapi_free_strList(dest->cpr_exec_command); dest->cpr_exec_command =3D QAPI_CLONE(strList, params->cpr_exec_co= mmand); } + + if (params->has_local) { + dest->local =3D params->local; + } } =20 static void migrate_params_apply(MigrationParameters *params) @@ -1556,6 +1568,10 @@ static void migrate_params_apply(MigrationParameters= *params) s->parameters.cpr_exec_command =3D QAPI_CLONE(strList, params->cpr_exec_command); } + + if (params->has_local) { + s->parameters.local =3D params->local; + } } =20 void qmp_migrate_set_parameters(MigrationParameters *params, Error **errp) diff --git a/qapi/migration.json b/qapi/migration.json index 27a79705569..bc331815da0 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -836,7 +836,8 @@ 'zero-page-detection', 'direct-io', { 'name': 'x-rdma-chunk-size', 'features': [ 'unstable' ] }, - 'cpr-exec-command'] } + 'cpr-exec-command', + 'local'] } =20 ## # @migrate-set-parameters: @@ -1018,6 +1019,12 @@ # Must be set to the same value on both source and destination # before migration starts. (Since 11.1) # +# @local: Enable local migration for devices that support it. Backend +# state and its file descriptors can then be passed to the +# destination in the migration channel. The migration channel +# must be a Unix domain socket. Usually needs to be enabled per +# device. (Since 11.1) +# # Features: # # @unstable: Members @x-checkpoint-delay, @x-rdma-chunk-size, and @@ -1059,7 +1066,8 @@ '*direct-io': 'bool', '*x-rdma-chunk-size': { 'type': 'uint64', 'features': [ 'unstable' ] }, - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*local': 'bool' } } =20 ## # @query-migrate-parameters: --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909233; cv=none; d=zohomail.com; s=zohoarc; b=lecJZRYf41Lsuq6ttQXcE/BqStFZQWPPs2W6BNTwfyodmzvrGIM07oIeVcBVvtObQJXr60fWJ7aIPnfzje9Hv+IE5n7TWEdkbSdy0+JF8uxPD+EncWgUdK6mcQT3FyaYittcv0/jrIuaNK7nMM50ftLfQ4NQakDQLwld/diYIos= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909233; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jMkSOAnGpVRf0VTnJs7rx42AV58qrFern/G4h2ROPa0=; b=LmWKNkoHGkOdDzmBWUxIZTSr7tCi5Bt3SDntBtiOnubON6MXdAh57aPNxda0NM16I5jBAROQCat1uwfKpN+T78B7qs97YlBenKVAOQ63u4CxF5oomA4AHvU7IQ018gTQUI7qQG4kvBQxdUliEW/GCf04tYXUZDoBPTgKkugTn4k= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909233122859.3416241583218; Wed, 27 May 2026 12:13:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJft-0006ap-VR; Wed, 27 May 2026 15:12:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfi-0006XU-Gx for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:07 -0400 Received: from forwardcorp1b.mail.yandex.net ([178.154.239.136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfd-0000at-ED for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:06 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 1989688488; Wed, 27 May 2026 22:12:00 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-fwChcYum; Wed, 27 May 2026 22:11:59 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909119; bh=jMkSOAnGpVRf0VTnJs7rx42AV58qrFern/G4h2ROPa0=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=OS4i12R2TtoFW7B/ZJt8sCR7gXWkI+l4NPLDaf0KrS+qLeJ+ff0sCmej1LskJ9l2h rcG14I/K/fM2BgQ233S3aqs4hioXuYvqK7ZntAAwgDHfTbCve35TCCpMk951Kbqr0x Qn+nC2NoO3rSTOEq/mhQLGWGurR55iAG5C2Xba7A= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com Subject: [PATCH v17 07/10] virtio-net: support local migration of backend Date: Wed, 27 May 2026 22:11:46 +0300 Message-ID: <20260527191150.250333-8-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=178.154.239.136; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909236282154100 Content-Type: text/plain; charset="utf-8" Next commit will introduce live-migration (with fd-passing) for TAP net backend. So, now we prepare virtio-net for it Add virtio-net option local-migration, which is true by default, but false for older machine types, which doesn't support the feature. We introduce interface for live-migrating backends: 1. ->is_wait_incoming() handler, so that virtio-net knows, that backend is not fully intialized, as it waits for incoming migration stream. 2. MIG_PRI_BACKEND priority: backends should migrate with higher priority than virtio-net, so that we can do final preparations here in post-load handlers and be sure, that backends are already prepared. Signed-off-by: Vladimir Sementsov-Ogievskiy --- hw/net/virtio-net.c | 89 +++++++++++++++++++++++++++++++++- include/hw/virtio/virtio-net.h | 1 + include/migration/vmstate.h | 2 + include/net/net.h | 2 + 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 2a5d642a647..e23ae6052a2 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -40,6 +40,7 @@ #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" #include "system/system.h" +#include "system/runstate.h" #include "system/replay.h" #include "trace.h" #include "monitor/qdev.h" @@ -3060,7 +3061,17 @@ static void virtio_net_set_multiqueue(VirtIONet *n, = int multiqueue) n->multiqueue =3D multiqueue; virtio_net_change_num_queues(n, max * 2 + 1); =20 - virtio_net_set_queue_pairs(n); + /* + * virtio_net_set_multiqueue() called from set_features(0) on early + * reset, when peer may wait for incoming (and is not initialized + * yet). + * Don't worry about it: virtio_net_set_queue_pairs() will be called + * later from virtio_net_post_load_device(), and anyway will be + * no-op for local incoming migration with live backend passing. + */ + if (!n->peers_wait_incoming) { + virtio_net_set_queue_pairs(n); + } } =20 static int virtio_net_pre_load_queues(VirtIODevice *vdev, uint32_t n) @@ -3089,6 +3100,17 @@ static void virtio_net_get_features(VirtIODevice *vd= ev, uint64_t *features, =20 virtio_add_feature_ex(features, VIRTIO_NET_F_MAC); =20 + if (n->peers_wait_incoming) { + /* + * Excessive feature set is OK for early initialization when + * we wait for local incoming migration: actual guest-negotiated + * features will come with migration stream anyway. And we are sure + * that we support same host-features as source, because the backe= nd + * is the same (the same TAP device, for example). + */ + return; + } + if (!peer_has_vnet_hdr(n)) { virtio_clear_feature_ex(features, VIRTIO_NET_F_CSUM); virtio_clear_feature_ex(features, VIRTIO_NET_F_HOST_TSO4); @@ -3185,6 +3207,7 @@ static int virtio_net_post_load_device(void *opaque, = int version_id) VirtIODevice *vdev =3D VIRTIO_DEVICE(n); int i, link_down; bool has_tunnel_hdr =3D virtio_has_tunnel_hdr(vdev->guest_features_ex); + Error *local_err =3D NULL; =20 trace_virtio_net_post_load_device(); virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs, @@ -3242,6 +3265,20 @@ static int virtio_net_post_load_device(void *opaque,= int version_id) } =20 virtio_net_commit_rss_config(n); + + /* + * If live-migration is enabled for some backend, than backend + * has already been migrated at higher priority (MIG_PRI_BACKEND) + * and virtio_net_vnet_post_load() has already called + * peer_test_vnet_hdr(). Recompute host_features so that virtio-net + * reflects the capabilities of the restored backend. + */ + virtio_net_get_features(vdev, &vdev->host_features, &local_err); + if (local_err) { + error_report_err(local_err); + return -EINVAL; + } + return 0; } =20 @@ -3392,6 +3429,14 @@ static int virtio_net_vnet_post_load(void *opaque, i= nt version_id) { struct VirtIONetMigTmp *tmp =3D opaque; =20 + /* + * If live-migration is enabled for some backend, than backend + * has already been migrated at higher priority (MIG_PRI_BACKEND), + * so n->has_vnet_hdr can be refreshed from the live backend right + * here. + */ + peer_test_vnet_hdr(tmp->parent); + if (tmp->has_vnet_hdr && !peer_has_vnet_hdr(tmp->parent)) { error_report("virtio-net: saved image requires vnet_hdr=3Don"); return -EINVAL; @@ -3864,6 +3909,42 @@ static bool failover_hide_primary_device(DeviceListe= ner *listener, return qatomic_read(&n->failover_primary_hidden); } =20 +static bool virtio_net_check_peers_wait_incoming(VirtIONet *n, bool *waiti= ng, + Error **errp) +{ + bool has_waiting =3D false; + bool has_not_waiting =3D false; + + for (int i =3D 0; i < n->max_queue_pairs; i++) { + NetClientState *peer =3D n->nic->ncs[i].peer; + if (!peer) { + continue; + } + + if (peer->info->is_wait_incoming && + peer->info->is_wait_incoming(peer)) { + has_waiting =3D true; + } else { + has_not_waiting =3D true; + } + + if (has_waiting && has_not_waiting) { + error_setg(errp, "Mixed peer states: some peers wait for incom= ing " + "migration while others don't"); + return false; + } + } + + if (has_waiting && !runstate_check(RUN_STATE_INMIGRATE)) { + error_setg(errp, "Peers wait for incoming, but it's not an incomin= g " + "migration."); + return false; + } + + *waiting =3D has_waiting; + return true; +} + static void virtio_net_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); @@ -4001,6 +4082,12 @@ static void virtio_net_device_realize(DeviceState *d= ev, Error **errp) n->nic->ncs[i].do_not_pad =3D true; } =20 + if (!virtio_net_check_peers_wait_incoming(n, &n->peers_wait_incoming, + errp)) { + virtio_cleanup(vdev); + return; + } + peer_test_vnet_hdr(n); if (peer_has_vnet_hdr(n)) { n->host_hdr_len =3D sizeof(struct virtio_net_hdr); diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 371e3764282..8c967760c2a 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -230,6 +230,7 @@ struct VirtIONet { struct EBPFRSSContext ebpf_rss; uint32_t nr_ebpf_rss_fds; char **ebpf_rss_fds; + bool peers_wait_incoming; }; =20 size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 0a8a2e85a63..c92c41397ae 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -178,6 +178,8 @@ typedef enum { =20 MIG_PRI_LOW, /* Must happen after default */ MIG_PRI_DEFAULT, + MIG_PRI_BACKEND, /* Must happen before emulated devices, */ + /* e.g. virtio-net */ MIG_PRI_IOMMU, /* Must happen before PCI devices */ MIG_PRI_PCI_BUS, /* Must happen before IOMMU */ MIG_PRI_VIRTIO_MEM, /* Must happen before IOMMU */ diff --git a/include/net/net.h b/include/net/net.h index bdf16bb3e64..658b0d0aaf1 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -81,6 +81,7 @@ typedef void (SocketReadStateFinalize)(SocketReadState *r= s); typedef void (NetAnnounce)(NetClientState *); typedef bool (SetSteeringEBPF)(NetClientState *, int); typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error **); +typedef bool (IsWaitIncoming)(NetClientState *); typedef struct vhost_net *(GetVHostNet)(NetClientState *nc); =20 typedef struct NetClientInfo { @@ -109,6 +110,7 @@ typedef struct NetClientInfo { NetAnnounce *announce; SetSteeringEBPF *set_steering_ebpf; NetCheckPeerType *check_peer_type; + IsWaitIncoming *is_wait_incoming; GetVHostNet *get_vhost_net; } NetClientInfo; =20 --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909260; cv=none; d=zohomail.com; s=zohoarc; b=hFoPQzrCloSN26j1xSsK5r8RgVogo/cgeuBgfnsA0p81lTAgbyatx1m0b00rIxVpDZIda29/ycQYrIDNnzru54p5NktS7c0aqGGvjFpg8GVpwVItxUylnFP11HJFg8oCnHpTPa7sHRQnooeOnSeYuiGWUrRJMBwgotPR0b712+4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909260; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qx1Ad2zujHxdEpruVjFNJqpz2VqXBNkmIJc/XEc8578=; b=GB9mXI6JmsnGQzXjOeDWnxm28NB0yKYuDMUpvjh7stIUR8gMNfI15IK57HsISlibRMKsPWYR6FhIwZhUxEUjqbt4IZHdMZiLtaYrsIUBY5TTo5TLYnxH1cBNjrx5IKEm8qfDkPbglhZkFm5Qsts/Pj66v9yZCbca+7XPaze48SE= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909260380229.10849159914437; Wed, 27 May 2026 12:14:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJft-0006aK-DQ; Wed, 27 May 2026 15:12:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfk-0006Xo-9M for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:09 -0400 Received: from forwardcorp1b.mail.yandex.net ([2a02:6b8:c02:900:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJff-0000bD-Fw for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:07 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 7612A88481; Wed, 27 May 2026 22:12:01 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-7R18QPgU; Wed, 27 May 2026 22:12:00 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909120; bh=qx1Ad2zujHxdEpruVjFNJqpz2VqXBNkmIJc/XEc8578=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=Lmw7aQT0BGcEMIlA7uODtOQV7RjVQEW7ne8lYJk95HcQRFdR0gAmB0jQ3oWxusihI Cep8XI5QFv7d9hI2wdfbwlszRyGKpJXffg+1aOM8UBsIEAAqiu2JOCHqq5UDUyC7gL VE47yLeiTjUJKBDHiCSe7jPs/V9pq9oM2+S1KCaY= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhao Liu , Eric Blake Subject: [PATCH v17 08/10] net/tap: support local migration with virtio-net Date: Wed, 27 May 2026 22:11:47 +0300 Message-ID: <20260527191150.250333-9-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c02:900:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909264721154100 Content-Type: text/plain; charset="utf-8" Support transferring of TAP state (including open fd). Add new property "local-migration-supported", which defines, is local-migration is actually supported for this TAP device. Starting from 11.1 MT it's enabled by default. Note, that local-migration (including migrating opened FDs through migration channel, which must be UNIX socket), is enabled by global "local" migration parameters. But individual devices may have additional options to enable/disable it personally. Add new option "incoming-fds", which should be set to true on target for incoming migration work. It says "do not open any files, but instead wait for FDs coming from migration stream". "local-migration-supported" option is not enough, as it work in pair with migration parameter "local", and intialization process of TAP device should not depend on migration parameters. For new option require explicitly unset script and downscript, to keep possibility of implementing support for them in the future. Note disabling read polling on source stop for TAP migration: otherwise, source process may steal packages from TAP fd even after source vm STOP. Signed-off-by: Vladimir Sementsov-Ogievskiy --- hw/core/machine.c | 2 + net/tap.c | 221 +++++++++++++++++++++++++++++++++++++++++++--- qapi/net.json | 20 ++++- 3 files changed, 231 insertions(+), 12 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 63baff859f3..306f01b1a68 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -36,11 +36,13 @@ #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" #include "hw/virtio/virtio-iommu.h" +#include "net/tap.h" #include "hw/acpi/generic_event_device.h" #include "qemu/audio.h" =20 GlobalProperty hw_compat_11_0[] =3D { { "chardev-vc", "encoding", "cp437" }, + { TYPE_TAP_NETDEV, "local-migration-supported", "false" }, }; const size_t hw_compat_11_0_len =3D G_N_ELEMENTS(hw_compat_11_0); =20 diff --git a/net/tap.c b/net/tap.c index 529ed4b0f5b..c84daad9895 100644 --- a/net/tap.c +++ b/net/tap.c @@ -36,13 +36,19 @@ #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" +#include "system/runstate.h" #include "system/system.h" +#include "migration/misc.h" #include "qapi/error.h" #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qemu/sockets.h" #include "hw/virtio/vhost.h" +#include "hw/core/vmstate-if.h" +#include "migration/vmstate.h" +#include "qom/object.h" +#include "qom/compat-properties.h" =20 #include "net/tap.h" #include "net/util.h" @@ -70,6 +76,8 @@ static const int kernel_feature_bits[] =3D { =20 OBJECT_DECLARE_SIMPLE_TYPE(TAPState, TAP_NETDEV) =20 +static const VMStateDescription vmstate_tap; + struct TAPState { Object parent_obj; =20 @@ -92,6 +100,9 @@ struct TAPState { Notifier exit; =20 int queue_index; + bool read_poll_detached; + VMChangeStateEntry *vmstate; + bool local_migration_supported; }; =20 static void launch_script(const char *setup_script, const char *ifname, @@ -100,19 +111,25 @@ static void launch_script(const char *setup_script, c= onst char *ifname, static void tap_send(void *opaque); static void tap_writable(void *opaque); =20 +static bool tap_is_explicit_no_script(const char *script_arg) +{ + return script_arg && + (script_arg[0] =3D=3D '\0' || strcmp(script_arg, "no") =3D=3D 0); +} + static char *tap_parse_script(const char *script_arg, const char *default_= path) { g_autofree char *res =3D g_strdup(script_arg); =20 - if (!res) { - res =3D get_relocated_path(default_path); + if (tap_is_explicit_no_script(script_arg)) { + return NULL; } =20 - if (res[0] =3D=3D '\0' || strcmp(res, "no") =3D=3D 0) { - return NULL; + if (!script_arg) { + return get_relocated_path(default_path); } =20 - return g_steal_pointer(&res); + return g_strdup(script_arg); } =20 static void tap_update_fd_handler(TAPState *s) @@ -129,6 +146,23 @@ static void tap_read_poll(TAPState *s, bool enable) tap_update_fd_handler(s); } =20 +static void tap_vm_state_change(void *opaque, bool running, RunState state) +{ + TAPState *s =3D opaque; + + if (running) { + if (s->read_poll_detached) { + tap_read_poll(s, true); + s->read_poll_detached =3D false; + } + } else if (state =3D=3D RUN_STATE_FINISH_MIGRATE) { + if (s->read_poll) { + s->read_poll_detached =3D true; + tap_read_poll(s, false); + } + } +} + static void tap_write_poll(TAPState *s, bool enable) { s->write_poll =3D enable; @@ -359,10 +393,17 @@ static void tap_cleanup(NetClientState *nc) s->exit.notify =3D NULL; } =20 + if (s->vmstate) { + qemu_del_vm_change_state_handler(s->vmstate); + s->vmstate =3D NULL; + } + tap_read_poll(s, false); tap_write_poll(s, false); close(s->fd); s->fd =3D -1; + + vmstate_unregister(VMSTATE_IF(s), &vmstate_tap, s); } =20 static void tap_poll(NetClientState *nc, bool enable) @@ -399,6 +440,73 @@ static VHostNetState *tap_get_vhost_net(NetClientState= *nc) return s->vhost_net; } =20 +static bool tap_is_wait_incoming(NetClientState *nc) +{ + TAPState *s =3D container_of(nc, TAPState, nc); + assert(nc->info->type =3D=3D NET_CLIENT_DRIVER_TAP); + return s->fd =3D=3D -1; +} + +static int tap_pre_load(void *opaque) +{ + TAPState *s =3D opaque; + + if (s->fd !=3D -1) { + error_report( + "TAP is already initialized and cannot receive incoming fd"); + return -EINVAL; + } + + return 0; +} + +static bool tap_setup_vhost(TAPState *s, Error **errp); + +static int tap_post_load(void *opaque, int version_id) +{ + TAPState *s =3D opaque; + Error *local_err =3D NULL; + + tap_read_poll(s, true); + + if (s->fd < 0) { + return -1; + } + + if (!tap_setup_vhost(s, &local_err)) { + error_prepend(&local_err, + "Failed to setup vhost during TAP post-load: "); + error_report_err(local_err); + return -1; + } + + return 0; +} + +static bool tap_needed(void *opaque) +{ + TAPState *s =3D opaque; + + return s->local_migration_supported && migrate_local(); +} + +static const VMStateDescription vmstate_tap =3D { + .name =3D "net-tap", + .priority =3D MIG_PRI_BACKEND, + .pre_load =3D tap_pre_load, + .post_load =3D tap_post_load, + .needed =3D tap_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_FD(fd, TAPState), + VMSTATE_BOOL(using_vnet_hdr, TAPState), + VMSTATE_BOOL(has_ufo, TAPState), + VMSTATE_BOOL(has_uso, TAPState), + VMSTATE_BOOL(has_tunnel, TAPState), + VMSTATE_BOOL(enabled, TAPState), + VMSTATE_UINT32(host_vnet_hdr_len, TAPState), + VMSTATE_END_OF_LIST() + } +}; =20 static char *tap_vmstate_if_get_id(VMStateIf *obj) { @@ -407,17 +515,42 @@ static char *tap_vmstate_if_get_id(VMStateIf *obj) return res; } =20 +static bool tap_get_local_migration_supported_prop(Object *obj, Error **er= rp) +{ + TAPState *s =3D TAP_NETDEV(obj); + return s->local_migration_supported; +} + +static void tap_set_local_migration_supported_prop(Object *obj, bool value, + Error **errp) +{ + TAPState *s =3D TAP_NETDEV(obj); + s->local_migration_supported =3D value; +} + +static void tap_instance_init(Object *obj) +{ + TAPState *s =3D TAP_NETDEV(obj); + s->local_migration_supported =3D true; +} + static void tap_class_init(ObjectClass *klass, const void *data) { VMStateIfClass *vc =3D VMSTATE_IF_CLASS(klass); =20 vc->get_id =3D tap_vmstate_if_get_id; + + object_class_property_add_bool(klass, "local-migration-supported", + tap_get_local_migration_supported_prop, + tap_set_local_migration_supported_prop); } =20 static const TypeInfo tap_netdev_info =3D { .name =3D TYPE_TAP_NETDEV, .parent =3D TYPE_OBJECT, .instance_size =3D sizeof(TAPState), + .instance_init =3D tap_instance_init, + .instance_post_init =3D object_apply_compat_props, .class_init =3D tap_class_init, .interfaces =3D (const InterfaceInfo[]) { { TYPE_VMSTATE_IF }, @@ -450,13 +583,16 @@ 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, + .is_wait_incoming =3D tap_is_wait_incoming, .get_vhost_net =3D tap_get_vhost_net, }; =20 static TAPState *new_tap(NetClientState *peer, const char *model, const char *name, - int queue_index) + int queue_index, + bool has_local_migration_supported, + bool local_migration_supported) { TAPState *s =3D TAP_NETDEV(object_new(TYPE_TAP_NETDEV)); =20 @@ -465,6 +601,12 @@ static TAPState *new_tap(NetClientState *peer, =20 s->queue_index =3D queue_index; =20 + if (has_local_migration_supported) { + s->local_migration_supported =3D local_migration_supported; + } + + vmstate_register(VMSTATE_IF(s), VMSTATE_INSTANCE_ID_ANY, &vmstate_tap,= s); + return s; } =20 @@ -473,10 +615,14 @@ static TAPState *net_tap_fd_init(NetClientState *peer, const char *name, int fd, int vnet_hdr, - int queue_index) + int queue_index, + bool has_local_migration_supported, + bool local_migration_supported) { NetOffloads ol =3D {}; - TAPState *s =3D new_tap(peer, model, name, queue_index); + TAPState *s =3D new_tap(peer, model, name, queue_index, + has_local_migration_supported, + local_migration_supported); =20 s->fd =3D fd; s->host_vnet_hdr_len =3D vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; @@ -713,7 +859,7 @@ int net_init_bridge(const Netdev *netdev, const char *n= ame, close(fd); return -1; } - s =3D net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0); + s =3D net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0, true, fal= se); =20 qemu_set_info_str(&s->nc, "helper=3D%s,br=3D%s", helper, br); =20 @@ -793,11 +939,16 @@ static bool net_init_tap_one(const NetdevTapOptions *= tap, NetClientState *peer, Error **errp) { TAPState *s =3D net_tap_fd_init(peer, tap->helper ? "bridge" : "tap", - name, fd, vnet_hdr, queue_index); + name, fd, vnet_hdr, queue_index, + tap->has_local_migration_supported, + tap->local_migration_supported); bool sndbuf_required =3D tap->has_sndbuf; int sndbuf =3D (tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT= _MAX; =20 + s->read_poll_detached =3D false; + s->vmstate =3D qemu_add_vm_change_state_handler(tap_vm_state_change, s= ); + if (!tap_set_sndbuf(fd, sndbuf, sndbuf_required ? errp : NULL) && sndbuf_required) { goto failed; @@ -960,6 +1111,31 @@ int net_init_tap(const Netdev *netdev, const char *na= me, return -1; } =20 + if (tap->incoming_fds && + (tap->fd || tap->fds || tap->helper || tap->br || tap->ifname || + tap->has_sndbuf || tap->has_vnet_hdr)) { + error_setg(errp, "incoming-fds is incompatible with " + "fd=3D, fds=3D, helper=3D, br=3D, ifname=3D, sndbuf=3D = and vnet_hdr=3D"); + return -1; + } + + if (tap->incoming_fds && + !(tap_is_explicit_no_script(tap->script) && + tap_is_explicit_no_script(tap->downscript))) { + /* + * script=3D"" and downscript=3D"" are silently supported to be co= nsistent + * with cases without incoming_fds, but do not care to put this in= to + * error message. + */ + error_setg(errp, "incoming-fds requires script=3Dno and downscript= =3Dno"); + return -1; + } + + if (tap->incoming_fds && !runstate_check(RUN_STATE_INMIGRATE)) { + error_setg(errp, "incoming-fds requires -incoming commandline opti= on"); + return -1; + } + queues =3D tap_parse_fds_and_queues(tap, &fds, errp); if (queues < 0) { return -1; @@ -978,7 +1154,30 @@ int net_init_tap(const Netdev *netdev, const char *na= me, goto fail; } =20 - if (fds) { + if (tap->incoming_fds) { + for (i =3D 0; i < queues; i++) { + TAPState *s =3D new_tap(peer, "tap", name, i, + tap->has_local_migration_supported, + tap->local_migration_supported); + + if (!s->local_migration_supported) { + error_setg(errp, + "incoming-fds=3Dtrue requires local-migration-s= upported=3Dtrue"); + qemu_del_net_client(&s->nc); + return -1; + } + + qemu_set_info_str(&s->nc, "incoming"); + + s->fd =3D -1; + if (vhost_fds) { + s->vhostfd =3D vhost_fds[i]; + s->vhost_busyloop_timeout =3D tap->has_poll_us ? tap->poll= _us : 0; + } else { + s->vhostfd =3D -1; + } + } + } else if (fds) { for (i =3D 0; i < queues; i++) { if (i =3D=3D 0) { vnet_hdr =3D tap_probe_vnet_hdr(fds[i], errp); diff --git a/qapi/net.json b/qapi/net.json index 1a6382825c5..c5d87ba308b 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -425,6 +425,22 @@ # @poll-us: maximum number of microseconds that could be spent on busy # polling for tap (since 2.7) # +# @incoming-fds: do not open or create any TAP devices. Prepare for +# getting TAP file descriptors from incoming migration stream. +# The option is incompatible with any of @fd, @fds, @helper, @br, +# @ifname, @sndbuf and @vnet_hdr options, and requires @script and +# @downscript be explicitly set to nothing (empty string or "no"), +# and requires also @local-migration-supported to be true, "local" +# migration parameter be set as well, and QEMU being in incoming +# migration state. (Since 11.1) +# +# @local-migration-supported: enable local migration for this TAP +# backend. When set, local migration is enabled/disabled by +# "local" migration parameter for this TAP backend. When unset, +# "local" migration parameter is ignored for this TAP backend. +# (Since 11.1. Defaults to true for MT >=3D 11.1, and to false for +# MT < 11.1) +# # Since: 1.2 ## { 'struct': 'NetdevTapOptions', @@ -443,7 +459,9 @@ '*vhostfds': 'str', '*vhostforce': 'bool', '*queues': 'uint32', - '*poll-us': 'uint32'} } + '*poll-us': 'uint32', + '*incoming-fds': 'bool', + '*local-migration-supported': 'bool' } } =20 ## # @NetdevSocketOptions: --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909198; cv=none; d=zohomail.com; s=zohoarc; b=F5P26GqqEfQaZkcX4XW5BHNXxpxctuOh+OiPCqtG+IysdYVkmogckmOGFKdlC4pcCtt3wwoa2i4gFCCMdEVJzwJVOzvahSeNTo3kASbFIyVRpV0ntlknTM8lgcx5sonZoyKopNFo1daCdYdT0cVhjEyVZA395YMElnw7T/MVaUM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909198; 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=eUlFYRpVeapYCcmEi/9tpmjPFPyxSUveD1Zne0K2r8Y=; b=Rq5IXpPm1JEaDfz5DyFgxQRt7jvOQYi3GCxk3YZJxLgocrrujqfX1aC2+KRf0+xrG+Pr/6fj/N1+kprqbY/wcTX9AsoYjP6Xb35/ILn06eYZhO1HoYsUPi9LMzNpuUN4WCo+Jtg3if2GGaaYR7Vif3Xo1vUWPfyhhQilVfzNPoA= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909197960593.9358355473227; Wed, 27 May 2026 12:13:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfs-0006Zp-5X; Wed, 27 May 2026 15:12:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfk-0006Xm-8s for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:09 -0400 Received: from forwardcorp1b.mail.yandex.net ([2a02:6b8:c02:900:1:45:d181:df01]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfh-0000bQ-O7 for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:07 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTPS id 944088847E; Wed, 27 May 2026 22:12:02 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-DyInHQYx; Wed, 27 May 2026 22:12:01 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909122; bh=eUlFYRpVeapYCcmEi/9tpmjPFPyxSUveD1Zne0K2r8Y=; h=Cc:Message-ID:References:Date:In-Reply-To:Subject:To:From; b=ac41fSeoB6ii0nagoVeM7hiCzt9Wa5Fb2fPVz8wFmpP5LfXB93juELqdc7tCNmPhM j0ARjnPsd8exoidG7gEfovmteIK5rdxjS18XQNtTDkAZes16h1yszY3euh8stQxNxH WTvaryEtimOJF1mS5NYlzNn/1jQ5b0MwyL6ydSIo= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com, Thomas Huth , Lei Yang , Maksim Davydov , Thomas Huth , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v17 09/10] tests/functional: add skipWithoutSudo() decorator Date: Wed, 27 May 2026 22:11:48 +0300 Message-ID: <20260527191150.250333-10-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c02:900:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1b.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909202347154100 To be used in the next commit: that would be a test for TAP networking, and it will need to setup TAP device. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Daniel P. Berrang=C3=A9 Reviewed-by: Thomas Huth Tested-by: Lei Yang Reviewed-by: Maksim Davydov Reviewed-by: Ben Chaney --- tests/functional/qemu_test/decorators.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qe= mu_test/decorators.py index fcf236ecfdf..aa135acc785 100644 --- a/tests/functional/qemu_test/decorators.py +++ b/tests/functional/qemu_test/decorators.py @@ -6,6 +6,7 @@ import os import platform import resource +import subprocess from unittest import skipIf, skipUnless =20 from .cmd import which @@ -177,3 +178,18 @@ def skipLockedMemoryTest(locked_memory): ulimit_memory =3D=3D resource.RLIM_INFINITY or ulimit_memory >=3D = locked_memory * 1024, f'Test required {locked_memory} kB of available locked memory', ) + +''' +Decorator to skip execution of a test if passwordless +sudo command is not available. +''' +def skipWithoutSudo(): + proc =3D subprocess.run(["sudo", "-n", "/bin/true"], + stdin=3Dsubprocess.PIPE, + stdout=3Dsubprocess.PIPE, + stderr=3Dsubprocess.STDOUT, + universal_newlines=3DTrue, + check=3DFalse) + + return skipUnless(proc.returncode =3D=3D 0, + f'requires password-less sudo access: {proc.stdout}') --=20 2.52.0 From nobody Sat May 30 17:35:17 2026 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=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1779909258; cv=none; d=zohomail.com; s=zohoarc; b=W5O0dMNzyh5kziSkZiIqjizGUXsDSYEi4tBqE7cHEQHvd/VW7ULGSeeptC8doMlRtE6prDkJYhaqTc+myVXiSy+Z9yK4ZhBJcwWnDpBsYYNELnJ1mSSnmxoSwEOoArHJVi7YnXzhxAagrDBeNiQ6G0u8vBYLt2yDvM/Iyl6+654= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779909258; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jJlKQDXIfT0mwN96oQ516AKc8S4vKzFC7fJkk9M73Tc=; b=WWK4eao+VSGAKO4PUCyEoMxPahmoEpIC9KtUR3XjjYXtPFw3zowW0uwJ8gaXn/5+ey/ilL0zf46xgo+xSbrTRrjkL+nq7609VDzMmBCXDjCmHCPh0BKax9nZVc8xUQr3QcHJB1rRJXMckxqThSmxIufvZVBK0VRTjrt8L/gbasI= 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=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779909258504740.286724929041; Wed, 27 May 2026 12:14:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSJfr-0006ZY-2y; Wed, 27 May 2026 15:12:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfl-0006Xu-G1 for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:09 -0400 Received: from forwardcorp1a.mail.yandex.net ([178.154.239.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSJfh-0000bf-O7 for qemu-devel@nongnu.org; Wed, 27 May 2026 15:12:09 -0400 Received: from mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:2925:0:640:1f39:0]) by forwardcorp1a.mail.yandex.net (Yandex) with ESMTPS id C1C2FC0482; Wed, 27 May 2026 22:12:03 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:69::1:d]) by mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net (smtpcorp) with ESMTPSA id qBf3L80XU0U0-NW2RxciL; Wed, 27 May 2026 22:12:02 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1779909122; bh=jJlKQDXIfT0mwN96oQ516AKc8S4vKzFC7fJkk9M73Tc=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=tOaMrAwS+UtdlZI6C376XC0jRIjR8xPJWP0uaRnBBDYPu5ZQgzbuIONjqJr7MvzQz 5mBYJUFxNu6vzDALTTP6hMD+CT5ESsp+922Xwj0+3kFNN+XrR6sCz8bOswyrkgQICz /NGmbMAG7yNIAFzG85617/ysEDc/k5LNHnx+ZMco= Authentication-Results: mail-nwsmtp-smtp-corp-main-80.iva.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: armbru@redhat.com, peterx@redhat.com, farosas@suse.de, raphael.s.norwitz@gmail.com, bchaney@akamai.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org, berrange@redhat.com, pbonzini@redhat.com, yc-core@yandex-team.ru, mark.caveayland@nutanix.com, Zhao Liu Subject: [PATCH v17 10/10] tests/functional: add test_tap_migration Date: Wed, 27 May 2026 22:11:49 +0300 Message-ID: <20260527191150.250333-11-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260527191150.250333-1-vsementsov@yandex-team.ru> References: <20260527191150.250333-1-vsementsov@yandex-team.ru> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=lists1p.gnu.org; Received-SPF: pass client-ip=178.154.239.72; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1a.mail.yandex.net 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 List-Id: qemu development 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 @yandex-team.ru) X-ZM-MESSAGEID: 1779909260857154100 Content-Type: text/plain; charset="utf-8" Add test for a new local-migration migration of virtio-net/tap, with fd passing through UNIX socket. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Ben Chaney --- tests/functional/x86_64/meson.build | 1 + tests/functional/x86_64/test_tap_migration.py | 458 ++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100755 tests/functional/x86_64/test_tap_migration.py diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/= meson.build index 1ed10ad6c29..c4bb14f034b 100644 --- a/tests/functional/x86_64/meson.build +++ b/tests/functional/x86_64/meson.build @@ -45,4 +45,5 @@ tests_x86_64_system_thorough =3D [ 'virtio_balloon', 'virtio_gpu', 'rebuild_vmfd', + 'tap_migration', ] diff --git a/tests/functional/x86_64/test_tap_migration.py b/tests/function= al/x86_64/test_tap_migration.py new file mode 100755 index 00000000000..6c99cd82834 --- /dev/null +++ b/tests/functional/x86_64/test_tap_migration.py @@ -0,0 +1,458 @@ +#!/usr/bin/env python3 +# +# Functional test that tests TAP local migration +# with fd passing +# +# Copyright (c) Yandex Technologies LLC, 2026 +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time +import subprocess +from subprocess import run +import signal +import ctypes +import ctypes.util +import unittest +from contextlib import contextmanager, ExitStack +from typing import Tuple + +from qemu_test import ( + LinuxKernelTest, + Asset, + exec_command_and_wait_for_pattern, +) +from qemu_test.decorators import skipWithoutSudo + + +GUEST_IP =3D "192.168.100.2" +GUEST_IP_MASK =3D f"{GUEST_IP}/24" +GUEST_MAC =3D "d6:0d:75:f8:0f:b7" +HOST_IP =3D "192.168.100.1" +HOST_IP_MASK =3D f"{HOST_IP}/24" +TAP_ID =3D "tap0" +TAP_ID2 =3D "tap1" +TAP_MAC =3D "e6:1d:44:b5:03:5d" +NETNS =3D f"qemu_test_ns_{os.getpid()}" + + +def ip(args, check=3DTrue) -> None: + """Run ip command with sudo""" + run(["sudo", "ip"] + args, check=3Dcheck) + + +@contextmanager +def switch_netns(netns_name): + libc =3D ctypes.CDLL(ctypes.util.find_library("c")) + netns_path =3D f"/var/run/netns/{netns_name}" + + def switch_to_fd(fd, check: bool =3D False): + """Switch to netns by file descriptor""" + SYS_setns =3D 308 + CLONE_NEWNET =3D 0x40000000 + ret =3D libc.syscall(SYS_setns, fd, CLONE_NEWNET) + if check and ret !=3D 0: + raise RuntimeError("syscall SETNS failed") + + with ExitStack() as stack: + original_netns_fd =3D os.open("/proc/self/ns/net", os.O_RDONLY) + stack.callback(os.close, original_netns_fd) + + ip(["netns", "add", netns_name]) + stack.callback(ip, ["netns", "del", netns_name], check=3DFalse) + + new_netns_fd =3D os.open(netns_path, os.O_RDONLY) + stack.callback(os.close, new_netns_fd) + + switch_to_fd(new_netns_fd) + stack.callback(switch_to_fd, original_netns_fd, check=3DFalse) + + yield + + +def del_tap(tap_name: str =3D TAP_ID) -> None: + ip(["tuntap", "del", tap_name, "mode", "tap", "multi_queue"], check=3D= False) + + +def init_tap(tap_name: str =3D TAP_ID, with_ip: bool =3D True) -> None: + ip(["tuntap", "add", "dev", tap_name, "mode", "tap", "multi_queue"]) + if with_ip: + ip(["link", "set", "dev", tap_name, "address", TAP_MAC]) + ip(["addr", "add", HOST_IP_MASK, "dev", tap_name]) + ip(["link", "set", tap_name, "up"]) + + +def switch_network_to_tap2() -> None: + ip(["link", "set", TAP_ID2, "down"]) + ip(["link", "set", TAP_ID, "down"]) + ip(["addr", "delete", HOST_IP_MASK, "dev", TAP_ID]) + ip(["link", "set", "dev", TAP_ID2, "address", TAP_MAC]) + ip(["addr", "add", HOST_IP_MASK, "dev", TAP_ID2]) + ip(["link", "set", TAP_ID2, "up"]) + + +def parse_ping_line(line: str) -> float: + # suspect lines like + # [1748524876.590509] 64 bytes from 94.245.155.3 \ + # (94.245.155.3): icmp_seq=3D1 ttl=3D250 time=3D101 ms + spl =3D line.split() + return float(spl[0][1:-1]) + + +def parse_ping_output(out) -> Tuple[bool, float, float]: + lines =3D [x for x in out.split("\n") if x.startswith("[")] + + try: + first_no_ans =3D next( + (ind for ind in range(len(lines)) if lines[ind][20:26] =3D=3D = "no ans") + ) + except StopIteration: + return False, parse_ping_line(lines[0]), parse_ping_line(lines[-1]) + + last_no_ans =3D next( + ind + for ind in range(len(lines) - 1, -1, -1) + if lines[ind][20:26] =3D=3D "no ans" + ) + + return ( + True, + parse_ping_line(lines[first_no_ans]), + parse_ping_line(lines[last_no_ans]), + ) + + +def wait_migration_finish(source_vm, target_vm): + migr_events =3D ( + ("MIGRATION", {"data": {"status": "completed"}}), + ("MIGRATION", {"data": {"status": "failed"}}), + ) + + source_e =3D source_vm.events_wait(migr_events)["data"] + target_e =3D target_vm.events_wait(migr_events)["data"] + + source_s =3D source_vm.cmd("query-status")["status"] + target_s =3D target_vm.cmd("query-status")["status"] + + assert ( + source_e["status"] =3D=3D "completed" + and target_e["status"] =3D=3D "completed" + and source_s =3D=3D "postmigrate" + and target_s =3D=3D "paused" + ), f"""Migration failed: + SRC status: {source_s} + SRC event: {source_e} + TGT status: {target_s} + TGT event:{target_e}""" + + +@skipWithoutSudo() +class TAPFdMigration(LinuxKernelTest): + + ASSET_KERNEL =3D Asset( + ( + "https://archives.fedoraproject.org/pub/archive/fedora/linux/r= eleases" + "/31/Server/x86_64/os/images/pxeboot/vmlinuz" + ), + "d4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129", + ) + + ASSET_INITRD =3D Asset( + ( + "https://archives.fedoraproject.org/pub/archive/fedora/linux/r= eleases" + "/31/Server/x86_64/os/images/pxeboot/initrd.img" + ), + "277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b", + ) + + ASSET_ALPINE_ISO =3D Asset( + ( + "https://dl-cdn.alpinelinux.org/" + "alpine/v3.22/releases/x86_64/alpine-standard-3.22.1-x86_64.is= o" + ), + "96d1b44ea1b8a5a884f193526d92edb4676054e9fa903ad2f016441a0fe13089", + ) + + @classmethod + def setUpClass(cls): + super().setUpClass() + + try: + cls.netns_context =3D switch_netns(NETNS) + cls.netns_context.__enter__() + except (OSError, subprocess.CalledProcessError) as e: + raise unittest.SkipTest(f"can't switch network namespace: {e}") + + @classmethod + def tearDownClass(cls): + if hasattr(cls, "netns_context"): + cls.netns_context.__exit__(None, None, None) + super().tearDownClass() + + def setUp(self): + super().setUp() + + init_tap() + + self.outer_ping_proc =3D None + self.shm_path =3D None + + def tearDown(self): + try: + del_tap(TAP_ID) + del_tap(TAP_ID2) + + if self.outer_ping_proc: + self.stop_outer_ping() + + if self.shm_path: + os.unlink(self.shm_path) + finally: + super().tearDown() + + def start_outer_ping(self) -> None: + assert self.outer_ping_proc is None + self.outer_ping_log =3D self.scratch_file("ping.log") + with open(self.outer_ping_log, "w") as f: + self.outer_ping_proc =3D subprocess.Popen( + ["ping", "-i", "0", "-O", "-D", GUEST_IP], + text=3DTrue, + stdout=3Df, + ) + + def stop_outer_ping(self) -> str: + assert self.outer_ping_proc + self.outer_ping_proc.send_signal(signal.SIGINT) + + self.outer_ping_proc.communicate(timeout=3D5) + self.outer_ping_proc =3D None + + with open(self.outer_ping_log) as f: + return f.read() + + def stop_ping_and_check(self, stop_time, resume_time): + ping_res =3D self.stop_outer_ping() + + discon, a, b =3D parse_ping_output(ping_res) + + if not discon: + text =3D ( + f"STOP: {stop_time}, RESUME: {resume_time}," f"PING: {a} -= {b}" + ) + if a > stop_time or b < resume_time: + self.fail(f"PING failed: {text}") + self.log.info(f"PING: no packets lost: {text}") + return + + text =3D ( + f"STOP: {stop_time}, RESUME: {resume_time}," + f"PING: disconnect: {a} - {b}" + ) + self.log.info(text) + eps =3D 0.05 + if a < stop_time - eps or b > resume_time + eps: + self.fail(text) + + def one_ping_from_guest(self, vm) -> None: + exec_command_and_wait_for_pattern( + self, + f"ping -c 1 -W 1 {HOST_IP}", + "1 packets transmitted, 1 packets received", + "1 packets transmitted, 0 packets received", + vm=3Dvm, + ) + self.wait_for_console_pattern("# ", vm=3Dvm) + + def one_ping_from_host(self) -> None: + run( + ["ping", "-c", "1", "-W", "1", GUEST_IP], + stdout=3Dsubprocess.DEVNULL, + check=3DTrue, + ) + + def setup_shared_memory(self): + self.shm_path =3D f"/dev/shm/qemu_test_{os.getpid()}" + + try: + with open(self.shm_path, "wb") as f: + f.write(b"\0" * (1024 * 1024 * 1024)) # 1GB + except Exception as e: + self.fail(f"Failed to create shared memory file: {e}") + + def prepare_and_launch_vm( + self, shm_path, vhost, incoming=3DFalse, vm=3DNone, local=3DTrue + ): + if not vm: + vm =3D self.vm + + vm.set_console() + vm.add_args("-accel", "kvm") + vm.add_args("-device", "pcie-pci-bridge,id=3Dpci.1,bus=3Dpcie.0") + vm.add_args("-m", "1G") + + vm.add_args( + "-object", + f"memory-backend-file,id=3Dram0,size=3D1G,mem-path=3D{shm_path= },share=3Don", + ) + vm.add_args("-machine", "memory-backend=3Dram0") + + vm.add_args( + "-drive", + f"file=3D{self.ASSET_ALPINE_ISO.fetch()},media=3Dcdrom,format= =3Draw", + ) + + vm.add_args("-S") + + if incoming: + vm.add_args("-incoming", "defer") + + vm_s =3D "target" if incoming else "source" + self.log.info(f"Launching {vm_s} VM") + vm.launch() + + if not local: + tap_name =3D TAP_ID2 if incoming else TAP_ID + else: + tap_name =3D TAP_ID + + self.add_virtio_net(vm, vhost, tap_name, local, incoming) + + self.set_migration_capabilities(vm, local) + + def add_virtio_net( + self, vm, vhost: bool, tap_name: str, local: bool, incoming: bool + ): + incoming_fds =3D local and incoming + netdev_params =3D { + "id": "netdev.1", + "vhost": vhost, + "type": "tap", + "queues": 4, + "incoming-fds": incoming_fds, + "script": "no", + "downscript": "no", + "local-migration-supported": local, + } + + if not incoming_fds: + netdev_params["vnet_hdr"] =3D True + netdev_params["ifname"] =3D tap_name + + vm.cmd("netdev_add", netdev_params) + + vm.cmd( + "device_add", + driver=3D"virtio-net-pci", + romfile=3D"", + id=3D"vnet.1", + netdev=3D"netdev.1", + mq=3DTrue, + vectors=3D18, + bus=3D"pci.1", + mac=3DGUEST_MAC, + disable_legacy=3D"off", + ) + + def set_migration_capabilities(self, vm, local=3DTrue): + vm.cmd( + "migrate-set-capabilities", + { + "capabilities": [ + {"capability": "events", "state": True}, + {"capability": "x-ignore-shared", "state": True}, + ] + }, + ) + vm.cmd("migrate-set-parameters", {"local": local}) + + def setup_guest_network(self) -> None: + exec_command_and_wait_for_pattern(self, "ip addr", "# ") + exec_command_and_wait_for_pattern( + self, + f"ip addr add {GUEST_IP_MASK} dev eth0 && " + "ip link set eth0 up && echo OK", + "OK", + ) + self.wait_for_console_pattern("# ") + + def do_test_tap_fd_migration(self, vhost, local=3DTrue): + self.require_accelerator("kvm") + self.set_machine("q35") + + socket_dir =3D self.socket_dir() + migration_socket =3D os.path.join(socket_dir.name, "migration.sock= ") + + self.setup_shared_memory() + + # Setup second TAP if needed + if not local: + del_tap(TAP_ID2) + init_tap(TAP_ID2, with_ip=3DFalse) + + self.prepare_and_launch_vm(self.shm_path, vhost, local=3Dlocal) + self.vm.cmd("cont") + self.wait_for_console_pattern("login:") + exec_command_and_wait_for_pattern(self, "root", "# ") + + self.setup_guest_network() + + self.one_ping_from_guest(self.vm) + self.one_ping_from_host() + self.start_outer_ping() + + # Get some successful pings before migration + time.sleep(0.5) + + target_vm =3D self.get_vm(name=3D"target") + self.prepare_and_launch_vm( + self.shm_path, + vhost, + incoming=3DTrue, + vm=3Dtarget_vm, + local=3Dlocal, + ) + + target_vm.cmd("migrate-incoming", {"uri": f"unix:{migration_socket= }"}) + + self.log.info("Starting migration") + freeze_start =3D time.time() + self.vm.cmd("migrate", {"uri": f"unix:{migration_socket}"}) + + self.log.info("Waiting for migration completion") + wait_migration_finish(self.vm, target_vm) + + # Switch network to tap1 if not using local-migration + if not local: + switch_network_to_tap2() + + target_vm.cmd("cont") + freeze_end =3D time.time() + + self.vm.shutdown() + + self.log.info("Verifying PING on target VM after migration") + self.one_ping_from_guest(target_vm) + self.one_ping_from_host() + + # And a bit more pings after source shutdown + time.sleep(0.3) + self.stop_ping_and_check(freeze_start, freeze_end) + + target_vm.shutdown() + + def test_tap_fd_migration(self): + self.do_test_tap_fd_migration(False) + + def test_tap_fd_migration_vhost(self): + self.do_test_tap_fd_migration(True) + + def test_tap_new_tap_migration(self): + self.do_test_tap_fd_migration(False, local=3DFalse) + + def test_tap_new_tap_migration_vhost(self): + self.do_test_tap_fd_migration(True, local=3DFalse) + + +if __name__ =3D=3D "__main__": + LinuxKernelTest.main() --=20 2.52.0