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


Reply via email to