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.palmer@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