On Wed, Jan 28, 2026 at 9:49 PM Juraj Marcin <[email protected]> wrote: > > Hi Jason, > > On 2026-01-28 10:55, Jason Wang wrote: > > On Tue, Jan 27, 2026 at 10:04 PM Juraj Marcin <[email protected]> wrote: > > > > > > From: Juraj Marcin <[email protected]> > > > > > > During migration switchover both the source and the destination machines > > > are paused (compute downtime). During this period network still routes > > > network packets to the source machine, as this is the last place where > > > the recipient MAC address has been seen. Once the destination side > > > starts and sends network announcement, all subsequent frames are routed > > > correctly. However, frames delivered to the source machine are never > > > processed and lost. This causes also a network downtime with roughly the > > > same duration as compute downtime. > > > > > > This can cause problems not only for protocols that cannot handle packet > > > loss, but can also introduce delays in protocols that can handle them. > > > > > > To resolve this, this feature instantiates a network filter for each > > > network backend present during migration setup on both migration sides. > > > On the source side, this filter caches all packets received from the > > > backend during switchover. Once the destination machine starts, all > > > cached packets are sent through the migration channel and the respective > > > filter object on the destination side injects them to the NIC attached > > > to the backend. > > > > > > Signed-off-by: Juraj Marcin <[email protected]> > > > --- > > > include/migration/vmstate.h | 6 + > > > include/net/net.h | 5 + > > > migration/meson.build | 1 + > > > migration/migration.c | 49 ++++++- > > > migration/migration.h | 2 + > > > migration/netpass.c | 246 ++++++++++++++++++++++++++++++++++++ > > > migration/netpass.h | 14 ++ > > > migration/options.c | 21 +++ > > > migration/options.h | 1 + > > > migration/savevm.c | 37 ++++++ > > > migration/savevm.h | 2 + > > > migration/trace-events | 9 ++ > > > net/net.c | 11 ++ > > > net/tap.c | 11 +- > > > qapi/migration.json | 7 +- > > > 15 files changed, 418 insertions(+), 4 deletions(-) > > > create mode 100644 migration/netpass.c > > > create mode 100644 migration/netpass.h > > > > > > diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > > > index 62d7e9fe38..7987e6c85a 100644 > > > --- a/include/migration/vmstate.h > > > +++ b/include/migration/vmstate.h > > > @@ -200,6 +200,12 @@ typedef enum { > > > * save_setup() in VMSD structures. > > > */ > > > VMS_PHASE_EARLY_SETUP, > > > + /* > > > + * Specifies a netpass VMSD, these devices are copied right after the > > > + * destination is started regardless of precopy/postcopy. Failure in > > > this > > > + * phase does not fail the migration in case of precopy. > > > + */ > > > + VMS_PHASE_NETPASS, > > > } VMStateSavePhase; > > > > > > struct VMStateDescription { > > > diff --git a/include/net/net.h b/include/net/net.h > > > index 45bc86fc86..510908845b 100644 > > > --- a/include/net/net.h > > > +++ b/include/net/net.h > > > @@ -82,6 +82,7 @@ typedef void (NetAnnounce)(NetClientState *); > > > typedef bool (SetSteeringEBPF)(NetClientState *, int); > > > typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error > > > **); > > > typedef struct vhost_net *(GetVHostNet)(NetClientState *nc); > > > +typedef void (NetpassEnabledNotify)(NetClientState *nc, void *opaque); > > > > > > typedef struct NetClientInfo { > > > NetClientDriver type; > > > @@ -130,6 +131,9 @@ struct NetClientState { > > > bool is_netdev; > > > bool do_not_pad; /* do not pad to the minimum ethernet frame length > > > */ > > > bool is_datapath; > > > + bool netpass_enabled; > > > + NetpassEnabledNotify *netpass_enabled_notify; > > > + void *netpass_enabled_notify_opaque; > > > QTAILQ_HEAD(, NetFilterState) filters; > > > }; > > > > > > > Adding Cindy, Eugenio can Chen. > > > > I think we can simple reuse the existing filters: > > > > redirector: which can redirect traffic from the source to the > > destination via chardev > > buffer: which can hold the packets until the destination is released > > > > And let the libvirt install/uninstall those filters at the correct time. > > > > Which means: > > > > On the source: there would be a redirector that can be enabled when vm > > is paused, and it redirect the traffic to a socket/chardev > > On the destination: there would be a redirector as well as the buffer, > > redirector receives packets from the socket and send it to buffer, > > buffer will hold those packets until VM in the destination is resumed. > > > > The current filters need some tweaks (e.g letting filters (redirector) > > work when VM is paused). The advantages of this are: > > I tested the idea of filters for the forwarding using the existing > filters first and it does work with mentioned tweaks, however this > requires additional channel between chardevs attached to filters.
It requires some changes in the redirector. One of the major but trivial changes is to make it work when the VM is paused. > > In my opinion it was better to reuse already existing migration channel, > so there are no necessary changes in higher layers. Furthermore, by > implementing this directly in QEMU, this feature can be used anywhere, > even if libvirt is not used. This requires more thought, leaving the policy to the upper may give us flexibility. > > > > > 1) reuse the existing filters > > 2) don't need to care about the vhost support on the source as vhost > > is disabled, for vDPA we can reuse shadow virtqueue > > Can you elaborate more on vhost being disabled? IUUC QEMU net filters > don't support vhost=on, including the redirector filter. We only need the filter work when vm is paused, in this case vhost is disabled. We can use packet socket to read or inject packet to tap. > > > 3) for the destination we can install a redirector to packet socket to > > let vhost works like socket -> redirector -> buffer -> redirector -> > > packet socket. > > > > Thanks > > > Thanks
