From nobody Sat Feb 7 05:52:23 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=1769962862; cv=none; d=zohomail.com; s=zohoarc; b=LVgEQrQMFzsL17yz57v5/6LTz8MAIpjLkiVbMJp883rtMnKJNw/KZ25hsjzG9jGXPZ6uABqz+QCGZbw/2ZeI+vntNTZCejMTzPNml+P0jKZni+gvrOROxXUgWQGbEvyxwv8UA4DhUD1PMx0zsdY86SUmLrtA+ON7Ho0VnMImAj8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962862; 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=eke6p0O5s5amIMdSZpuJ4Ezrfqr3WEqzpErFVjEXg1Y=; b=WDCThNAYzuE4kb2YGLzpk3nhltJHiMV5W8+qyCQZKwGdeYI1YHMLiQAcJjZ8NC6I0O4ErdLxIFIZR36FfSgfbfd1VDEwX2ev3b35ZrxA7UNZfNf22UCWwUv8qHO1762UyQIOhvoCYUl58uqkwYlhwMwJD6X0rNc3lY0I8Hv/6A4= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962862690235.69527883763305; Sun, 1 Feb 2026 08:21:02 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBR-0001Bj-9F; Sun, 01 Feb 2026 11:20:21 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBM-00019l-Og for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from forwardcorp1d.mail.yandex.net ([2a02:6b8:c41:1300: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 1vmaBI-0005Xg-Io for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id B7E81807BD; Sun, 01 Feb 2026 19:20:08 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-qqHgTxWH; Sun, 01 Feb 2026 19:20:08 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962808; bh=eke6p0O5s5amIMdSZpuJ4Ezrfqr3WEqzpErFVjEXg1Y=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=emlGa0mmY+8Ym6es7hCdOzWMegH891jbN8QNbxFTjCkVOCR/hTg8MWdrAtYoILbmy SXQTSWiWsv9eYtlKHbeS1haZxSq0LK+bONbTAEIQz/tjtRvi6OR3zCIznoAgDY2RbJ WRWDseuIurwJ3lthrtCRoZnf/QyDwgpyTPl19iXk= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 1/8] net/tap: move vhost-net open() calls to tap_parse_vhost_fds() Date: Sun, 1 Feb 2026 19:19:53 +0300 Message-ID: <20260201162001.296328-2-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=2a02:6b8:c41:1300:1:45:d181:df01; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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: 1769962864826158500 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 --- net/tap.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/net/tap.c b/net/tap.c index 288cfedd81..d003b82142 100644 --- a/net/tap.c +++ b/net/tap.c @@ -738,8 +738,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; @@ -749,17 +748,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; @@ -841,13 +829,30 @@ 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, unsigned 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->fd ?: tap->fds, vhost_fds, queues, errp) < 0) { - return false; + if (tap->vhostfd || tap->vhostfds) { + if (net_parse_fds(tap->fd ?: tap->fds, vhost_fds, queues, errp) < = 0) { + return false; + } + } else if (!(tap->vhostfd || tap->vhostfds)) { + *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 Feb 7 05:52:23 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=1769962843; cv=none; d=zohomail.com; s=zohoarc; b=BdYY91odunwbNllNAX4xmQavOXwxnEY42RoplmCpiVChSHyDkY1OveAvrTpGErLuxNtSZr68Ke7mA5NK5HG85tSfwHjDt4XZYjPLJgwz5nsUw9PM+zuZcPJWMwN2Ivpwmyl4TBpkdrB5BA5pUmrwomvc7QcXMIL/WWk3e6qMKpQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962843; 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=j0wdKdaZ3JhTN4OZ4woAPlqYZxZB2pgPq4Wx2ZcwoJs=; b=bFNvPHj1ydVMVQ3Pu3YeMceay4Q+kyrtHScnr1Oud7LnKL42Q+XlxJDfYyCieVxo1mhMPLSP0ZntMQKSuP9JdxDGQEib6UXPbF2B523I9LFFS2V4djChC/mnSKXGM4oUMTbMnYvs5Er8idx3J4lP4H3X9wxEhCF5HE6GoFIY2z0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176996284217399.0916438460481; Sun, 1 Feb 2026 08:20:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBS-0001Br-QJ; Sun, 01 Feb 2026 11:20:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBM-00019k-Nw for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBI-0005Xw-Go for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id E18B0807B2; Sun, 01 Feb 2026 19:20:09 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-qssyeVHN; Sun, 01 Feb 2026 19:20:09 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962809; bh=j0wdKdaZ3JhTN4OZ4woAPlqYZxZB2pgPq4Wx2ZcwoJs=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=a73vmIzPUIBoXeEIQ0nvg3I+yEzOtmQCx1vND+1MENP3jqeNNxHU+xxCAsXzvMmO4 fn/gTWFKC5zX+5nbaVOfpq4YJaFraEMDvxXp4JA4ucQsT9TA5YszKdR87wVg2TRiQG lIUWxlG5MckXQasd/InH26OFtT8htXmbPJLD1/zs= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 2/8] net/tap: move vhost initialization to tap_setup_vhost() Date: Sun, 1 Feb 2026 19:19:54 +0300 Message-ID: <20260201162001.296328-3-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962846086158500 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 --- net/tap.c | 62 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/net/tap.c b/net/tap.c index d003b82142..bd19c71c42 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]; @@ -704,6 +706,38 @@ static int net_tap_init(const NetdevTapOptions *tap, i= nt *vnet_hdr, =20 #define MAX_TAP_QUEUES 1024 =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, @@ -738,30 +772,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 Feb 7 05:52:23 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=1769962842; cv=none; d=zohomail.com; s=zohoarc; b=JegospF8Rhvm9aV5PJrwwpcxx6fC5h2ziAZ+LAz76r279sBgHVSMP8yl7Jr2kAC6OJ3n2re6QiQS9xtBYuSX27wCtB8gC/CN+CTPpJjDOo793hjzaHVGQyvIsqPywh0Mf+YFvqVcISdqqWbBtKKsTKAZTqBJasL7CUUqyRb2Eis= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962842; 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=AIepM3J8V/vaTzwRFdY0iEBThQ1LNyZOI1AMBNNUhgc=; b=euean59nktkH5f1amKdHt0ksVey4XuPrpgTEi6Ok/LEBe3o1X9DABlM+1BHYNyQEsl1xDCQ9AptC4VHDdQKLhXpIUqT0A1ZXD9ycHTITlLYYuYynDdQW7fUWDMwgzKSIP5ZPxx1Sil1SCsjDY1szkmk1hOpkgX2ntKm4p3NSkuU= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962841893271.15750834361063; Sun, 1 Feb 2026 08:20:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBN-00019y-Hx; Sun, 01 Feb 2026 11:20:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBL-00019Q-Er for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:15 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBI-0005YB-Hd for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:15 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id C468D807CC; Sun, 01 Feb 2026 19:20:10 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-MSCfCKtD; Sun, 01 Feb 2026 19:20:10 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962810; bh=AIepM3J8V/vaTzwRFdY0iEBThQ1LNyZOI1AMBNNUhgc=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=VfIMG6ILbdqIu9i6xu6aisGwmFuWk19tx6DY4N+HmiaRMjdHBRWLgLq6OtYTgGD4I uGLxlQ9SqTqPYeTWATO3MYS2EMMluwUCbafMh8xy29+K53wbEmZQlKctIbKqMRAIAb pFyzYosjVLwsYaxW+aCSSdpipYMAFY3w091Nj5xU= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 3/8] qapi: add backend-transfer migration parameter Date: Sun, 1 Feb 2026 19:19:55 +0300 Message-ID: <20260201162001.296328-4-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962846249158500 Content-Type: text/plain; charset="utf-8" We are going to implement backend-transfer feature: some devices will be able to transfer their backend through migration stream for local migration through UNIX domain socket. For example, virtio-net will migrate its attached TAP netdev, with all its connected file descriptors. In this commit we introduce a migration parameter, which enables the feature, for supporting devices (no one at the moment). Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Markus Armbruster Acked-by: Peter Xu --- include/migration/misc.h | 2 ++ migration/options.c | 18 +++++++++++++++++- qapi/migration.json | 13 +++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/migration/misc.h b/include/migration/misc.h index e26d418a6e..f23a4d8b59 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -152,4 +152,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_backend_transfer(void); + #endif diff --git a/migration/options.c b/migration/options.c index 1ffe85a2d8..a4c9e68457 100644 --- a/migration/options.c +++ b/migration/options.c @@ -13,6 +13,7 @@ =20 #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qapi/util.h" #include "exec/target_page.h" #include "qapi/clone-visitor.h" #include "qapi/error.h" @@ -24,6 +25,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" @@ -336,6 +338,12 @@ bool migrate_mapped_ram(void) return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM]; } =20 +bool migrate_backend_transfer(void) +{ + MigrationState *s =3D migrate_get_current(); + return s->parameters.backend_transfer; +} + bool migrate_ignore_shared(void) { MigrationState *s =3D migrate_get_current(); @@ -1047,7 +1055,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_cpr_exec_command, + &p->has_cpr_exec_command, &p->has_backend_transfer, }; =20 len =3D ARRAY_SIZE(has_fields); @@ -1386,6 +1394,10 @@ static void migrate_params_test_apply(MigrationParam= eters *params, if (params->has_cpr_exec_command) { dest->cpr_exec_command =3D params->cpr_exec_command; } + + if (params->has_backend_transfer) { + dest->backend_transfer =3D params->backend_transfer; + } } =20 static void migrate_params_apply(MigrationParameters *params) @@ -1514,6 +1526,10 @@ static void migrate_params_apply(MigrationParameters= *params) s->parameters.cpr_exec_command =3D QAPI_CLONE(strList, params->cpr_exec_command); } + + if (params->has_backend_transfer) { + s->parameters.backend_transfer =3D params->backend_transfer; + } } =20 void qmp_migrate_set_parameters(MigrationParameters *params, Error **errp) diff --git a/qapi/migration.json b/qapi/migration.json index f925e5541b..cbe88f0c91 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -828,7 +828,8 @@ 'mode', 'zero-page-detection', 'direct-io', - 'cpr-exec-command'] } + 'cpr-exec-command', + 'backend-transfer'] } =20 ## # @migrate-set-parameters: @@ -1004,6 +1005,13 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: Enable backend-transfer feature for devices that +# supports it. In general that means that backend state and its +# file descriptors are passed to the destination in the migraton +# channel (which must be a UNIX socket). Individual devices +# declare the support for backend-transfer by per-device +# backend-transfer option. (Since 11.0) +# # Features: # # @unstable: Members @x-checkpoint-delay and @@ -1043,7 +1051,8 @@ '*mode': 'MigMode', '*zero-page-detection': 'ZeroPageDetection', '*direct-io': 'bool', - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*backend-transfer': 'bool' } } =20 ## # @query-migrate-parameters: --=20 2.52.0 From nobody Sat Feb 7 05:52:23 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=1769962862; cv=none; d=zohomail.com; s=zohoarc; b=cKHxWJfghZBMjSPgLKhS1dN3HyPADiuErp35cBmSaKyKVRUrNYUeJH63pPz8lsK6vbJmz4mIEbHSjvNwuygSKEKpyebOdbsmG07ZhHshGtIXRIVWnqRXMgYx/xaxEfPM4YWRpXXLblLUrJ7gfLH3+0W7ht2GU+SNhAJKRNM25M4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962862; 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=3FQTYV0oeBjEz+LJ2Xf+QTLx28lfTEWd/fh896lYb3E=; b=mG7taw3Bq6EvutHdQW0TSeyMZZdCY9mj5152vCVFsRZswQXlekaZquLJZAkqhCj9Ujey9b6onlZF54G8z1jRVT2iDhpbcfgSmCFeNLOubJnxGZ+/RdXFTTI47LOp4mRZJ661UbIrLb2bGIzU+UBMbSJ7+HU4CWztXi5OAvSjQcY= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962862920281.33335087191404; Sun, 1 Feb 2026 08:21:02 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBU-0001CG-AA; Sun, 01 Feb 2026 11:20:24 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBM-00019m-QF for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBJ-0005YM-Py for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:16 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 6FA43807D1; Sun, 01 Feb 2026 19:20:11 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-P8W3mn5K; Sun, 01 Feb 2026 19:20:11 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962811; bh=3FQTYV0oeBjEz+LJ2Xf+QTLx28lfTEWd/fh896lYb3E=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=SNRHGzA7MeX0+vnzt4Mgv+9rlD5AwK8dHTnu4A6nBEYGhmUdZ64xMgRXBXDHz3tZo YzDO7Uuf/jR+EjvIksCxGzr5oSyh7SUgSANyTHwvraHwpIkQzbUvm5k/cpOzw8AarF oNVeNBU9/zbBSbtDkZjuq/HnvgH73UqadauZXD0c= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 4/8] net: introduce vmstate_net_peer_backend Date: Sun, 1 Feb 2026 19:19:56 +0300 Message-ID: <20260201162001.296328-5-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962864704158500 Content-Type: text/plain; charset="utf-8" To implement backend-transfer migration in virtio-net in the next commit, we need a generic API to migrate net backend. Here is it. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/net/net.h | 4 ++++ net/net.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/net/net.h b/include/net/net.h index 45bc86fc86..aa34043b1a 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -5,6 +5,7 @@ #include "qapi/qapi-types-net.h" #include "net/queue.h" #include "hw/core/qdev-properties-system.h" +#include "migration/vmstate.h" =20 #define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X" #define MAC_ARG(x) ((uint8_t *)(x))[0], ((uint8_t *)(x))[1], \ @@ -110,6 +111,7 @@ typedef struct NetClientInfo { SetSteeringEBPF *set_steering_ebpf; NetCheckPeerType *check_peer_type; GetVHostNet *get_vhost_net; + const VMStateDescription *backend_vmsd; } NetClientInfo; =20 struct NetClientState { @@ -354,4 +356,6 @@ static inline bool net_peer_needs_padding(NetClientStat= e *nc) return nc->peer && !nc->peer->do_not_pad; } =20 +extern const VMStateInfo vmstate_net_peer_backend; + #endif diff --git a/net/net.c b/net/net.c index a176936f9b..58e11b9597 100644 --- a/net/net.c +++ b/net/net.c @@ -58,6 +58,7 @@ #include "qapi/string-output-visitor.h" #include "qapi/qobject-input-visitor.h" #include "standard-headers/linux/virtio_net.h" +#include "migration/vmstate.h" =20 /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) @@ -2173,3 +2174,49 @@ int net_fill_rstate(SocketReadState *rs, const uint8= _t *buf, int size) assert(size =3D=3D 0); return 0; } + +static int get_peer_backend(QEMUFile *f, void *pv, size_t size, + const VMStateField *field) +{ + NetClientState *nc =3D pv; + Error *local_err =3D NULL; + int ret; + + if (!nc->peer) { + return -EINVAL; + } + nc =3D nc->peer; + + ret =3D vmstate_load_state(f, nc->info->backend_vmsd, nc, 0, &local_er= r); + if (ret < 0) { + error_report_err(local_err); + } + + return ret; +} + +static int put_peer_backend(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmdesc) +{ + NetClientState *nc =3D pv; + Error *local_err =3D NULL; + int ret; + + if (!nc->peer) { + return -EINVAL; + } + nc =3D nc->peer; + + ret =3D vmstate_save_state(f, nc->info->backend_vmsd, nc, 0, &local_er= r); + if (ret < 0) { + error_report_err(local_err); + } + + return ret; +} + +const VMStateInfo vmstate_net_peer_backend =3D { + .name =3D "virtio-net-nic-nc-backend", + .get =3D get_peer_backend, + .put =3D put_peer_backend, +}; --=20 2.52.0 From nobody Sat Feb 7 05:52:23 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=1769962877; cv=none; d=zohomail.com; s=zohoarc; b=dzJ4tgRorSlxTnfctcvtf1BvzenNp/x+S0gRG1k+iyCidd4XJdsqcCXNNtqq5sUtN5quto4i0XX9C8jXQLRWipFuEATBJcwZTXPnkztmgOat+Fw9iVOIBxbwh1V1urfozX3gvjWMBW4QfM+w6QD/4zR4WQafqraZNpW9A3bY5xk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962877; 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=SwD49Svyd1/6kpEmGERECJwjoVPTQ54wE2SU9wfUGPo=; b=XWBvRPCub31ni8YnS3ZnH+J0yH7DxnyvgdmKK7ugwachH2rO7qJ06CXhptiXOI6iP2SO8LyHuAhzYFaXSYjWBuu7GBsN42EkrArrMa8f4AARImoAxrVol3BqPFhiga1ZuVo7iZICVx1mpQ60ZmfM82nCyL4M5Tg3+hWq+rY4GB8= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962877546406.54726098651986; Sun, 1 Feb 2026 08:21:17 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBV-0001Cu-Ci; Sun, 01 Feb 2026 11:20:25 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBO-0001AZ-C2 for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:18 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBJ-0005YT-Pr for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:18 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 3D302807DC; Sun, 01 Feb 2026 19:20:12 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-gTbaFVOH; Sun, 01 Feb 2026 19:20:11 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962811; bh=SwD49Svyd1/6kpEmGERECJwjoVPTQ54wE2SU9wfUGPo=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=Vih7Kftq2FvUwEhSJrFBnmY8ZYDWm4yXRpJdMMxwXzqCkMX3021gTH4H5sjlYdQa2 +zuXzBr1KCCxOHCgBkRP+8B8ML22ogrEpBylqlb4OxDGA2rju1upjAEWm8cc3VVCwm inYJm6Zyn3fu3Ar4JNrtzYbGfHMDEf9PAwpAnol4= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 5/8] virtio-net: support backend-transfer migration Date: Sun, 1 Feb 2026 19:19:57 +0300 Message-ID: <20260201162001.296328-6-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962878526158500 Content-Type: text/plain; charset="utf-8" Add virtio-net option backend-transfer, which is true by default, but false for older machine types, which doesn't support the feature. For backend-transfer migration, both global migration parameter backend-transfer and virtio-net backend-transfer option should be set to true. With the parameters enabled (both on source and target, of-course), and with unix-socket used as migration-channel, we do "migrate" the virtio-net backend - TAP device, with all its fds. This way management tool should not care about creating new TAP, and should not handle switching to it. Migration downtime become shorter. Support for TAP will come in the next commit. Signed-off-by: Vladimir Sementsov-Ogievskiy --- hw/core/machine.c | 4 +- hw/net/virtio-net.c | 137 ++++++++++++++++++++++++++++++++- include/hw/virtio/virtio-net.h | 2 + include/net/net.h | 2 + 4 files changed, 143 insertions(+), 2 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 6411e68856..cc99287232 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -38,7 +38,9 @@ #include "hw/acpi/generic_event_device.h" #include "qemu/audio.h" =20 -GlobalProperty hw_compat_10_2[] =3D {}; +GlobalProperty hw_compat_10_2[] =3D { + { TYPE_VIRTIO_NET, "backend-transfer", "false" }, +}; const size_t hw_compat_10_2_len =3D G_N_ELEMENTS(hw_compat_10_2); =20 GlobalProperty hw_compat_10_1[] =3D { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 512a7c02c9..9e3f75031a 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -38,8 +38,10 @@ #include "qapi/qapi-events-migration.h" #include "hw/virtio/virtio-access.h" #include "migration/misc.h" +#include "migration/options.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" @@ -3061,7 +3063,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 form virtio_net_post_load_device(), and anyway will be + * noop 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) @@ -3090,6 +3102,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); @@ -3181,6 +3204,18 @@ static void virtio_net_get_features(VirtIODevice *vd= ev, uint64_t *features, } } =20 +static bool virtio_net_update_host_features(VirtIONet *n, Error **errp) +{ + ERRP_GUARD(); + VirtIODevice *vdev =3D VIRTIO_DEVICE(n); + + peer_test_vnet_hdr(n); + + virtio_net_get_features(vdev, &vdev->host_features, errp); + + return !*errp; +} + static int virtio_net_post_load_device(void *opaque, int version_id) { VirtIONet *n =3D opaque; @@ -3302,6 +3337,9 @@ struct VirtIONetMigTmp { uint16_t curr_queue_pairs_1; uint8_t has_ufo; uint32_t has_vnet_hdr; + + NetClientState *ncs; + uint32_t max_queue_pairs; }; =20 /* The 2nd and subsequent tx_waiting flags are loaded later than @@ -3571,6 +3609,57 @@ static const VMStateDescription vhost_user_net_backe= nd_state =3D { } }; =20 +static bool virtio_net_is_backend_transfer(void *opaque, int version_id) +{ + VirtIONet *n =3D opaque; + + return migrate_backend_transfer() && n->backend_transfer; +} + +static int virtio_net_nic_pre_save(void *opaque) +{ + struct VirtIONetMigTmp *tmp =3D opaque; + + tmp->ncs =3D tmp->parent->nic->ncs; + tmp->max_queue_pairs =3D tmp->parent->max_queue_pairs; + + return 0; +} + +static int virtio_net_nic_pre_load(void *opaque) +{ + /* Reuse the pointer setup from save */ + virtio_net_nic_pre_save(opaque); + + return 0; +} + +static int virtio_net_nic_post_load(void *opaque, int version_id) +{ + struct VirtIONetMigTmp *tmp =3D opaque; + Error *local_err =3D NULL; + + if (!virtio_net_update_host_features(tmp->parent, &local_err)) { + error_report_err(local_err); + return -EINVAL; + } + + return 0; +} + +static const VMStateDescription vmstate_virtio_net_nic =3D { + .name =3D "virtio-net-nic", + .pre_load =3D virtio_net_nic_pre_load, + .pre_save =3D virtio_net_nic_pre_save, + .post_load =3D virtio_net_nic_post_load, + .fields =3D (const VMStateField[]) { + VMSTATE_VARRAY_UINT32(ncs, struct VirtIONetMigTmp, + max_queue_pairs, 0, vmstate_net_peer_backend, + NetClientState), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_virtio_net_device =3D { .name =3D "virtio-net-device", .version_id =3D VIRTIO_NET_VM_VERSION, @@ -3602,6 +3691,9 @@ static const VMStateDescription vmstate_virtio_net_de= vice =3D { * but based on the uint. */ VMSTATE_BUFFER_POINTER_UNSAFE(vlans, VirtIONet, 0, MAX_VLAN >> 3), + VMSTATE_WITH_TMP_TEST(VirtIONet, virtio_net_is_backend_transfer, + struct VirtIONetMigTmp, + vmstate_virtio_net_nic), VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp, vmstate_virtio_net_has_vnet), VMSTATE_UINT8(mac_table.multi_overflow, VirtIONet), @@ -3866,6 +3958,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); @@ -4003,6 +4131,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); @@ -4314,6 +4448,7 @@ static const Property virtio_net_properties[] =3D { host_features_ex, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM, true), + DEFINE_PROP_BOOL("backend-transfer", VirtIONet, backend_transfer, true= ), }; =20 static void virtio_net_class_init(ObjectClass *klass, const void *data) diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 5b8ab7bda7..14a5c7c77b 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -231,6 +231,8 @@ struct VirtIONet { struct EBPFRSSContext ebpf_rss; uint32_t nr_ebpf_rss_fds; char **ebpf_rss_fds; + bool peers_wait_incoming; + bool backend_transfer; }; =20 size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, diff --git a/include/net/net.h b/include/net/net.h index aa34043b1a..d4cf399d4a 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -82,6 +82,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 { @@ -110,6 +111,7 @@ typedef struct NetClientInfo { NetAnnounce *announce; SetSteeringEBPF *set_steering_ebpf; NetCheckPeerType *check_peer_type; + IsWaitIncoming *is_wait_incoming; GetVHostNet *get_vhost_net; const VMStateDescription *backend_vmsd; } NetClientInfo; --=20 2.52.0 From nobody Sat Feb 7 05:52:23 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=1769962851; cv=none; d=zohomail.com; s=zohoarc; b=TMMLmu3U0GjUI3/JTLrtFOKy1ZgrRz2cSoG+aSsvhMrMUIN5liX4MrGugLwJRjEY8mTjLl1tGyqexk1ZGAcSodAXpyQqH4j9QmvX6MO6xsafwSQ73R6ugRGxWMXtPSmIW8MESCnbje3Y430n9Lr7FcGeRPLxkanAhy6DVwsb2H0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962851; 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=P1HaemTso6fzJD5byCYPxAqcpX9YE+ug+soY+b3svcs=; b=ezsVE3Kfh4WkvRI8J+gbdVGayEGp2K+BUvX3Jcl3AGSpe/XeeXowhVs2nf0JBONlyN//G6GXNoEUI7D7QdMmgb7am2n2VlX0OvpjFNSvB7DoGDyN8tIJ4CiqS6i3+lG3BBu9Hu6FMwGEjsJit19yEJfp6Nnn5YUdZCIRfB6byVc= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962851909848.4884161872676; Sun, 1 Feb 2026 08:20:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBS-0001Bq-Oy; Sun, 01 Feb 2026 11:20:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBO-0001AT-64 for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:18 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBK-0005Ye-8V for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:17 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id E7CA8807F6; Sun, 01 Feb 2026 19:20:12 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-ufP40ES0; Sun, 01 Feb 2026 19:20:12 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962812; bh=P1HaemTso6fzJD5byCYPxAqcpX9YE+ug+soY+b3svcs=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=b3TWEPpZeTlsTYgHvsbKfDPZeiEsb6RrhPwzHmqqD1P5iRy/krROqaOMMSbRJcEmj ww0oE1D2h5wWh/3DkBQFfYwJt2g/OviyLVtNkKiTNazjsDW4BVKIezLzs5dEzs9Rdt pYXeuMAkz7RxAXVNH51C6lSJ3aVYA5m+AvEcffxM= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 6/8] net/tap: support backend-transfer migration Date: Sun, 1 Feb 2026 19:19:58 +0300 Message-ID: <20260201162001.296328-7-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962854694158500 Content-Type: text/plain; charset="utf-8" Support transferring of TAP state (including open fd) through migration stream. Add new option, incoming-fds, which should be set to true to trigger new logic. Signed-off-by: Vladimir Sementsov-Ogievskiy --- net/tap.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++- qapi/net.json | 6 +++- 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/net/tap.c b/net/tap.c index bd19c71c42..57d4d2d9f8 100644 --- a/net/tap.c +++ b/net/tap.c @@ -393,6 +393,65 @@ static VHostNetState *tap_get_vhost_net(NetClientState= *nc) return s->vhost_net; } =20 +static bool tap_is_wait_incoming(NetClientState *nc) +{ + TAPState *s =3D DO_UPCAST(TAPState, nc, 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 const VMStateDescription vmstate_tap =3D { + .name =3D "net-tap", + .pre_load =3D tap_pre_load, + .post_load =3D tap_post_load, + .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() + } +}; + /* fd support */ =20 static NetClientInfo net_tap_info =3D { @@ -412,7 +471,9 @@ 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, + .backend_vmsd =3D &vmstate_tap, }; =20 static TAPState *net_tap_fd_init(NetClientState *peer, @@ -907,6 +968,14 @@ int net_init_tap(const Netdev *netdev, const char *nam= e, return -1; } =20 + if (tap->incoming_fds && + (tap->fd || tap->fds || tap->helper || tap->script || + tap->downscript)) { + error_setg(errp, "incoming-fds is incompatible with " + "fd=3D, fds=3D, helper=3D, script=3D, downscript=3D"); + return -1; + } + queues =3D tap_parse_fds_and_queues(tap, &fds, errp); if (queues < 0) { return -1; @@ -925,7 +994,24 @@ int net_init_tap(const Netdev *netdev, const char *nam= e, goto fail; } =20 - if (fds) { + if (tap->incoming_fds) { + for (i =3D 0; i < queues; i++) { + NetClientState *nc; + TAPState *s; + + nc =3D qemu_new_net_client(&net_tap_info, peer, "tap", name); + qemu_set_info_str(nc, "incoming"); + + s =3D DO_UPCAST(TAPState, nc, nc); + 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 118bd34965..79f5ce9f43 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -355,6 +355,9 @@ # @poll-us: maximum number of microseconds that could be spent on busy # polling for tap (since 2.7) # +# @incoming-fds: do not open/connnect any resources, instead wait for +# TAP state from incoming migration stream. (Since 11.0) +# # Since: 1.2 ## { 'struct': 'NetdevTapOptions', @@ -373,7 +376,8 @@ '*vhostfds': 'str', '*vhostforce': 'bool', '*queues': 'uint32', - '*poll-us': 'uint32'} } + '*poll-us': 'uint32', + '*incoming-fds': 'bool' } } =20 ## # @NetdevSocketOptions: --=20 2.52.0 From nobody Sat Feb 7 05:52:23 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=1769962863; cv=none; d=zohomail.com; s=zohoarc; b=Z0XLwN5vlDmfKOf4QoCrx2M5NiWua2ZNeK1DvC99hqnO0f/Sm/A7y8MnE+4I9GMp25Jer+tq1mwJihj26/XGeeOc8Qz0h/9xdGkaquugr6iVaMcFR7RU7c6aamsLipOxqVTXsIBWXdMT0wv+2w2AEJ5mQavjL1DNShy586JBxSM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962863; 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=FtthCjv4jZclLpHuxzc/o+cbJSRbpvzPto3AWwLXoAM=; b=bgSJGGlGzE0U1M2/kamMlD5PNxzk68OFi7uQxyXCkqokffpVW3mQixw719U7sJ4Vv7Sh1Bn/y4+Ksbrr6TskCzN3hFzXVpZyOEyXHG2HURE+bYJgvcQKV8iV3/oeniYgY/rVDIdpPAXytGjaheDANz7yTRAL1hCfqMcGyysjOXI= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962863101798.7788018976989; Sun, 1 Feb 2026 08:21:03 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBS-0001Bk-21; Sun, 01 Feb 2026 11:20:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBO-0001AS-0S for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:18 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBK-0005Yk-Sq for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:17 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 9877A807DE; Sun, 01 Feb 2026 19:20:13 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-SrGBpnhP; Sun, 01 Feb 2026 19:20:13 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962813; bh=FtthCjv4jZclLpHuxzc/o+cbJSRbpvzPto3AWwLXoAM=; h=Cc:Message-ID:References:Date:In-Reply-To:Subject:To:From; b=Ajal0O/X/kwaM9NEU6S2UaF6tLnBWso7C3UGkV+whOo5fGWNDerNbMLlE/eWDpOqA NgOEfjQsSqike/XO5eaSXugFwYYvNOCxl76SAHGeS48oHbQhEUDMtn8XloVH8euPUJ k0nYP2T7ZeBvx5hIq1UJy5iBO4TLObET0x06kVsw= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 7/8] tests/functional: add skipWithoutSudo() decorator Date: Sun, 1 Feb 2026 19:19:59 +0300 Message-ID: <20260201162001.296328-8-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962864690158500 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 --- 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 fcf236ecfd..aa135acc78 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 Feb 7 05:52:23 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=1769962883; cv=none; d=zohomail.com; s=zohoarc; b=e2dKFzq/h4AWrABqrA5Lomoog/1lmeFuXhrTE9cPnneIrVeo5y22QDhmg6PxMCmZ8TSZnSJM5yRbkdL8cW9HIdz3Hmm46HcUtxSk7KeaG63OyjSeR48JjfhDy/+HfgDR7ZJBVR+6G05U2K6TrhiFQc0d6rvSEaePzEV/ATce47c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769962883; 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=lJn8sPo65PFunVLi3WT+r54D/oVubZHAgxhDA907cCA=; b=n17blLf0KGta9/Wsk7iHyiYq3/pxXcQOINR/gipHWZ/M5GajX+M2yVV2mDOSKZeNFuI22lIbn+9IoQ/EKFqFKhFoFZz/4yGmDL3p7AbhHGb0xgGtg86eY5P9nAkS9RwqJFs2Pwm66fCpEVGKevmitjefFhvJq4vMSxjdDr8ompQ= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769962882046770.1365829649333; Sun, 1 Feb 2026 08:21:22 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vmaBU-0001By-3S; Sun, 01 Feb 2026 11:20:24 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBO-0001BG-Qf for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:20 -0500 Received: from forwardcorp1d.mail.yandex.net ([178.154.239.200]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vmaBM-0005Z5-Ct for qemu-devel@nongnu.org; Sun, 01 Feb 2026 11:20:18 -0500 Received: from mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:65a0:0:640:e1de:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 1F45A80818; Sun, 01 Feb 2026 19:20:15 +0300 (MSK) Received: from vsementsov-lin (unknown [2a02:6bf:8080:765::1:3b]) by mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 4Kp2C46Aq8c0-yWITa1ib; Sun, 01 Feb 2026 19:20:13 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1769962813; bh=lJn8sPo65PFunVLi3WT+r54D/oVubZHAgxhDA907cCA=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=qjZCi5rTqQaw3xgLQcKsOnWeGS0myah9OxeBBksNmcvji1s7bHnnlGGUMx1CsCZ20 qYNicViDpqG7U//zPnZ8pQA8eP34aHJWEjGGqmdIyMCGko7iINlLBFZcg1fRHHG01h qrG31mIFK4+jyb5k44xpB6GmTrKMPOmIDFcoZdmk= Authentication-Results: mail-nwsmtp-smtp-corp-main-56.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: jasowang@redhat.com, mst@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, thuth@redhat.com, armbru@redhat.com, eblake@redhat.com, farosas@suse.de, peterx@redhat.com, zhao1.liu@intel.com, wangyanan55@huawei.com, philmd@linaro.org, marcel.apfelbaum@gmail.com, eduardo@habkost.net, davydov-max@yandex-team.ru, qemu-devel@nongnu.org, vsementsov@yandex-team.ru, yc-core@yandex-team.ru, leiyang@redhat.com, raphael.s.norwitz@gmail.com, bchaney@akamai.com Subject: [PATCH v10 8/8] tests/functional: add test_tap_migration Date: Sun, 1 Feb 2026 19:20:00 +0300 Message-ID: <20260201162001.296328-9-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201162001.296328-1-vsementsov@yandex-team.ru> References: <20260201162001.296328-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=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.200; envelope-from=vsementsov@yandex-team.ru; helo=forwardcorp1d.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, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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: 1769962884481158500 Content-Type: text/plain; charset="utf-8" Add test for a new backend-transfer migration of virtio-net/tap, with fd passing through unix socket. Signed-off-by: Vladimir Sementsov-Ogievskiy --- tests/functional/x86_64/meson.build | 1 + tests/functional/x86_64/test_tap_migration.py | 401 ++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 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 f78eec5e6c..d23b0cc727 100644 --- a/tests/functional/x86_64/meson.build +++ b/tests/functional/x86_64/meson.build @@ -36,4 +36,5 @@ tests_x86_64_system_thorough =3D [ 'vfio_user_client', 'virtio_balloon', 'virtio_gpu', + '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 100644 index 0000000000..0263843fd0 --- /dev/null +++ b/tests/functional/x86_64/test_tap_migration.py @@ -0,0 +1,401 @@ +#!/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 +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 "10.0.1.2" +GUEST_IP_MASK =3D f"{GUEST_IP}/24" +GUEST_MAC =3D "d6:0d:75:f8:0f:b7" +HOST_IP =3D "10.0.1.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" + + +def ip(args, check=3DTrue) -> None: + """Run ip command with sudo""" + run(["sudo", "ip"] + args, check=3Dcheck) + + +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", + ) + + 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.01 + 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]) + + 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, backend_transf= er=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 backend_transfer: + tap_name =3D TAP_ID2 if incoming else TAP_ID + else: + tap_name =3D TAP_ID + + self.add_virtio_net(vm, vhost, tap_name, backend_transfer, incomin= g) + + self.set_migration_capabilities(vm, backend_transfer) + + def add_virtio_net(self, vm, vhost: bool, tap_name: str, + backend_transfer: bool, incoming: bool): + incoming_fds =3D backend_transfer and incoming + netdev_params =3D { + "id": "netdev.1", + "vhost": vhost, + "type": "tap", + "ifname": tap_name, + "queues": 4, + "vnet_hdr": True, + "incoming-fds": incoming_fds, + } + + if not incoming_fds: + netdev_params["script"] =3D "no" + netdev_params["downscript"] =3D "no" + + 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", + backend_transfer=3Dbackend_transfer, + ) + + def set_migration_capabilities(self, vm, backend_transfer=3DTrue): + vm.cmd("migrate-set-capabilities", { "capabilities": [ + {"capability": "events", "state": True}, + {"capability": "x-ignore-shared", "state": True}, + ]}) + vm.cmd("migrate-set-parameters", { + "backend-transfer": backend_transfer + }) + + 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, backend_transfer=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 backend_transfer: + del_tap(TAP_ID2) + init_tap(TAP_ID2, with_ip=3DFalse) + + self.prepare_and_launch_vm( + self.shm_path, vhost, backend_transfer=3Dbackend_transfer + ) + 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, + backend_transfer=3Dbackend_transfer, + ) + + 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 backend transfer + if not backend_transfer: + 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, backend_transfer=3DFalse) + + def test_tap_new_tap_migration_vhost(self): + self.do_test_tap_fd_migration(True, backend_transfer=3DFalse) + + +if __name__ =3D=3D "__main__": + LinuxKernelTest.main() --=20 2.52.0