From eea1e5c9d6fac211cf3fe2d3d7f3be2bf767d421 Mon Sep 17 00:00:00 2001 From: Steve Sistare Date: Wed, 25 Oct 2023 12:44:24 -0700 Subject: migration: mode parameter Create a mode migration parameter that can be used to select alternate migration algorithms. The default mode is normal, representing the current migration algorithm, and does not need to be explicitly set. No functional change until a new mode is added, except that the mode is shown by the 'info migrate' command. Signed-off-by: Steve Sistare Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela Message-ID: <1698263069-406971-2-git-send-email-steven.sistare@oracle.com> --- migration/migration-hmp-cmds.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'migration/migration-hmp-cmds.c') diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index dfe98da355..a170440991 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -387,6 +387,11 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: %" PRIu64 " MB/s\n", MigrationParameter_str(MIGRATION_PARAMETER_VCPU_DIRTY_LIMIT), params->vcpu_dirty_limit); + + assert(params->has_mode); + monitor_printf(mon, "%s: %s\n", + MigrationParameter_str(MIGRATION_PARAMETER_MODE), + qapi_enum_lookup(&MigMode_lookup, params->mode)); } qapi_free_MigrationParameters(params); @@ -661,6 +666,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_vcpu_dirty_limit = true; visit_type_size(v, param, &p->vcpu_dirty_limit, &err); break; + case MIGRATION_PARAMETER_MODE: + p->has_mode = true; + visit_type_MigMode(v, param, &p->mode, &err); + break; default: assert(0); } -- cgit 1.4.1 From 074dbce5fcce597e61ff6c44d2977458f0ba2f29 Mon Sep 17 00:00:00 2001 From: Het Gala Date: Mon, 23 Oct 2023 15:20:48 -0300 Subject: migration: New migrate and migrate-incoming argument 'channels' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MigrateChannelList allows to connect accross multiple interfaces. Add MigrateChannelList struct as argument to migration QAPIs. We plan to include multiple channels in future, to connnect multiple interfaces. Hence, we choose 'MigrateChannelList' as the new argument over 'MigrateChannel' to make migration QAPIs future proof. Suggested-by: Aravind Retnakaran Signed-off-by: Het Gala Acked-by: Markus Armbruster Reviewed-by: Daniel P. Berrangé Signed-off-by: Fabiano Rosas Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela Message-ID: <20231023182053.8711-10-farosas@suse.de> --- migration/migration-hmp-cmds.c | 6 +-- migration/migration.c | 56 ++++++++++++++++++-- qapi/migration.json | 113 ++++++++++++++++++++++++++++++++++++++++- system/vl.c | 2 +- 4 files changed, 167 insertions(+), 10 deletions(-) (limited to 'migration/migration-hmp-cmds.c') diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index a170440991..6ec778a990 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -452,7 +452,7 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict) Error *err = NULL; const char *uri = qdict_get_str(qdict, "uri"); - qmp_migrate_incoming(uri, &err); + qmp_migrate_incoming(uri, false, NULL, &err); hmp_handle_error(mon, err); } @@ -764,8 +764,8 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) " use blockdev-mirror with NBD instead"); } - qmp_migrate(uri, !!blk, blk, !!inc, inc, - false, false, true, resume, &err); + qmp_migrate(uri, false, NULL, !!blk, blk, !!inc, inc, + false, false, true, resume, &err); if (hmp_handle_error(mon, err)) { return; } diff --git a/migration/migration.c b/migration/migration.c index 04037b340c..a9cd5e2d5d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -506,11 +506,34 @@ static bool migrate_uri_parse(const char *uri, return true; } -static void qemu_start_incoming_migration(const char *uri, Error **errp) +static void qemu_start_incoming_migration(const char *uri, bool has_channels, + MigrationChannelList *channels, + Error **errp) { g_autoptr(MigrationAddress) channel = NULL; MigrationIncomingState *mis = migration_incoming_get_current(); + /* + * Having preliminary checks for uri and channel + */ + if (has_channels) { + error_setg(errp, "'channels' argument should not be set yet."); + return; + } + + if (uri && has_channels) { + error_setg(errp, "'uri' and 'channels' arguments are mutually " + "exclusive; exactly one of the two should be present in " + "'migrate-incoming' qmp command "); + return; + } + + if (!uri && !has_channels) { + error_setg(errp, "neither 'uri' or 'channels' argument are " + "specified in 'migrate-incoming' qmp command "); + return; + } + /* URI is not suitable for migration? */ if (!migration_channels_and_uri_compatible(uri, errp)) { return; @@ -1681,7 +1704,8 @@ void migrate_del_blocker(Error **reasonp) } } -void qmp_migrate_incoming(const char *uri, Error **errp) +void qmp_migrate_incoming(const char *uri, bool has_channels, + MigrationChannelList *channels, Error **errp) { Error *local_err = NULL; static bool once = true; @@ -1699,7 +1723,7 @@ void qmp_migrate_incoming(const char *uri, Error **errp) return; } - qemu_start_incoming_migration(uri, &local_err); + qemu_start_incoming_migration(uri, has_channels, channels, &local_err); if (local_err) { yank_unregister_instance(MIGRATION_YANK_INSTANCE); @@ -1735,7 +1759,7 @@ void qmp_migrate_recover(const char *uri, Error **errp) * only re-setup the migration stream and poke existing migration * to continue using that newly established channel. */ - qemu_start_incoming_migration(uri, errp); + qemu_start_incoming_migration(uri, false, NULL, errp); } void qmp_migrate_pause(Error **errp) @@ -1892,7 +1916,8 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, return true; } -void qmp_migrate(const char *uri, bool has_blk, bool blk, +void qmp_migrate(const char *uri, bool has_channels, + MigrationChannelList *channels, bool has_blk, bool blk, bool has_inc, bool inc, bool has_detach, bool detach, bool has_resume, bool resume, Error **errp) { @@ -1901,6 +1926,27 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, MigrationState *s = migrate_get_current(); g_autoptr(MigrationAddress) channel = NULL; + /* + * Having preliminary checks for uri and channel + */ + if (has_channels) { + error_setg(errp, "'channels' argument should not be set yet."); + return; + } + + if (uri && has_channels) { + error_setg(errp, "'uri' and 'channels' arguments are mutually " + "exclusive; exactly one of the two should be present in " + "'migrate' qmp command "); + return; + } + + if (!uri && !has_channels) { + error_setg(errp, "neither 'uri' or 'channels' argument are " + "specified in 'migrate' qmp command "); + return; + } + /* URI is not suitable for migration? */ if (!migration_channels_and_uri_compatible(uri, errp)) { return; diff --git a/qapi/migration.json b/qapi/migration.json index 182b150b87..975761eebd 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1641,6 +1641,34 @@ 'rdma': 'InetSocketAddress', 'file': 'FileMigrationArgs' } } +## +# @MigrationChannelType: +# +# The migration channel-type request options. +# +# @main: Main outbound migration channel. +# +# Since 8.1 +## +{ 'enum': 'MigrationChannelType', + 'data': [ 'main' ] } + +## +# @MigrationChannel: +# +# Migration stream channel parameters. +# +# @channel-type: Channel type for transfering packet information. +# +# @addr: Migration endpoint configuration on destination interface. +# +# Since 8.1 +## +{ 'struct': 'MigrationChannel', + 'data': { + 'channel-type': 'MigrationChannelType', + 'addr': 'MigrationAddress' } } + ## # @migrate: # @@ -1648,6 +1676,9 @@ # # @uri: the Uniform Resource Identifier of the destination VM # +# @channels: list of migration stream channels with each stream in the +# list connected to a destination interface endpoint. +# # @blk: do block migration (full disk copy) # # @inc: incremental disk copy migration @@ -1677,13 +1708,57 @@ # 3. The user Monitor's "detach" argument is invalid in QMP and should # not be used # +# 4. The uri argument should have the Uniform Resource Identifier of +# default destination VM. This connection will be bound to default +# network. +# +# 5. For now, number of migration streams is restricted to one, i.e +# number of items in 'channels' list is just 1. +# +# 6. The 'uri' and 'channels' arguments are mutually exclusive; +# exactly one of the two should be present. +# # Example: # # -> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } } # <- { "return": {} } +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "socket", +# "type": "inet", +# "host": "10.12.34.9", +# "port": "1050" } } ] } } +# <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "exec", +# "args": [ "/bin/nc", "-p", "6000", +# "/some/sock" ] } } ] } } +# <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "rdma", +# "host": "10.12.34.9", +# "port": "1050" } } ] } } +# <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "file", +# "filename": "/tmp/migfile", +# "offset": "0x1000" } } ] } } +# <- { "return": {} } +# ## { 'command': 'migrate', 'data': {'uri': 'str', + '*channels': [ 'MigrationChannel' ], '*blk': { 'type': 'bool', 'features': [ 'deprecated' ] }, '*inc': { 'type': 'bool', 'features': [ 'deprecated' ] }, '*detach': 'bool', '*resume': 'bool' } } @@ -1697,6 +1772,9 @@ # @uri: The Uniform Resource Identifier identifying the source or # address to listen on # +# @channels: list of migration stream channels with each stream in the +# list connected to a destination interface endpoint. +# # Returns: nothing on success # # Since: 2.3 @@ -1712,13 +1790,46 @@ # # 3. The uri format is the same as for -incoming # +# 5. For now, number of migration streams is restricted to one, i.e +# number of items in 'channels' list is just 1. +# +# 4. The 'uri' and 'channels' arguments are mutually exclusive; +# exactly one of the two should be present. +# # Example: # # -> { "execute": "migrate-incoming", # "arguments": { "uri": "tcp::4446" } } # <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "socket", +# "type": "inet", +# "host": "10.12.34.9", +# "port": "1050" } } ] } } +# <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "exec", +# "args": [ "/bin/nc", "-p", "6000", +# "/some/sock" ] } } ] } } +# <- { "return": {} } +# +# -> { "execute": "migrate", +# "arguments": { +# "channels": [ { "channel-type": "main", +# "addr": { "transport": "rdma", +# "host": "10.12.34.9", +# "port": "1050" } } ] } } +# <- { "return": {} } ## -{ 'command': 'migrate-incoming', 'data': {'uri': 'str' } } +{ 'command': 'migrate-incoming', + 'data': {'*uri': 'str', + '*channels': [ 'MigrationChannel' ] } } ## # @xen-save-devices-state: diff --git a/system/vl.c b/system/vl.c index 92d29bf521..3fb569254a 100644 --- a/system/vl.c +++ b/system/vl.c @@ -2702,7 +2702,7 @@ void qmp_x_exit_preconfig(Error **errp) if (incoming) { Error *local_err = NULL; if (strcmp(incoming, "defer") != 0) { - qmp_migrate_incoming(incoming, &local_err); + qmp_migrate_incoming(incoming, false, NULL, &local_err); if (local_err) { error_reportf_err(local_err, "-incoming %s: ", incoming); exit(1); -- cgit 1.4.1 From 967f2de5c9ec224480b940d5c9fc207ca625b7d8 Mon Sep 17 00:00:00 2001 From: Het Gala Date: Mon, 23 Oct 2023 15:20:52 -0300 Subject: migration: Implement MigrateChannelList to hmp migration flow. Integrate MigrateChannelList with all transport backends (socket, exec and rdma) for both src and dest migration endpoints for hmp migration. Suggested-by: Aravind Retnakaran Signed-off-by: Het Gala Signed-off-by: Fabiano Rosas Message-ID: <20231023182053.8711-14-farosas@suse.de> Signed-off-by: Juan Quintela --- migration/migration-hmp-cmds.c | 23 +++++++++++++++++++++-- migration/migration.c | 5 ++--- migration/migration.h | 3 ++- 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'migration/migration-hmp-cmds.c') diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index 6ec778a990..86ae832176 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -451,9 +451,18 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict) { Error *err = NULL; const char *uri = qdict_get_str(qdict, "uri"); + MigrationChannelList *caps = NULL; + g_autoptr(MigrationChannel) channel = NULL; - qmp_migrate_incoming(uri, false, NULL, &err); + if (!migrate_uri_parse(uri, &channel, &err)) { + goto end; + } + QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel)); + qmp_migrate_incoming(NULL, true, caps, &err); + qapi_free_MigrationChannelList(caps); + +end: hmp_handle_error(mon, err); } @@ -753,6 +762,8 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) bool resume = qdict_get_try_bool(qdict, "resume", false); const char *uri = qdict_get_str(qdict, "uri"); Error *err = NULL; + MigrationChannelList *caps = NULL; + g_autoptr(MigrationChannel) channel = NULL; if (inc) { warn_report("option '-i' is deprecated;" @@ -764,12 +775,20 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) " use blockdev-mirror with NBD instead"); } - qmp_migrate(uri, false, NULL, !!blk, blk, !!inc, inc, + if (!migrate_uri_parse(uri, &channel, &err)) { + hmp_handle_error(mon, err); + return; + } + QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel)); + + qmp_migrate(NULL, true, caps, !!blk, blk, !!inc, inc, false, false, true, resume, &err); if (hmp_handle_error(mon, err)) { return; } + qapi_free_MigrationChannelList(caps); + if (!detach) { HMPMigrationStatus *status; diff --git a/migration/migration.c b/migration/migration.c index 10a6f2fb12..28a34c9068 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -457,9 +457,8 @@ void migrate_add_address(SocketAddress *address) QAPI_CLONE(SocketAddress, address)); } -static bool migrate_uri_parse(const char *uri, - MigrationChannel **channel, - Error **errp) +bool migrate_uri_parse(const char *uri, MigrationChannel **channel, + Error **errp) { g_autoptr(MigrationChannel) val = g_new0(MigrationChannel, 1); g_autoptr(MigrationAddress) addr = g_new0(MigrationAddress, 1); diff --git a/migration/migration.h b/migration/migration.h index af8c965b7f..cf2c9c88e0 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -520,7 +520,8 @@ bool check_dirty_bitmap_mig_alias_map(const BitmapMigrationNodeAliasList *bbm, Error **errp); void migrate_add_address(SocketAddress *address); - +bool migrate_uri_parse(const char *uri, MigrationChannel **channel, + Error **errp); int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); #define qemu_ram_foreach_block \ -- cgit 1.4.1