From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856430; cv=none; d=zohomail.com; s=zohoarc; b=lbBgBzYrogXWRhqxXq8AlrZFLGj8T9cp/nwDAnunebk/EHqrGTlzrmahY7+WfcSvPXfN/GKNb1K3I6tkw27etO+3UuVagpwvcVQKbBon4+EmPfdHtMCLHIgpiqAQjgt1S9A5l4B46x/s4a7x7x3U3DMNQG1uQQlk1b3AjVjrzxQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856430; 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=m3l8D6/W9LkZBZ3lH190RliJgauyjn3Sep0D+DmIu1Y=; b=M4XXRoiMXDtil8h94UCU8DQND1qYcqDItbndAblfBDHRqyW6lEguIaCSJj1qGoZ/e8zdWU0pwTjNA8tTtDAR2/EOZ3Qikuoc5TBMfYBe4qgIUPHuHrgadBr3KxU8elP37XAEeLdelDNMnpHtkZmrz7J+KOXFO0XcQcssiAh2DHk= 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 1761856430565624.1946810832629; Thu, 30 Oct 2025 13:33:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJN-0000hP-9K; Thu, 30 Oct 2025 16:31:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJC-0000fN-Jq for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:47 -0400 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 1vEZIw-0005v1-B6 for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:45 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id B534880A81; Thu, 30 Oct 2025 23:31:20 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-xSuIlzYQ; Thu, 30 Oct 2025 23:31:20 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856280; bh=m3l8D6/W9LkZBZ3lH190RliJgauyjn3Sep0D+DmIu1Y=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=vyggrqc91/TXyDzkIQVn5K6CU31frztBuxGpHoxJ81PdMbSm7pDkCDwTaBgvgL3kz 4d8wVhKW872MJlpCvCguBm6wJP2qiab2S4dChv2jQVPML6wyByNrbyUOh0BCUnzV3k L3ksXvnE7bZYXVgVwAORFfxefYNwxgCn/txtsI10= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 1/8] migration: introduce .pre_incoming() vmsd handler Date: Thu, 30 Oct 2025 23:31:08 +0300 Message-ID: <20251030203116.870742-2-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: 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: 1761856432336154100 Content-Type: text/plain; charset="utf-8" Add possibility for devices to hook into top of migrate-incoming QMP command. It's a place, where migration capabilities and parameters are already set, but migration downtime is not yet started (source is still running). So here devices may do some remaining initializations dependent on migration capabilities. This will be used in further commit to support backend-transfer migration feature for vhost-user-blk. Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Peter Xu --- include/migration/vmstate.h | 1 + migration/migration.c | 4 ++++ migration/savevm.c | 15 +++++++++++++++ migration/savevm.h | 1 + 4 files changed, 21 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 09f1eefcfb..6ea5b212f2 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -217,6 +217,7 @@ struct VMStateDescription { int version_id; int minimum_version_id; MigrationPriority priority; + bool (*pre_incoming)(void *opaque, Error **errp); int (*pre_load)(void *opaque); int (*pre_load_errp)(void *opaque, Error **errp); int (*post_load)(void *opaque, int version_id); diff --git a/migration/migration.c b/migration/migration.c index a63b46bbef..6ed6a10f57 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1983,6 +1983,10 @@ void qmp_migrate_incoming(const char *uri, bool has_= channels, return; } =20 + if (!qemu_pre_incoming(errp)) { + return; + } + if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) { return; } diff --git a/migration/savevm.c b/migration/savevm.c index 7b35ec4dd0..6e240ea100 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1268,6 +1268,21 @@ bool qemu_savevm_state_blocked(Error **errp) return false; } =20 +bool qemu_pre_incoming(Error **errp) +{ + SaveStateEntry *se; + + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { + if (se->vmsd && se->vmsd->pre_incoming) { + if (!se->vmsd->pre_incoming(se->opaque, errp)) { + return false; + } + } + } + + return true; +} + void qemu_savevm_non_migratable_list(strList **reasons) { SaveStateEntry *se; diff --git a/migration/savevm.h b/migration/savevm.h index c337e3e3d1..4ad8997f94 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -29,6 +29,7 @@ #define QEMU_VM_COMMAND 0x08 #define QEMU_VM_SECTION_FOOTER 0x7e =20 +bool qemu_pre_incoming(Error **errp); bool qemu_savevm_state_blocked(Error **errp); void qemu_savevm_non_migratable_list(strList **reasons); int qemu_savevm_state_prepare(Error **errp); --=20 2.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856354; cv=none; d=zohomail.com; s=zohoarc; b=JLbAylDtgn6Idf7/A0OdqefICVvsRkBaJEfbA2Ynt9wD44HPFzvq6ddPAu1XjYCSKZT/7FBsasotTjEYL5ePqjuSg0aYKqrKAV8WrvbS724CYxeRQXnF8InsrqO+LnhHJIMKR4979uSSGdFvMnWyJ/+Sz0z/PNuPiNhJT3vIBkc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856354; 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=WL2qBDwHi63ZyswAWcDw2TfQ6wvgQUcXwyFscx5q4ms=; b=FBevbdUE0tl9b5Ftj/Yw4wpgz2plFvJlWp4BsmAEUYNxuPqO+5VpfTe2jbQ51VyeJWREUpqCUqWRSUNX6spuO3OQFXcFN4xYjrHYerRtT96B42GHCQRsa3rLbZcze3RnT55/d7KMZ8bjSWUxTYzAP23agcQ36pOWlgNtD2eM148= 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 1761856353814305.86547940612934; Thu, 30 Oct 2025 13:32:33 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJ4-0000eG-NZ; Thu, 30 Oct 2025 16:31:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJ1-0000dp-6R for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:35 -0400 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 1vEZIw-0005vM-8g for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:34 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id BA91380AA6; Thu, 30 Oct 2025 23:31:21 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-9a1q0RCR; Thu, 30 Oct 2025 23:31:21 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856281; bh=WL2qBDwHi63ZyswAWcDw2TfQ6wvgQUcXwyFscx5q4ms=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=VDHjp8LB7T8gdExzgiXJWFBxSMapQgfX0guH6nPQhvg84LMX2kY6bL0svX+0vmmKx BGcfQMf+vrazB3vZkYN9jyumiuPgR7Z3CjKsBeQFDfhW0WmmKy9Z0Zwa2/aOmZUVsc iVJN3r8s5o7eWzsjT7+7ZvlroYwWnYkOkvapqm1Y= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 2/8] qapi: introduce query-backend-transfer-support Date: Thu, 30 Oct 2025 23:31:09 +0300 Message-ID: <20251030203116.870742-3-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: 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: 1761856364309158500 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. Let's add a command to list supporting devices (no one for now), together with necessary infrastructure in qdev code. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/hw/qdev-core.h | 7 +++++++ qapi/qdev.json | 26 +++++++++++++++++++++++++ system/qdev-monitor.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 2caa0cbd26..0551fbaa6c 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -96,6 +96,7 @@ typedef void (*DeviceReset)(DeviceState *dev); typedef void (*BusRealize)(BusState *bus, Error **errp); typedef void (*BusUnrealize)(BusState *bus); typedef int (*DeviceSyncConfig)(DeviceState *dev, Error **errp); +typedef bool (*DeviceSupportBackendTransfer)(DeviceState *dev, Error **err= p); =20 /** * struct DeviceClass - The base class for all devices. @@ -174,6 +175,12 @@ struct DeviceClass { DeviceUnrealize unrealize; DeviceSyncConfig sync_config; =20 + /** + * @backend_transfer_support: reports support for backend-transfer + * migration of the device. + */ + DeviceSupportBackendTransfer backend_transfer_support; + /** * @vmsd: device state serialisation description for * migration/save/restore diff --git a/qapi/qdev.json b/qapi/qdev.json index e14a0c9259..d7e878d58d 100644 --- a/qapi/qdev.json +++ b/qapi/qdev.json @@ -188,3 +188,29 @@ { 'command': 'device-sync-config', 'features': [ 'unstable' ], 'data': {'id': 'str'} } + +## +# @DevPath: +# +# @path: the device's QOM path +# +# Since: 10.2 +## +{ 'struct': 'DevPath', + 'data': { 'path': 'str' } } + +## +# @query-backend-transfer-support: +# +# Returns list of devices, supporting backend-transfer +# migration. +# +# Features: +# +# @unstable: The command is experimental. +# +# Since: 10.2 +## +{ 'command': 'query-backend-transfer-support', + 'features': [ 'unstable' ], + 'returns': [ 'DevPath' ] } diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index ec4a2394ce..9d3d961c15 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -939,6 +939,49 @@ void qmp_device_del(const char *id, Error **errp) } } =20 +static bool qdev_backend_transfer_support(DeviceState *dev, Error **errp) +{ + DeviceClass *dc =3D DEVICE_GET_CLASS(dev); + + if (!dc->backend_transfer_support) { + error_setg(errp, "backend-transfer is not supported for '%s'", + object_get_typename(OBJECT(dev))); + return false; + } + + return dc->backend_transfer_support(dev, errp); +} + +static int qdev_add_if_backend_transfer_supported(Object *obj, void *opaqu= e) +{ + DevPathList **list =3D opaque; + DeviceState *dev =3D (DeviceState *)object_dynamic_cast(obj, TYPE_DEVI= CE); + + if (dev !=3D NULL && qdev_backend_transfer_support(dev, NULL)) { + DevPath *el =3D g_new(DevPath, 1); + *el =3D (DevPath) { + .path =3D g_strdup(dev->canonical_path), + }; + QAPI_LIST_PREPEND(*list, el); + } + + /* Recursively check all children */ + object_child_foreach(obj, qdev_add_if_backend_transfer_supported, opaq= ue); + + return 0; +} + +DevPathList *qmp_query_backend_transfer_support(Error **errp) +{ + DevPathList *result =3D NULL; + Object *peripheral =3D machine_get_container("peripheral"); + + object_child_foreach(peripheral, qdev_add_if_backend_transfer_supporte= d, + &result); + + return result; +} + int qdev_sync_config(DeviceState *dev, Error **errp) { DeviceClass *dc =3D DEVICE_GET_CLASS(dev); --=20 2.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856369; cv=none; d=zohomail.com; s=zohoarc; b=WX8cbsGKYN/gI+fux00jKiIJVEey7Si9cmpfITzaGptqMwMG1Y7IzR8BdmsKyn8+7P4vqeM3OoBoMr3OSFIdy2JjI8zD/4W6x11th40ZK1QBGEePj4J/NzkDQXPlfeKygpr6vZOGR/2cYH3xtVWdPKY7AZ49xSxR1TvYfT9+8HY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856369; 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=Qznovkf0Y+7NhB3GQmNH7kj9tnURcGnlg9ou7FjQK0s=; b=IY/9e3jyto5l5TP4LczZ6HwZR9dLd3QNOMFvW0j/D+KZ9r/K/IAoQ4FIm+SSe+ENTIV3Z/ft6aJSLozOkmdb5IPSJWPEiiqyYdygYsY/uEGJ+E+zYHncHHshxZOZgaPRHELhAsnre2vEabwXPK7I0pLGT7hlczglivpAKHCit6Y= 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 1761856369224248.51881459080005; Thu, 30 Oct 2025 13:32:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJI-0000fz-Ij; Thu, 30 Oct 2025 16:31:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJ9-0000f0-Lv for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:44 -0400 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 1vEZIv-0005vP-GT for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:41 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id BE05180A76; Thu, 30 Oct 2025 23:31:22 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-IwcerLAU; Thu, 30 Oct 2025 23:31:22 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856282; bh=Qznovkf0Y+7NhB3GQmNH7kj9tnURcGnlg9ou7FjQK0s=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=uYuMjD8hiUzHNHgixl08d1N6WnyyCUf8uwzJQptJNVqgF4h1v0ka864AhBTa/+Iwj LVxJcrXBOKljrPEmNbl/FospG3p1YamxZYitnrV+Lh76CpdGofUgVHV1B7U2jo3bkH jskN7bcx+Y7yDXS6ikv/zxMjX5qcgMQ9PEhJpGPA= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 3/8] qapi: add backend-transfer migration parameter Date: Thu, 30 Oct 2025 23:31:10 +0300 Message-ID: <20251030203116.870742-4-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: 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: 1761856371974158500 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 pick devices for backend-transfer migration in context of next outgoing or incoming migration. Of course, user is responsible to pick same set of devices on source and target. QMP command query-backend-transfer-support command may help to prepare such set as intersection of query-backend-transfer-support results on source and target. With this commit, no device yet support backend-transfer, so passing something other then empty list to backend-transfer migration parameter will fail. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/hw/qdev-core.h | 3 +++ include/migration/misc.h | 2 ++ migration/options.c | 31 +++++++++++++++++++++++++++++++ qapi/migration.json | 35 +++++++++++++++++++++++++++++------ system/qdev-monitor.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 6 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 0551fbaa6c..9ed0b3f04d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -1168,4 +1168,7 @@ typedef enum MachineInitPhase { bool phase_check(MachineInitPhase phase); void phase_advance(MachineInitPhase phase); =20 +bool migrate_backend_transfer(DeviceState *dev); +bool migrate_backend_transfer_check_list(const strList *list, Error **errp= ); + #endif diff --git a/include/migration/misc.h b/include/migration/misc.h index 592b93021e..7f931bed17 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 +const strList *migrate_backend_transfer_list(void); + #endif diff --git a/migration/options.c b/migration/options.c index 5183112775..1644728ed7 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" @@ -262,6 +264,12 @@ bool migrate_mapped_ram(void) return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM]; } =20 +const strList *migrate_backend_transfer_list(void) +{ + MigrationState *s =3D migrate_get_current(); + return s->parameters.backend_transfer; +} + bool migrate_ignore_shared(void) { MigrationState *s =3D migrate_get_current(); @@ -963,6 +971,12 @@ MigrationParameters *qmp_query_migrate_parameters(Erro= r **errp) params->cpr_exec_command =3D QAPI_CLONE(strList, s->parameters.cpr_exec_command); =20 + if (s->parameters.backend_transfer) { + params->has_backend_transfer =3D true; + params->backend_transfer =3D QAPI_CLONE(strList, + s->parameters.backend_transf= er); + } + return params; } =20 @@ -997,6 +1011,7 @@ void migrate_params_init(MigrationParameters *params) params->has_zero_page_detection =3D true; params->has_direct_io =3D true; params->has_cpr_exec_command =3D true; + params->has_backend_transfer =3D true; } =20 /* @@ -1183,6 +1198,11 @@ bool migrate_params_check(MigrationParameters *param= s, Error **errp) return false; } =20 + if (params->has_backend_transfer && + !migrate_backend_transfer_check_list(params->backend_transfer, err= p)) { + return false; + } + return true; } =20 @@ -1305,6 +1325,10 @@ static void migrate_params_test_apply(MigrateSetPara= meters *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(MigrateSetParameters *params, Error **err= p) @@ -1443,6 +1467,13 @@ static void migrate_params_apply(MigrateSetParameter= s *params, Error **errp) s->parameters.cpr_exec_command =3D QAPI_CLONE(strList, params->cpr_exec_command); } + + if (params->has_backend_transfer) { + qapi_free_strList(s->parameters.backend_transfer); + + s->parameters.backend_transfer =3D QAPI_CLONE(strList, + params->backend_transf= er); + } } =20 void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) diff --git a/qapi/migration.json b/qapi/migration.json index be0f3fcc12..9478c4ddab 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -951,9 +951,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # Since: 2.4 @@ -978,7 +984,8 @@ 'mode', 'zero-page-detection', 'direct-io', - 'cpr-exec-command'] } + 'cpr-exec-command', + { 'name': 'backend-transfer', 'features': ['unstable'] } ] } =20 ## # @MigrateSetParameters: @@ -1137,9 +1144,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # TODO: either fuse back into `MigrationParameters`, or make @@ -1179,7 +1192,9 @@ '*mode': 'MigMode', '*zero-page-detection': 'ZeroPageDetection', '*direct-io': 'bool', - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*backend-transfer': { 'type': [ 'str' ], + 'features': [ 'unstable' ] } } } =20 ## # @migrate-set-parameters: @@ -1352,9 +1367,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # Since: 2.4 @@ -1391,7 +1412,9 @@ '*mode': 'MigMode', '*zero-page-detection': 'ZeroPageDetection', '*direct-io': 'bool', - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*backend-transfer': { 'type': [ 'str' ], + 'features': [ 'unstable' ] } } } =20 ## # @query-migrate-parameters: diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 9d3d961c15..549c77b2f0 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -939,6 +939,19 @@ void qmp_device_del(const char *id, Error **errp) } } =20 +bool migrate_backend_transfer(DeviceState *dev) +{ + const strList *el =3D migrate_backend_transfer_list(); + + for ( ; el; el =3D el->next) { + if (find_device_state(el->value, false, NULL) =3D=3D dev) { + return true; + } + } + + return false; +} + static bool qdev_backend_transfer_support(DeviceState *dev, Error **errp) { DeviceClass *dc =3D DEVICE_GET_CLASS(dev); @@ -952,6 +965,24 @@ static bool qdev_backend_transfer_support(DeviceState = *dev, Error **errp) return dc->backend_transfer_support(dev, errp); } =20 +bool migrate_backend_transfer_check_list(const strList *list, Error **errp) +{ + const strList *el =3D list; + + for ( ; el; el =3D el->next) { + DeviceState *dev =3D find_device_state(el->value, true, errp); + if (!dev) { + return false; + } + + if (!qdev_backend_transfer_support(dev, errp)) { + return false; + } + } + + return true; +} + static int qdev_add_if_backend_transfer_supported(Object *obj, void *opaqu= e) { DevPathList **list =3D opaque; --=20 2.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856433; cv=none; d=zohomail.com; s=zohoarc; b=lvpTbjGVAVEpWi6BAr2cEIyGYrqlOFggVHzhuwLmVmkacFmOzGC9pu2W7M9A6sf3iBBfHWXV0At/cT2X8Vu8SZ9vhmlSrqBighC4tWcbEU/s/xTEgevaEtRs7oFIirFjBZYfBH5vTaQpfIzf69fED/y0HuoaEikiVrKceXGcMYM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856433; 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=yr86GKt6fRLAn3ICldus7yhJBrk2W1GNN0v7ofSRZkc=; b=NrsP4+4pU73QDMbVflWM5R0kYZN9o5AOR7mEM+JjzOMwSuKfneu+vwoe5VupnCeyhC9VIHuhDeKr0jJf03QrUUsAYf4Y3TwRsLTz0YdDKNn7RxQwdl2n+yMDwzrSMpZK3B8R0RXxY86U3L71CmxXmyijfhyTCM0DPXNMCd9c5Oo= 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 1761856433661445.5493304921806; Thu, 30 Oct 2025 13:33:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJg-0000lf-4a; Thu, 30 Oct 2025 16:32:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJH-0000gM-Mp for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:52 -0400 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 1vEZIx-0005vT-Tg for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:48 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id DC32280AAA; Thu, 30 Oct 2025 23:31:23 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-ELmHcMW9; Thu, 30 Oct 2025 23:31:23 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856283; bh=yr86GKt6fRLAn3ICldus7yhJBrk2W1GNN0v7ofSRZkc=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=1ys0C97pAv8i92Z5wOYIPnuD+ab3duSBZLtTAhmFs83DJ/umRKTrwo5MHXFlUXouL gCBoxMYY+BEx6/ayQHqLhFsVyaF4F2neCQ52IJCPTa8PgDw9GHZKjAsAzO2wg4YASN RR4SlkVL47dynmfar1K5FZJQvPxiJYdjFkUJJ2l8= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 4/8] net: introduce vmstate_net_peer_backend Date: Thu, 30 Oct 2025 23:31:11 +0300 Message-ID: <20251030203116.870742-5-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: 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: 1761856434355158500 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 3aa67db57c..8375ca89a7 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/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], \ @@ -115,6 +116,7 @@ typedef struct NetClientInfo { NetCheckPeerType *check_peer_type; GetVHostNet *get_vhost_net; NetBackendConnect *backend_connect; + const VMStateDescription *backend_vmsd; } NetClientInfo; =20 struct NetClientState { @@ -360,4 +362,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 4fc6b1d0a6..cca4fa0a6b 100644 --- a/net/net.c +++ b/net/net.c @@ -57,6 +57,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) @@ -2177,3 +2178,49 @@ bool net_backend_connect(NetClientState *nc, Error *= *errp) =20 return nc->info->backend_connect(nc, errp); } + +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.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856436; cv=none; d=zohomail.com; s=zohoarc; b=dfr4xlXdRT4KvUGdmgtCpCmFjvXCOj9T6ocQTdHimVu/YAYheTXiKzrkhqdf6TtD4g8Na0t01InvTe/CBOkYI57bRDcZcfYz4mrQl8jBu3DIjERcdeXMg+Cla0+LpxPSbcp+rLbWDAIS7AMAq2S3c7uu/FhOZLC0iw/TazBVlJ4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856436; 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=NL0jCrX2LP9YnzAQ/IxZiBP2DlF4NfwjD+aDOcx8SOo=; b=fGHrgge80N7QCOLw1Bv8afiS41NVA2Cs/RTS2UGdFZj/a7Q2AxBEliH8NhHipXt5iPe0UdnKWrIY76WzpmPidMZFRGgmBRBk9O7sex4HU0GcH2mPZZuIv7m61x5gLU366lbP7Kz1rEg4gIdjh8hq/XOuY3kyumPJbg3szuM0ZCc= 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 1761856436521871.032116866394; Thu, 30 Oct 2025 13:33:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJb-0000jh-Hc; Thu, 30 Oct 2025 16:32:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJF-0000g0-A0 for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:50 -0400 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 1vEZIv-0005vd-1x for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:46 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id AC9BF80A84; Thu, 30 Oct 2025 23:31:24 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-020dyFVg; Thu, 30 Oct 2025 23:31:24 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856284; bh=NL0jCrX2LP9YnzAQ/IxZiBP2DlF4NfwjD+aDOcx8SOo=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=wfYpv0HcOMnP6JwjN5MLOmaEw6+TMu6K7bP2voPJ84SJ6VGiDM/DKUfTgYraLOlbP hm45Uwbf4XtYLWRZ2iQo0peDbs9QVu6sKu55ti9GzcZ8GFHuCJHgOekyNnW29HpSWa FXFrrudK05RsP9cpvabsTj83yysL62fjCeV5d6hU= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 5/8] virtio-net: support backend-transfer migration Date: Thu, 30 Oct 2025 23:31:12 +0300 Message-ID: <20251030203116.870742-6-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, T_SPF_HELO_TEMPERROR=0.01, T_SPF_TEMPERROR=0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @yandex-team.ru) X-ZM-MESSAGEID: 1761856440750158500 Content-Type: text/plain; charset="utf-8" Implement backend-transfer support for virtio-net device. How it works: 1. Use DEFINE_NIC_PROPERTIES_NO_CONNECT(), so that backend not being connected during netdev property setting. 2. If we are not in incoming migration, just call net_backend_connect() in _realize() 3. If we are in incoming migration, postpone backend connect up to pre-incoming. At this point we check migration parameters, and if backend-transfer is NOT enabled for this virtio-net device, do net_backend_connect(). Otherwise - do noting, live backend will come in migration stream. 4. During virtio-load, we get backend state as part of virtio-net state Signed-off-by: Vladimir Sementsov-Ogievskiy --- hw/net/virtio-net.c | 157 ++++++++++++++++++++++++++++++++- include/hw/virtio/virtio-net.h | 1 + 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 17ed0ef919..94e41c225a 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" @@ -3060,7 +3062,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) @@ -3089,6 +3101,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); @@ -3180,6 +3203,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; @@ -3301,6 +3336,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 @@ -3570,6 +3608,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(DEVICE(n)); +} + +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 { */ VMSTATE_BUFFER_UNSAFE(vlans, VirtIONet, 0, sizeof(typeof_field(VirtIONet, vlans))), + 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), @@ -4003,6 +4095,20 @@ static void virtio_net_device_realize(DeviceState *d= ev, Error **errp) n->nic->ncs[i].do_not_pad =3D true; } =20 + if (runstate_check(RUN_STATE_INMIGRATE)) { + n->peers_wait_incoming =3D true; + } else { + for (i =3D 0; i < n->max_queue_pairs; i++) { + nc =3D qemu_get_subqueue(n->nic, i); + if (!nc->peer) { + continue; + } + if (!net_backend_connect(nc->peer, errp)) { + return; + } + } + } + peer_test_vnet_hdr(n); if (peer_has_vnet_hdr(n)) { n->host_hdr_len =3D sizeof(struct virtio_net_hdr); @@ -4176,6 +4282,30 @@ static bool dev_unplug_pending(void *opaque) return vdc->primary_unplug_pending(dev); } =20 +static bool vhost_user_blk_pre_incoming(void *opaque, Error **errp) +{ + VirtIONet *n =3D opaque; + int i; + + if (!virtio_net_is_backend_transfer(opaque, 0) && n->peers_wait_incomi= ng) { + for (i =3D 0; i < n->max_queue_pairs; i++) { + NetClientState *nc =3D qemu_get_subqueue(n->nic, i); + if (!nc->peer) { + continue; + } + if (!net_backend_connect(nc->peer, errp)) { + return false; + } + } + + n->peers_wait_incoming =3D false; + + return virtio_net_update_host_features(n, errp); + } + + return true; +} + static const VMStateDescription vmstate_virtio_net =3D { .name =3D "virtio-net", .minimum_version_id =3D VIRTIO_NET_VM_VERSION, @@ -4184,6 +4314,7 @@ static const VMStateDescription vmstate_virtio_net = =3D { VMSTATE_VIRTIO_DEVICE, VMSTATE_END_OF_LIST() }, + .pre_incoming =3D vhost_user_blk_pre_incoming, .pre_save =3D virtio_net_pre_save, .dev_unplug_pending =3D dev_unplug_pending, }; @@ -4239,7 +4370,7 @@ static const Property virtio_net_properties[] =3D { VIRTIO_NET_F_RSC_EXT, false), DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout, VIRTIO_NET_RSC_DEFAULT_INTERVAL), - DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf), + DEFINE_NIC_PROPERTIES_NO_CONNECT(VirtIONet, nic_conf), DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer, TX_TIMER_INTERVAL), DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST), @@ -4314,6 +4445,27 @@ static const Property virtio_net_properties[] =3D { false), }; =20 +static bool virtio_net_backend_transfer_support(DeviceState *dev, Error **= errp) +{ + VirtIONet *n =3D VIRTIO_NET(dev); + NetClientState *nc =3D qemu_get_queue(n->nic); + + if (!nc->peer) { + error_setg(errp, "Device %s has no attached backend", + qdev_get_dev_path(dev)); + return false; + } + + if (!nc->peer->info->backend_vmsd) { + error_setg(errp, "Device %s backend is %s, does not support backen= d" + " transfer", qdev_get_dev_path(dev), + NetClientDriver_str(nc->peer->info->type)); + return false; + } + + return true; +} + static void virtio_net_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -4321,6 +4473,7 @@ static void virtio_net_class_init(ObjectClass *klass,= const void *data) =20 device_class_set_props(dc, virtio_net_properties); dc->vmsd =3D &vmstate_virtio_net; + dc->backend_transfer_support =3D virtio_net_backend_transfer_support; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); vdc->realize =3D virtio_net_device_realize; vdc->unrealize =3D virtio_net_device_unrealize; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index f708355306..7e0e156908 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -231,6 +231,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, --=20 2.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856446; cv=none; d=zohomail.com; s=zohoarc; b=Y+2Q/8y5RkNLtSQh1pVofT4swGPzEZI6AKYjaDzYKLYC+ZWobNKY62pyPjnvhMotc5Z7l5maq9SJNtD4lzH1q+xfoWLA9p0nDxlKZF+DsuC4rez8KAqitwmJycsJHuVHRhnniruE2d/rgUTKPxusdCY0W2ZoRUbuNkxs4qU45BU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856446; 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=mQwvhGHiZqI2TjGcnxQJGUhpsykI0z4S9z0cd6haisY=; b=W8/tz0LvxrKpSeu82PhAClO9pmr87PuiogHDZRuQLjHbvBZr39jaDddR2T47VhcU0jK4bcbDkMxD8oRBtMfhrEK28El6MiLDM4PlStPYwsD8NLouLA2LOuo2v6CFIthxdVusW30VZpmX9xP7X3d3VWcYJORb9saHv9zUsKnaDBA= 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 1761856446450642.1396570715052; Thu, 30 Oct 2025 13:34:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJR-0000ix-On; Thu, 30 Oct 2025 16:32:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJD-0000fQ-Dh for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:48 -0400 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 1vEZIu-0005vk-PP for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:43 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 6541780A94; Thu, 30 Oct 2025 23:31:25 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-aWeEbpK8; Thu, 30 Oct 2025 23:31:24 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856285; bh=mQwvhGHiZqI2TjGcnxQJGUhpsykI0z4S9z0cd6haisY=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=wI+q22YMMHYojSfkMqitHVDMBsNRAHfzoPzouefoaTzOcUh+8OJ37G2vgWw4eoTht o3rW0mAMW3GqrgAKxnQcmHp2C776WPDVhdDo3rxGOt2ggyS5TrHPmTl1aojvH8mx/Q i6YdOSNxDTkZ6E44dabgD6d5WUvM+DVc3QRXUeZI= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 6/8] net/tap: support backend-transfer migration Date: Thu, 30 Oct 2025 23:31:13 +0300 Message-ID: <20251030203116.870742-7-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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_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: 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: 1761856448544154101 Content-Type: text/plain; charset="utf-8" Support transferring of TAP state (including open fd) through migration stream. Signed-off-by: Vladimir Sementsov-Ogievskiy --- net/tap.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/net/tap.c b/net/tap.c index ad1d458521..4a752006de 100644 --- a/net/tap.c +++ b/net/tap.c @@ -413,6 +413,49 @@ static VHostNetState *tap_get_vhost_net(NetClientState= *nc) return s->vhost_net; } =20 +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 int tap_post_load(void *opaque, int version_id) +{ + TAPState *s =3D opaque; + Error *local_err =3D NULL; + + if (!net_tap_setup(s, -1, -1, &local_err)) { + error_report_err(local_err); + qemu_del_net_client(&s->nc); + return -EINVAL; + } + + 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 { @@ -434,6 +477,7 @@ static NetClientInfo net_tap_info =3D { .set_steering_ebpf =3D tap_set_steering_ebpf, .get_vhost_net =3D tap_get_vhost_net, .backend_connect =3D tap_backend_connect, + .backend_vmsd =3D &vmstate_tap, }; =20 static TAPState *net_tap_new(NetClientState *peer, const char *model, @@ -800,7 +844,7 @@ static void net_init_tap_one(const NetdevTapOptions *ta= p, NetClientState *peer, =20 static bool net_tap_setup(TAPState *s, int fd, int vnet_hdr, Error **errp) { - if (!net_tap_set_fd(s, fd, vnet_hdr, errp)) { + if (fd !=3D -1 && !net_tap_set_fd(s, fd, vnet_hdr, errp)) { return false; } =20 --=20 2.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856380; cv=none; d=zohomail.com; s=zohoarc; b=PjDH4beWQxQIgEQyYvZ48fvJuS014/5rQKwzavVVfu1xf+iCT+Bp2Anqt53vEAtREABTA6/uA7sqngtr8kTcdeha0msZaOJ5uRWMDocX1sg7LjSBNxM49HH/4k6uH1Y62bMvqzWyG4AmOUbK0LiFhoJXlN87cy4m/w80v5nklA4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856380; 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=vOw5oa65DZ0Z+eI0DURWrqAVxZOetTHC4LKJBWHMDPQ=; b=ZldI92yrnmnSIQCjxCO2tFYIbOC8X296gNqcBr7fQOId6GZFlqqboPfslPGrlf88nn8cLoEjWXouaOZeXhEaTMxFQUibfCV98POjKZETcIH4jfG4kaeY/YWGRLPI8gvNOPn7Vq4V6i7hiR64gAD9JNefLh2gTS3zrKPoDzCBFWM= 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 1761856379938331.06662351572777; Thu, 30 Oct 2025 13:32:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJg-0000lo-Ph; Thu, 30 Oct 2025 16:32:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJL-0000gv-01 for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:56 -0400 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 1vEZJ5-0005wI-DF for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:51 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 0FB5380AAC; Thu, 30 Oct 2025 23:31:26 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-MKEVMu0Z; Thu, 30 Oct 2025 23:31:25 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856285; bh=vOw5oa65DZ0Z+eI0DURWrqAVxZOetTHC4LKJBWHMDPQ=; h=Cc:Message-ID:References:Date:In-Reply-To:Subject:To:From; b=rvSpYNIzeXup8Llds7Rml/zQMdza20s7zu4qcKpFH4KwRUv+kxoqFZtg0lB6CoKxY eV9mbBq4+iNrLWx35SrDVZFvegeymbKDudRF4JeR4piagOreE5Tg5bU5aJSNkPxoA0 DYbBX2PhGdZsdwFhdoY39t71NZ/Qcchgw9Nl02Kk= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 7/8] tests/functional: add skipWithoutSudo() decorator Date: Thu, 30 Oct 2025 23:31:14 +0300 Message-ID: <20251030203116.870742-8-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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=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, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @yandex-team.ru) X-ZM-MESSAGEID: 1761856384251154100 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 b239295804..125d31dda6 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 @@ -167,3 +168,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.48.1 From nobody Fri Nov 14 17:03:08 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1761856357; cv=none; d=zohomail.com; s=zohoarc; b=Y8ak+rz4i79CR8hm4bRUsgvtPJbdM11KJoFQsGjbwjVWnDnIR/dNVNDg7e8eBEswbLMjbJaYGzIBTZsf6jsadyEGWLvpBwunxUBf/FDZ41peO5RChZ+fVSH26skR9rC9ybb4xTBfqccYlPTYrJOe5b+xtS+RxJMKcafTzrQlLNc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761856357; 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=VWwA9uHWYRG/v+i4McggNwCD3/+zQOvcEs4ZrHw1vRY=; b=BtP2N7IlAxmQu9b0etDObTc9Rv0bpQKIOdeKeUnFOwUnFmfm0yyulUFvKsevcgeJVZieHA6MJGLwMVKy0cesj1vNAwt5/dXkr7CQF+xapP8ZCov5c45Chm4ihDGKTo8dnQDONdke1/u8V9kc4xbRJe+iHh0zOq61VnVrlMas8Vk= 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 1761856356538808.6148148130269; Thu, 30 Oct 2025 13:32:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEZJO-0000iD-Kj; Thu, 30 Oct 2025 16:31:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEZJC-0000fF-FF for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:47 -0400 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 1vEZIz-0005w6-Dt for qemu-devel@nongnu.org; Thu, 30 Oct 2025 16:31:45 -0400 Received: from mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net [IPv6:2a02:6b8:c42:94a9:0:640:a3fa:0]) by forwardcorp1d.mail.yandex.net (Yandex) with ESMTPS id 0A32A80AAD; Thu, 30 Oct 2025 23:31:27 +0300 (MSK) Received: from vsementsov-lin.. (unknown [2a02:6bf:8080:861::1:2b]) by mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id HVmKdN0F6Cg0-PofALTg5; Thu, 30 Oct 2025 23:31:26 +0300 Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1761856286; bh=VWwA9uHWYRG/v+i4McggNwCD3/+zQOvcEs4ZrHw1vRY=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=fmfVy16LfYMNTBYDz8TTJLGlqHbVi66HNXb6bqXGP5yFCQFJk4/6G/T3kQol07qa6 foBD2Rs1vZ2UvXqdORJw13PDELMwMVCjh9VVUM/D4Jev4VLYjOlaBdRY/bcBTdaL3f 44zrFhBuUrfCsE3iDLM8i5t6afddNb3qP0B+p1L8= Authentication-Results: mail-nwsmtp-smtp-corp-main-68.klg.yp-c.yandex.net; dkim=pass header.i=@yandex-team.ru From: Vladimir Sementsov-Ogievskiy To: mst@redhat.com, jasowang@redhat.com Cc: pbonzini@redhat.com, berrange@redhat.com, eduardo@habkost.net, peterx@redhat.com, farosas@suse.de, eblake@redhat.com, armbru@redhat.com, thuth@redhat.com, philmd@linaro.org, zhao1.liu@intel.com, qemu-devel@nongnu.org, leiyang@redhat.com, davydov-max@yandex-team.ru, yc-core@yandex-team.ru, vsementsov@yandex-team.ru, raphael.s.norwitz@gmail.com Subject: [PATCH v9 8/8] tests/functional: add test_tap_migration Date: Thu, 30 Oct 2025 23:31:15 +0300 Message-ID: <20251030203116.870742-9-vsementsov@yandex-team.ru> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251030203116.870742-1-vsementsov@yandex-team.ru> References: <20251030203116.870742-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: 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: 1761856360923158500 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 | 398 ++++++++++++++++++ 2 files changed, 399 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..fd9f706fc3 --- /dev/null +++ b/tests/functional/x86_64/test_tap_migration.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python3 +# +# Functional test that tests TAP local migration +# with fd passing +# +# Copyright (c) Yandex Technologies LLC, 2025 +# +# 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 VhostUserBlkFdMigration(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) + + self.set_migration_capabilities(vm, backend_transfer) + + def add_virtio_net(self, vm, vhost: bool, tap_name: str =3D "tap0"): + netdev_params =3D { + "id": "netdev.1", + "vhost": vhost, + "type": "tap", + "ifname": tap_name, + "script": "no", + "downscript": "no", + "queues": 4, + "vnet_hdr": True, + } + + 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, backend_transfer=3DTrue): + capabilities =3D [ + {"capability": "events", "state": True}, + {"capability": "x-ignore-shared", "state": True}, + ] + vm.cmd("migrate-set-capabilities", {"capabilities": capabilities}) + if backend_transfer: + res =3D vm.cmd("query-backend-transfer-support") + path =3D "/machine/peripheral/vnet.1/virtio-backend" + self.assertEqual(res, [{"path": path}]) + vm.cmd("migrate-set-parameters", {"backend-transfer": [path]}) + + 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.48.1