Add SaveVMHandlers struct for virtio-net iterative migration support. The handlers are registered but only contain no-op implementations.
This provides the framework for iterative migration without changing any actual migration behavior when the capability is disabled. A BFD representation is used when registering a virtio-net device's SaveVMHandlers hooks. This is to create unique IDs in the case of multiple virtio-net devices. Signed-off-by: Jonah Palmer <jonah.pal...@oracle.com> --- hw/net/virtio-net.c | 85 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 93029104b3..19aa5b5936 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -17,6 +17,7 @@ #include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" +#include "qemu/cutils.h" #include "hw/virtio/virtio.h" #include "net/net.h" #include "net/checksum.h" @@ -38,6 +39,9 @@ #include "qapi/qapi-events-migration.h" #include "hw/virtio/virtio-access.h" #include "migration/misc.h" +#include "migration/register.h" +#include "migration/qemu-file.h" +#include "migration/migration.h" #include "standard-headers/linux/ethtool.h" #include "system/system.h" #include "system/replay.h" @@ -3791,11 +3795,77 @@ static const VMStateDescription vmstate_virtio_net = { .dev_unplug_pending = dev_unplug_pending, }; +static bool virtio_net_iterative_migration_enabled(void) +{ + MigrationState *s = migrate_get_current(); + return s->capabilities[MIGRATION_CAPABILITY_VIRTIO_ITERATIVE]; +} + +static bool virtio_net_is_active(void *opaque) +{ + return virtio_net_iterative_migration_enabled(); +} + +static int virtio_net_save_setup(QEMUFile *f, void *opaque, Error **errp) +{ + return 0; +} + +static int virtio_net_save_live_iterate(QEMUFile *f, void *opaque) +{ + return 1; +} + +static int virtio_net_save_live_complete_precopy(QEMUFile *f, void *opaque) +{ + return 0; +} + +static void virtio_net_save_cleanup(void *opaque) +{ + +} + +static int virtio_net_load_setup(QEMUFile *f, void *opaque, Error **errp) +{ + return 0; +} + +static int virtio_net_load_state(QEMUFile *f, void *opaque, int version_id) +{ + return 0; +} + +static int virtio_net_load_cleanup(void *opaque) +{ + return 0; +} + +static void virtio_net_state_pending_exact(void *opaque, uint64_t *must_precopy, + uint64_t *can_postcopy) +{ + +} + +static const SaveVMHandlers savevm_virtio_net_handlers = { + .is_active = virtio_net_is_active, + .save_setup = virtio_net_save_setup, + .save_live_iterate = virtio_net_save_live_iterate, + .save_live_complete_precopy = virtio_net_save_live_complete_precopy, + .save_cleanup = virtio_net_save_cleanup, + .load_setup = virtio_net_load_setup, + .load_state = virtio_net_load_state, + .load_cleanup = virtio_net_load_cleanup, + .state_pending_exact = virtio_net_state_pending_exact, +}; + static void virtio_net_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIONet *n = VIRTIO_NET(dev); NetClientState *nc; + g_autofree char *path = NULL; + char id[256] = ""; int i; if (n->net_conf.mtu) { @@ -3963,12 +4033,21 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { virtio_net_load_ebpf(n, errp); } + + /* Register handlers for iterative migration */ + path = qdev_get_dev_path(DEVICE(&n->parent_obj)); + path = g_strdup_printf("%s/virtio-net-iterative", path); + strpadcpy(id, sizeof(id), path, '\0'); + register_savevm_live(id, VMSTATE_INSTANCE_ID_ANY, 1, + &savevm_virtio_net_handlers, n); } static void virtio_net_device_unrealize(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIONet *n = VIRTIO_NET(dev); + g_autofree char *path = NULL; + char id[256] = ""; int i, max_queue_pairs; if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { @@ -4007,6 +4086,12 @@ static void virtio_net_device_unrealize(DeviceState *dev) g_free(n->rss_data.indirections_table); net_rx_pkt_uninit(n->rx_pkt); virtio_cleanup(vdev); + + /* Unregister migration handlers */ + path = qdev_get_dev_path(DEVICE(&n->parent_obj)); + path = g_strdup_printf("%s/virtio-net-iterative", path); + strpadcpy(id, sizeof(id), path, '\0'); + unregister_savevm(VMSTATE_IF(dev), id, n); } static void virtio_net_reset(VirtIODevice *vdev) -- 2.47.1