On Mon, Jul 13, 2026 at 06:08:26PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> On 13.07.26 16:29, Markus Armbruster wrote:
> > Vladimir Sementsov-Ogievskiy <[email protected]> writes:
> > 
> > > On 13.07.26 10:57, Markus Armbruster wrote:
> > > > Vladimir Sementsov-Ogievskiy <[email protected]> writes:
> > > > 
> > > > > Support transferring of TAP state (including open fd).
> > > > > 
> > > > > Add new property "local-migration-supported", which defines
> > > > > whether local-migration is actually supported for this TAP device.
> > > > > Starting from 11.2 QEMU Machine Types it's enabled by default.
> > > > > 
> > > > > Note, that local-migration (including migrating opened FDs
> > > > 
> > > > Scratch the comma after "Note", ...
> > > > 
> > > > > through migration channel, which must be UNIX socket), is
> > > > 
> > > > ... and the one before "is".
> > > > 
> > > > > enabled by global "local" migration parameters. But individual
> > > > > devices may have additional options to enable/disable it
> > > > > per device.
> > > > > 
> > > > > The tricky thing, is that we need to know, should we do
> > > > 
> > > > Do you mean "The tricky thing is that we ween to know whether to call"?
> > > 
> > > yes
> > > 
> > > > 
> > > > > call open/connect in TAP initialization code. That means,
> > > > > that on incoming migration we want to know status of
> > > > > "local" migration parameter at time of creating TAP device.
> > > > > So, currently, for incoming local migration only TAP device
> > > > > created through QMP is supported, as you need to set migration
> > > > > parameter first (through QMP as well).
> > 
> > Possibly clearer:
> > 
> >      The tricky thing is that we need to know whether to call open/connect
> >      in TAP initialization code, i.e. we need to know the value of
> >      migration parameter "local" when creating the TAP device.  For
> >      incoming migration, we can know only for TAP devices created with QMP
> >      after setting the migration parameter with QMP.
> > 
> > > > > 
> > > > > So the full picture is:
> > > > > 
> > > > > On source, to start outgoing "local" migration you need:
> > > > > 
> > > > >    - migration parameter "local" set to true
> > > > >    - "local-migration-supported" TAP option set to true (the
> > > > >      default, starting from 11.2 QEMU Machine Types)
> > > > > 
> > > > > If at least one of these options is not set, TAP backend
> > > > > doesn't participate in migration.
> > > > > 
> > > > > On target, things are more difficult:
> > > > > 
> > > > > Same, you need both "local" and "local-migration-supported"
> > > > > be set. And same, if one of them is not set, TAP backend
> > > > > is initialized as usual, and doesn't accept any incoming
> > > > > state.
> > > > > 
> > > > > Additionally, if you are going to set "local", it must be
> > > > > set before creating the TAP device. If TAP device created
> > > > > with "local" unset, it initializes as usual. If you enable
> > > > > "local" after it and start incoming migration, it will fail
> > > > > in .pre_load handler of TAP backend.
> > > > 
> > > > Out of curiosity, how would such a failure look like?
> > > 
> > > TAP is initialized as usual, so the answer depends on the options.
> > > 
> > > For incoming migration we should open TAP without "ifname" argument.
> > > If so (and "local" is not set), new TAP device will be created. It
> > > shouldn't trigger any additional problems I think.
> > > 
> > > 
> > > Checking with test:
> > > 
> > >     diff --git a/tests/functional/x86_64/test_tap_migration.py 
> > > b/tests/functional/x86_64/test_tap_migration.py
> > >     index bcc0a60dfe9..94982bc7b55 100755
> > >     --- a/tests/functional/x86_64/test_tap_migration.py
> > >     +++ b/tests/functional/x86_64/test_tap_migration.py
> > >     @@ -316,8 +316,8 @@ def prepare_and_launch_vm(
> > >              else:
> > >                  tap_name = TAP_ID
> > > 
> > >     -        self.set_migration_capabilities(vm, local)
> > >              self.add_virtio_net(vm, vhost, tap_name, local, incoming)
> > >     +        self.set_migration_capabilities(vm, local)
> > > 
> > >          def add_virtio_net(
> > >              self, vm, vhost: bool, tap_name: str, local: bool, incoming: 
> > > bool
> > > 
> > > 
> > > Leads to
> > > 
> > > qemu-system-x86_64: TAP is already initialized and cannot receive 
> > > incoming fd
> > > qemu-system-x86_64: warning: qemu_fclose: received fd 27 was never claimed
> > > qemu-system-x86_64: load of migration failed: Invalid argument: error 
> > > while loading state for instance 0x0 of device 'netdev.1/0/net-tap': pre 
> > > load hook failed for: 'net-tap', version_id: 0, minimum version_id: 0, 
> > > ret: -22
> > > 
> > > on target, and failed migration, as expected.
> > 
> > How is the user supposed to reason their way from here to "oh, I need to
> > create my TAP device with QMP and after setting @local"?
> 
> Not trivial, yes.
> 
> I can update error message to
> 
>    TAP is already initialized and cannot receive incoming fd. For local 
> migration, "local" migration parameter must be set _before_ creating TAP 
> device.


Another reason to just make it a machine property globally
and be done with it, maybe?

> > 
> > > 
> > > > 
> > > > > Moreover, there are interface restrictions: if you create TAP
> > > > > device when QEMU is in INCOMING state, and both "local"
> > > > > and "local-migration-supported" set, most of TAP options are
> > > > > not allowed, and script/downscript are required to be explicitly
> > > > > unset (set to "" or "no").
> > > > > 
> > > > > Signed-off-by: Vladimir Sementsov-Ogievskiy 
> > > > > <[email protected]>
> > 
> > [...]
> > 
> 
> 
> -- 
> Best regards,
> Vladimir


Reply via email to