18a645544SFabiano Rosas /*
28a645544SFabiano Rosas * QTest testcase for precopy migration
38a645544SFabiano Rosas *
48a645544SFabiano Rosas * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
58a645544SFabiano Rosas * based on the vhost-user-test.c that is:
68a645544SFabiano Rosas * Copyright (c) 2014 Virtual Open Systems Sarl.
78a645544SFabiano Rosas *
88a645544SFabiano Rosas * This work is licensed under the terms of the GNU GPL, version 2 or later.
98a645544SFabiano Rosas * See the COPYING file in the top-level directory.
108a645544SFabiano Rosas *
118a645544SFabiano Rosas */
128a645544SFabiano Rosas
138a645544SFabiano Rosas #include "qemu/osdep.h"
148a645544SFabiano Rosas #include "chardev/char.h"
158a645544SFabiano Rosas #include "crypto/tlscredspsk.h"
168a645544SFabiano Rosas #include "libqtest.h"
178a645544SFabiano Rosas #include "migration/bootfile.h"
188a645544SFabiano Rosas #include "migration/framework.h"
198a645544SFabiano Rosas #include "migration/migration-qmp.h"
208a645544SFabiano Rosas #include "migration/migration-util.h"
218a645544SFabiano Rosas #include "ppc-util.h"
22407bc4bfSDaniel P. Berrangé #include "qobject/qlist.h"
23*538e03d2SFabiano Rosas #include "qapi-types-migration.h"
248a645544SFabiano Rosas #include "qemu/module.h"
258a645544SFabiano Rosas #include "qemu/option.h"
268a645544SFabiano Rosas #include "qemu/range.h"
278a645544SFabiano Rosas #include "qemu/sockets.h"
288a645544SFabiano Rosas
298a645544SFabiano Rosas
308a645544SFabiano Rosas /*
318a645544SFabiano Rosas * Dirtylimit stop working if dirty page rate error
328a645544SFabiano Rosas * value less than DIRTYLIMIT_TOLERANCE_RANGE
338a645544SFabiano Rosas */
348a645544SFabiano Rosas #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */
358a645544SFabiano Rosas
368a645544SFabiano Rosas static char *tmpfs;
378a645544SFabiano Rosas
test_precopy_unix_plain(void)388a645544SFabiano Rosas static void test_precopy_unix_plain(void)
398a645544SFabiano Rosas {
408a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
418a645544SFabiano Rosas MigrateCommon args = {
428a645544SFabiano Rosas .listen_uri = uri,
438a645544SFabiano Rosas .connect_uri = uri,
448a645544SFabiano Rosas /*
458a645544SFabiano Rosas * The simplest use case of precopy, covering smoke tests of
468a645544SFabiano Rosas * get-dirty-log dirty tracking.
478a645544SFabiano Rosas */
488a645544SFabiano Rosas .live = true,
498a645544SFabiano Rosas };
508a645544SFabiano Rosas
518a645544SFabiano Rosas test_precopy_common(&args);
528a645544SFabiano Rosas }
538a645544SFabiano Rosas
test_precopy_unix_suspend_live(void)548a645544SFabiano Rosas static void test_precopy_unix_suspend_live(void)
558a645544SFabiano Rosas {
568a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
578a645544SFabiano Rosas MigrateCommon args = {
588a645544SFabiano Rosas .listen_uri = uri,
598a645544SFabiano Rosas .connect_uri = uri,
608a645544SFabiano Rosas /*
618a645544SFabiano Rosas * despite being live, the test is fast because the src
628a645544SFabiano Rosas * suspends immediately.
638a645544SFabiano Rosas */
648a645544SFabiano Rosas .live = true,
658a645544SFabiano Rosas .start.suspend_me = true,
668a645544SFabiano Rosas };
678a645544SFabiano Rosas
688a645544SFabiano Rosas test_precopy_common(&args);
698a645544SFabiano Rosas }
708a645544SFabiano Rosas
test_precopy_unix_suspend_notlive(void)718a645544SFabiano Rosas static void test_precopy_unix_suspend_notlive(void)
728a645544SFabiano Rosas {
738a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
748a645544SFabiano Rosas MigrateCommon args = {
758a645544SFabiano Rosas .listen_uri = uri,
768a645544SFabiano Rosas .connect_uri = uri,
778a645544SFabiano Rosas .start.suspend_me = true,
788a645544SFabiano Rosas };
798a645544SFabiano Rosas
808a645544SFabiano Rosas test_precopy_common(&args);
818a645544SFabiano Rosas }
828a645544SFabiano Rosas
test_precopy_unix_dirty_ring(void)838a645544SFabiano Rosas static void test_precopy_unix_dirty_ring(void)
848a645544SFabiano Rosas {
858a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
868a645544SFabiano Rosas MigrateCommon args = {
878a645544SFabiano Rosas .start = {
888a645544SFabiano Rosas .use_dirty_ring = true,
898a645544SFabiano Rosas },
908a645544SFabiano Rosas .listen_uri = uri,
918a645544SFabiano Rosas .connect_uri = uri,
928a645544SFabiano Rosas /*
938a645544SFabiano Rosas * Besides the precopy/unix basic test, cover dirty ring interface
948a645544SFabiano Rosas * rather than get-dirty-log.
958a645544SFabiano Rosas */
968a645544SFabiano Rosas .live = true,
978a645544SFabiano Rosas };
988a645544SFabiano Rosas
998a645544SFabiano Rosas test_precopy_common(&args);
1008a645544SFabiano Rosas }
1018a645544SFabiano Rosas
test_precopy_tcp_plain(void)1028a645544SFabiano Rosas static void test_precopy_tcp_plain(void)
1038a645544SFabiano Rosas {
1048a645544SFabiano Rosas MigrateCommon args = {
1058a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0",
1068a645544SFabiano Rosas };
1078a645544SFabiano Rosas
1088a645544SFabiano Rosas test_precopy_common(&args);
1098a645544SFabiano Rosas }
1108a645544SFabiano Rosas
migrate_hook_start_switchover_ack(QTestState * from,QTestState * to)1118a645544SFabiano Rosas static void *migrate_hook_start_switchover_ack(QTestState *from, QTestState *to)
1128a645544SFabiano Rosas {
1138a645544SFabiano Rosas
1148a645544SFabiano Rosas migrate_set_capability(from, "return-path", true);
1158a645544SFabiano Rosas migrate_set_capability(to, "return-path", true);
1168a645544SFabiano Rosas
1178a645544SFabiano Rosas migrate_set_capability(from, "switchover-ack", true);
1188a645544SFabiano Rosas migrate_set_capability(to, "switchover-ack", true);
1198a645544SFabiano Rosas
1208a645544SFabiano Rosas return NULL;
1218a645544SFabiano Rosas }
1228a645544SFabiano Rosas
test_precopy_tcp_switchover_ack(void)1238a645544SFabiano Rosas static void test_precopy_tcp_switchover_ack(void)
1248a645544SFabiano Rosas {
1258a645544SFabiano Rosas MigrateCommon args = {
1268a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0",
1278a645544SFabiano Rosas .start_hook = migrate_hook_start_switchover_ack,
1288a645544SFabiano Rosas /*
1298a645544SFabiano Rosas * Source VM must be running in order to consider the switchover ACK
1308a645544SFabiano Rosas * when deciding to do switchover or not.
1318a645544SFabiano Rosas */
1328a645544SFabiano Rosas .live = true,
1338a645544SFabiano Rosas };
1348a645544SFabiano Rosas
1358a645544SFabiano Rosas test_precopy_common(&args);
1368a645544SFabiano Rosas }
1378a645544SFabiano Rosas
1388a645544SFabiano Rosas #ifndef _WIN32
migrate_hook_start_fd(QTestState * from,QTestState * to)1398a645544SFabiano Rosas static void *migrate_hook_start_fd(QTestState *from,
1408a645544SFabiano Rosas QTestState *to)
1418a645544SFabiano Rosas {
1428a645544SFabiano Rosas int ret;
1438a645544SFabiano Rosas int pair[2];
1448a645544SFabiano Rosas
1458a645544SFabiano Rosas /* Create two connected sockets for migration */
1468a645544SFabiano Rosas ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair);
1478a645544SFabiano Rosas g_assert_cmpint(ret, ==, 0);
1488a645544SFabiano Rosas
1498a645544SFabiano Rosas /* Send the 1st socket to the target */
1508a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &pair[0], 1,
1518a645544SFabiano Rosas "{ 'execute': 'getfd',"
1528a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
1538a645544SFabiano Rosas close(pair[0]);
1548a645544SFabiano Rosas
1558a645544SFabiano Rosas /* Start incoming migration from the 1st socket */
15643ca9d18SSteve Sistare migrate_incoming_qmp(to, "fd:fd-mig", NULL, "{}");
1578a645544SFabiano Rosas
1588a645544SFabiano Rosas /* Send the 2nd socket to the target */
1598a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &pair[1], 1,
1608a645544SFabiano Rosas "{ 'execute': 'getfd',"
1618a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
1628a645544SFabiano Rosas close(pair[1]);
1638a645544SFabiano Rosas
1648a645544SFabiano Rosas return NULL;
1658a645544SFabiano Rosas }
1668a645544SFabiano Rosas
migrate_hook_end_fd(QTestState * from,QTestState * to,void * opaque)1678a645544SFabiano Rosas static void migrate_hook_end_fd(QTestState *from,
1688a645544SFabiano Rosas QTestState *to,
1698a645544SFabiano Rosas void *opaque)
1708a645544SFabiano Rosas {
1718a645544SFabiano Rosas QDict *rsp;
1728a645544SFabiano Rosas const char *error_desc;
1738a645544SFabiano Rosas
1748a645544SFabiano Rosas /* Test closing fds */
1758a645544SFabiano Rosas /*
1768a645544SFabiano Rosas * We assume, that QEMU removes named fd from its list,
1778a645544SFabiano Rosas * so this should fail.
1788a645544SFabiano Rosas */
1798a645544SFabiano Rosas rsp = qtest_qmp(from,
1808a645544SFabiano Rosas "{ 'execute': 'closefd',"
1818a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
1828a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error"));
1838a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
1848a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
1858a645544SFabiano Rosas qobject_unref(rsp);
1868a645544SFabiano Rosas
1878a645544SFabiano Rosas rsp = qtest_qmp(to,
1888a645544SFabiano Rosas "{ 'execute': 'closefd',"
1898a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
1908a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error"));
1918a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
1928a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
1938a645544SFabiano Rosas qobject_unref(rsp);
1948a645544SFabiano Rosas }
1958a645544SFabiano Rosas
test_precopy_fd_socket(void)1968a645544SFabiano Rosas static void test_precopy_fd_socket(void)
1978a645544SFabiano Rosas {
1988a645544SFabiano Rosas MigrateCommon args = {
1998a645544SFabiano Rosas .listen_uri = "defer",
2008a645544SFabiano Rosas .connect_uri = "fd:fd-mig",
2018a645544SFabiano Rosas .start_hook = migrate_hook_start_fd,
2028a645544SFabiano Rosas .end_hook = migrate_hook_end_fd,
2038a645544SFabiano Rosas };
2048a645544SFabiano Rosas test_precopy_common(&args);
2058a645544SFabiano Rosas }
2068a645544SFabiano Rosas
migrate_hook_start_precopy_fd_file(QTestState * from,QTestState * to)2078a645544SFabiano Rosas static void *migrate_hook_start_precopy_fd_file(QTestState *from,
2088a645544SFabiano Rosas QTestState *to)
2098a645544SFabiano Rosas {
2108a645544SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
2118a645544SFabiano Rosas int src_flags = O_CREAT | O_RDWR;
2128a645544SFabiano Rosas int dst_flags = O_CREAT | O_RDWR;
2138a645544SFabiano Rosas int fds[2];
2148a645544SFabiano Rosas
2158a645544SFabiano Rosas fds[0] = open(file, src_flags, 0660);
2168a645544SFabiano Rosas assert(fds[0] != -1);
2178a645544SFabiano Rosas
2188a645544SFabiano Rosas fds[1] = open(file, dst_flags, 0660);
2198a645544SFabiano Rosas assert(fds[1] != -1);
2208a645544SFabiano Rosas
2218a645544SFabiano Rosas
2228a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &fds[0], 1,
2238a645544SFabiano Rosas "{ 'execute': 'getfd',"
2248a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
2258a645544SFabiano Rosas
2268a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &fds[1], 1,
2278a645544SFabiano Rosas "{ 'execute': 'getfd',"
2288a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
2298a645544SFabiano Rosas
2308a645544SFabiano Rosas close(fds[0]);
2318a645544SFabiano Rosas close(fds[1]);
2328a645544SFabiano Rosas
2338a645544SFabiano Rosas return NULL;
2348a645544SFabiano Rosas }
2358a645544SFabiano Rosas
test_precopy_fd_file(void)2368a645544SFabiano Rosas static void test_precopy_fd_file(void)
2378a645544SFabiano Rosas {
2388a645544SFabiano Rosas MigrateCommon args = {
2398a645544SFabiano Rosas .listen_uri = "defer",
2408a645544SFabiano Rosas .connect_uri = "fd:fd-mig",
2418a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_fd_file,
2428a645544SFabiano Rosas .end_hook = migrate_hook_end_fd,
2438a645544SFabiano Rosas };
2448a645544SFabiano Rosas test_file_common(&args, true);
2458a645544SFabiano Rosas }
2468a645544SFabiano Rosas #endif /* _WIN32 */
2478a645544SFabiano Rosas
2488a645544SFabiano Rosas /*
2498a645544SFabiano Rosas * The way auto_converge works, we need to do too many passes to
2508a645544SFabiano Rosas * run this test. Auto_converge logic is only run once every
2518a645544SFabiano Rosas * three iterations, so:
2528a645544SFabiano Rosas *
2538a645544SFabiano Rosas * - 3 iterations without auto_converge enabled
2548a645544SFabiano Rosas * - 3 iterations with pct = 5
2558a645544SFabiano Rosas * - 3 iterations with pct = 30
2568a645544SFabiano Rosas * - 3 iterations with pct = 55
2578a645544SFabiano Rosas * - 3 iterations with pct = 80
2588a645544SFabiano Rosas * - 3 iterations with pct = 95 (max(95, 80 + 25))
2598a645544SFabiano Rosas *
2608a645544SFabiano Rosas * To make things even worse, we need to run the initial stage at
2618a645544SFabiano Rosas * 3MB/s so we enter autoconverge even when host is (over)loaded.
2628a645544SFabiano Rosas */
test_auto_converge(void)2638a645544SFabiano Rosas static void test_auto_converge(void)
2648a645544SFabiano Rosas {
2658a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
2668a645544SFabiano Rosas MigrateStart args = {};
2678a645544SFabiano Rosas QTestState *from, *to;
2688a645544SFabiano Rosas int64_t percentage;
2698a645544SFabiano Rosas
2708a645544SFabiano Rosas /*
2718a645544SFabiano Rosas * We want the test to be stable and as fast as possible.
2728a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without throttling,
2738a645544SFabiano Rosas * so we need to decrease a bandwidth.
2748a645544SFabiano Rosas */
2758a645544SFabiano Rosas const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
2768a645544SFabiano Rosas uint64_t prev_dirty_sync_cnt, dirty_sync_cnt;
2778a645544SFabiano Rosas int max_try_count, hit = 0;
2788a645544SFabiano Rosas
2798a645544SFabiano Rosas if (migrate_start(&from, &to, uri, &args)) {
2808a645544SFabiano Rosas return;
2818a645544SFabiano Rosas }
2828a645544SFabiano Rosas
2838a645544SFabiano Rosas migrate_set_capability(from, "auto-converge", true);
2848a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct);
2858a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct);
2868a645544SFabiano Rosas migrate_set_parameter_int(from, "max-cpu-throttle", max_pct);
2878a645544SFabiano Rosas
2888a645544SFabiano Rosas /*
2898a645544SFabiano Rosas * Set the initial parameters so that the migration could not converge
2908a645544SFabiano Rosas * without throttling.
2918a645544SFabiano Rosas */
2928a645544SFabiano Rosas migrate_ensure_non_converge(from);
2938a645544SFabiano Rosas
2948a645544SFabiano Rosas /* To check remaining size after precopy */
2958a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true);
2968a645544SFabiano Rosas
2978a645544SFabiano Rosas /* Wait for the first serial output from the source */
2988a645544SFabiano Rosas wait_for_serial("src_serial");
2998a645544SFabiano Rosas
3008a645544SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
3018a645544SFabiano Rosas
3028a645544SFabiano Rosas /* Wait for throttling begins */
3038a645544SFabiano Rosas percentage = 0;
3048a645544SFabiano Rosas do {
3058a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
3068a645544SFabiano Rosas if (percentage != 0) {
3078a645544SFabiano Rosas break;
3088a645544SFabiano Rosas }
3098a645544SFabiano Rosas usleep(20);
3108a645544SFabiano Rosas g_assert_false(get_src()->stop_seen);
3118a645544SFabiano Rosas } while (true);
3128a645544SFabiano Rosas /* The first percentage of throttling should be at least init_pct */
3138a645544SFabiano Rosas g_assert_cmpint(percentage, >=, init_pct);
3148a645544SFabiano Rosas
3158a645544SFabiano Rosas /*
3168a645544SFabiano Rosas * End the loop when the dirty sync count greater than 1.
3178a645544SFabiano Rosas */
3188a645544SFabiano Rosas while ((dirty_sync_cnt = get_migration_pass(from)) < 2) {
3198a645544SFabiano Rosas usleep(1000 * 1000);
3208a645544SFabiano Rosas }
3218a645544SFabiano Rosas
3228a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt;
3238a645544SFabiano Rosas
3248a645544SFabiano Rosas /*
3258a645544SFabiano Rosas * The RAMBlock dirty sync count must changes in 5 seconds, here we set
3268a645544SFabiano Rosas * the timeout to 10 seconds to ensure it changes.
3278a645544SFabiano Rosas *
3288a645544SFabiano Rosas * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s,
3298a645544SFabiano Rosas * while the qtest mem is >= 100MB, one iteration takes at least 33s (100/3)
3308a645544SFabiano Rosas * to complete; this ensures that the RAMBlock dirty sync occurs.
3318a645544SFabiano Rosas */
3328a645544SFabiano Rosas max_try_count = 10;
3338a645544SFabiano Rosas while (--max_try_count) {
3348a645544SFabiano Rosas dirty_sync_cnt = get_migration_pass(from);
3358a645544SFabiano Rosas if (dirty_sync_cnt != prev_dirty_sync_cnt) {
3368a645544SFabiano Rosas hit = 1;
3378a645544SFabiano Rosas break;
3388a645544SFabiano Rosas }
3398a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt;
3408a645544SFabiano Rosas sleep(1);
3418a645544SFabiano Rosas }
3428a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1);
3438a645544SFabiano Rosas
3448a645544SFabiano Rosas /* Now, when we tested that throttling works, let it converge */
3458a645544SFabiano Rosas migrate_ensure_converge(from);
3468a645544SFabiano Rosas
3478a645544SFabiano Rosas /*
3488a645544SFabiano Rosas * Wait for pre-switchover status to check last throttle percentage
3498a645544SFabiano Rosas * and remaining. These values will be zeroed later
3508a645544SFabiano Rosas */
3518a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL);
3528a645544SFabiano Rosas
3538a645544SFabiano Rosas /* The final percentage of throttling shouldn't be greater than max_pct */
3548a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
3558a645544SFabiano Rosas g_assert_cmpint(percentage, <=, max_pct);
3568a645544SFabiano Rosas migrate_continue(from, "pre-switchover");
3578a645544SFabiano Rosas
3588a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME");
3598a645544SFabiano Rosas
3608a645544SFabiano Rosas wait_for_serial("dest_serial");
3618a645544SFabiano Rosas wait_for_migration_complete(from);
3628a645544SFabiano Rosas
3638a645544SFabiano Rosas migrate_end(from, to, true);
3648a645544SFabiano Rosas }
3658a645544SFabiano Rosas
3668a645544SFabiano Rosas static void *
migrate_hook_start_precopy_tcp_multifd(QTestState * from,QTestState * to)3678a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd(QTestState *from,
3688a645544SFabiano Rosas QTestState *to)
3698a645544SFabiano Rosas {
3708a645544SFabiano Rosas return migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
3718a645544SFabiano Rosas }
3728a645544SFabiano Rosas
3738a645544SFabiano Rosas static void *
migrate_hook_start_precopy_tcp_multifd_zero_page_legacy(QTestState * from,QTestState * to)3748a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_zero_page_legacy(QTestState *from,
3758a645544SFabiano Rosas QTestState *to)
3768a645544SFabiano Rosas {
3778a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
3788a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "legacy");
3798a645544SFabiano Rosas return NULL;
3808a645544SFabiano Rosas }
3818a645544SFabiano Rosas
3828a645544SFabiano Rosas static void *
migrate_hook_start_precopy_tcp_multifd_no_zero_page(QTestState * from,QTestState * to)3838a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_no_zero_page(QTestState *from,
3848a645544SFabiano Rosas QTestState *to)
3858a645544SFabiano Rosas {
3868a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
3878a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "none");
3888a645544SFabiano Rosas return NULL;
3898a645544SFabiano Rosas }
3908a645544SFabiano Rosas
test_multifd_tcp_uri_none(void)3918a645544SFabiano Rosas static void test_multifd_tcp_uri_none(void)
3928a645544SFabiano Rosas {
3938a645544SFabiano Rosas MigrateCommon args = {
3948a645544SFabiano Rosas .listen_uri = "defer",
3958a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd,
3968a645544SFabiano Rosas /*
3978a645544SFabiano Rosas * Multifd is more complicated than most of the features, it
3988a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure
3998a645544SFabiano Rosas * everything will work alright even if guest page is changing.
4008a645544SFabiano Rosas */
4018a645544SFabiano Rosas .live = true,
4028a645544SFabiano Rosas };
4038a645544SFabiano Rosas test_precopy_common(&args);
4048a645544SFabiano Rosas }
4058a645544SFabiano Rosas
test_multifd_tcp_zero_page_legacy(void)4068a645544SFabiano Rosas static void test_multifd_tcp_zero_page_legacy(void)
4078a645544SFabiano Rosas {
4088a645544SFabiano Rosas MigrateCommon args = {
4098a645544SFabiano Rosas .listen_uri = "defer",
4108a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_zero_page_legacy,
4118a645544SFabiano Rosas /*
4128a645544SFabiano Rosas * Multifd is more complicated than most of the features, it
4138a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure
4148a645544SFabiano Rosas * everything will work alright even if guest page is changing.
4158a645544SFabiano Rosas */
4168a645544SFabiano Rosas .live = true,
4178a645544SFabiano Rosas };
4188a645544SFabiano Rosas test_precopy_common(&args);
4198a645544SFabiano Rosas }
4208a645544SFabiano Rosas
test_multifd_tcp_no_zero_page(void)4218a645544SFabiano Rosas static void test_multifd_tcp_no_zero_page(void)
4228a645544SFabiano Rosas {
4238a645544SFabiano Rosas MigrateCommon args = {
4248a645544SFabiano Rosas .listen_uri = "defer",
4258a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_no_zero_page,
4268a645544SFabiano Rosas /*
4278a645544SFabiano Rosas * Multifd is more complicated than most of the features, it
4288a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure
4298a645544SFabiano Rosas * everything will work alright even if guest page is changing.
4308a645544SFabiano Rosas */
4318a645544SFabiano Rosas .live = true,
4328a645544SFabiano Rosas };
4338a645544SFabiano Rosas test_precopy_common(&args);
4348a645544SFabiano Rosas }
4358a645544SFabiano Rosas
test_multifd_tcp_channels_none(void)4368a645544SFabiano Rosas static void test_multifd_tcp_channels_none(void)
4378a645544SFabiano Rosas {
4388a645544SFabiano Rosas MigrateCommon args = {
4398a645544SFabiano Rosas .listen_uri = "defer",
4408a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd,
4418a645544SFabiano Rosas .live = true,
4428a645544SFabiano Rosas .connect_channels = ("[ { 'channel-type': 'main',"
4438a645544SFabiano Rosas " 'addr': { 'transport': 'socket',"
4448a645544SFabiano Rosas " 'type': 'inet',"
4458a645544SFabiano Rosas " 'host': '127.0.0.1',"
4468a645544SFabiano Rosas " 'port': '0' } } ]"),
4478a645544SFabiano Rosas };
4488a645544SFabiano Rosas test_precopy_common(&args);
4498a645544SFabiano Rosas }
4508a645544SFabiano Rosas
4518a645544SFabiano Rosas /*
4528a645544SFabiano Rosas * This test does:
4538a645544SFabiano Rosas * source target
4548a645544SFabiano Rosas * migrate_incoming
4558a645544SFabiano Rosas * migrate
4568a645544SFabiano Rosas * migrate_cancel
4578a645544SFabiano Rosas * launch another target
4588a645544SFabiano Rosas * migrate
4598a645544SFabiano Rosas *
4608a645544SFabiano Rosas * And see that it works
4618a645544SFabiano Rosas */
test_multifd_tcp_cancel(void)4628a645544SFabiano Rosas static void test_multifd_tcp_cancel(void)
4638a645544SFabiano Rosas {
4648a645544SFabiano Rosas MigrateStart args = {
4658a645544SFabiano Rosas .hide_stderr = true,
4668a645544SFabiano Rosas };
4678a645544SFabiano Rosas QTestState *from, *to, *to2;
4688a645544SFabiano Rosas
4698a645544SFabiano Rosas if (migrate_start(&from, &to, "defer", &args)) {
4708a645544SFabiano Rosas return;
4718a645544SFabiano Rosas }
4728a645544SFabiano Rosas
4738a645544SFabiano Rosas migrate_ensure_non_converge(from);
4748a645544SFabiano Rosas migrate_prepare_for_dirty_mem(from);
4758a645544SFabiano Rosas
4768a645544SFabiano Rosas migrate_set_parameter_int(from, "multifd-channels", 16);
4778a645544SFabiano Rosas migrate_set_parameter_int(to, "multifd-channels", 16);
4788a645544SFabiano Rosas
4798a645544SFabiano Rosas migrate_set_capability(from, "multifd", true);
4808a645544SFabiano Rosas migrate_set_capability(to, "multifd", true);
4818a645544SFabiano Rosas
4828a645544SFabiano Rosas /* Start incoming migration from the 1st socket */
48343ca9d18SSteve Sistare migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}");
4848a645544SFabiano Rosas
4858a645544SFabiano Rosas /* Wait for the first serial output from the source */
4868a645544SFabiano Rosas wait_for_serial("src_serial");
4878a645544SFabiano Rosas
4888a645544SFabiano Rosas migrate_qmp(from, to, NULL, NULL, "{}");
4898a645544SFabiano Rosas
4908a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to);
4918a645544SFabiano Rosas
4928a645544SFabiano Rosas migrate_cancel(from);
4938a645544SFabiano Rosas
4948a645544SFabiano Rosas /* Make sure QEMU process "to" exited */
4958a645544SFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE);
4968a645544SFabiano Rosas qtest_wait_qemu(to);
4978a645544SFabiano Rosas qtest_quit(to);
4988a645544SFabiano Rosas
4998a645544SFabiano Rosas /*
5008a645544SFabiano Rosas * Ensure the source QEMU finishes its cancellation process before we
5018a645544SFabiano Rosas * proceed with the setup of the next migration. The migrate_start()
5028a645544SFabiano Rosas * function and others might want to interact with the source in a way that
5038a645544SFabiano Rosas * is not possible while the migration is not canceled properly. For
5048a645544SFabiano Rosas * example, setting migration capabilities when the migration is still
5058a645544SFabiano Rosas * running leads to an error.
5068a645544SFabiano Rosas */
5078a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL);
5088a645544SFabiano Rosas
5098a645544SFabiano Rosas args = (MigrateStart){
5108a645544SFabiano Rosas .only_target = true,
5118a645544SFabiano Rosas };
5128a645544SFabiano Rosas
5138a645544SFabiano Rosas if (migrate_start(&from, &to2, "defer", &args)) {
5148a645544SFabiano Rosas return;
5158a645544SFabiano Rosas }
5168a645544SFabiano Rosas
5178a645544SFabiano Rosas migrate_set_parameter_int(to2, "multifd-channels", 16);
5188a645544SFabiano Rosas
5198a645544SFabiano Rosas migrate_set_capability(to2, "multifd", true);
5208a645544SFabiano Rosas
5218a645544SFabiano Rosas /* Start incoming migration from the 1st socket */
52243ca9d18SSteve Sistare migrate_incoming_qmp(to2, "tcp:127.0.0.1:0", NULL, "{}");
5238a645544SFabiano Rosas
5248a645544SFabiano Rosas migrate_ensure_non_converge(from);
5258a645544SFabiano Rosas
5268a645544SFabiano Rosas migrate_qmp(from, to2, NULL, NULL, "{}");
5278a645544SFabiano Rosas
5288a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to2);
5298a645544SFabiano Rosas
5308a645544SFabiano Rosas migrate_ensure_converge(from);
5318a645544SFabiano Rosas
5328a645544SFabiano Rosas wait_for_stop(from, get_src());
5338a645544SFabiano Rosas qtest_qmp_eventwait(to2, "RESUME");
5348a645544SFabiano Rosas
5358a645544SFabiano Rosas wait_for_serial("dest_serial");
5368a645544SFabiano Rosas wait_for_migration_complete(from);
5378a645544SFabiano Rosas migrate_end(from, to2, true);
5388a645544SFabiano Rosas }
5398a645544SFabiano Rosas
test_cancel_src_after_failed(QTestState * from,QTestState * to,const char * uri,const char * phase)540*538e03d2SFabiano Rosas static void test_cancel_src_after_failed(QTestState *from, QTestState *to,
541*538e03d2SFabiano Rosas const char *uri, const char *phase)
542*538e03d2SFabiano Rosas {
543*538e03d2SFabiano Rosas /*
544*538e03d2SFabiano Rosas * No migrate_incoming_qmp() at the start to force source into
545*538e03d2SFabiano Rosas * failed state during migrate_qmp().
546*538e03d2SFabiano Rosas */
547*538e03d2SFabiano Rosas
548*538e03d2SFabiano Rosas wait_for_serial("src_serial");
549*538e03d2SFabiano Rosas migrate_ensure_converge(from);
550*538e03d2SFabiano Rosas
551*538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
552*538e03d2SFabiano Rosas
553*538e03d2SFabiano Rosas migration_event_wait(from, phase);
554*538e03d2SFabiano Rosas migrate_cancel(from);
555*538e03d2SFabiano Rosas
556*538e03d2SFabiano Rosas /* cancelling will not move the migration out of 'failed' */
557*538e03d2SFabiano Rosas
558*538e03d2SFabiano Rosas wait_for_migration_status(from, "failed",
559*538e03d2SFabiano Rosas (const char * []) { "completed", NULL });
560*538e03d2SFabiano Rosas
561*538e03d2SFabiano Rosas /*
562*538e03d2SFabiano Rosas * Not waiting for the destination because it never started
563*538e03d2SFabiano Rosas * migration.
564*538e03d2SFabiano Rosas */
565*538e03d2SFabiano Rosas }
566*538e03d2SFabiano Rosas
test_cancel_src_after_cancelled(QTestState * from,QTestState * to,const char * uri,const char * phase)567*538e03d2SFabiano Rosas static void test_cancel_src_after_cancelled(QTestState *from, QTestState *to,
568*538e03d2SFabiano Rosas const char *uri, const char *phase)
569*538e03d2SFabiano Rosas {
570*538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }");
571*538e03d2SFabiano Rosas
572*538e03d2SFabiano Rosas wait_for_serial("src_serial");
573*538e03d2SFabiano Rosas migrate_ensure_converge(from);
574*538e03d2SFabiano Rosas
575*538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
576*538e03d2SFabiano Rosas
577*538e03d2SFabiano Rosas /* To move to cancelled/cancelling */
578*538e03d2SFabiano Rosas migrate_cancel(from);
579*538e03d2SFabiano Rosas migration_event_wait(from, phase);
580*538e03d2SFabiano Rosas
581*538e03d2SFabiano Rosas /* The migrate_cancel under test */
582*538e03d2SFabiano Rosas migrate_cancel(from);
583*538e03d2SFabiano Rosas
584*538e03d2SFabiano Rosas wait_for_migration_status(from, "cancelled",
585*538e03d2SFabiano Rosas (const char * []) { "completed", NULL });
586*538e03d2SFabiano Rosas
587*538e03d2SFabiano Rosas wait_for_migration_status(to, "failed",
588*538e03d2SFabiano Rosas (const char * []) { "completed", NULL });
589*538e03d2SFabiano Rosas }
590*538e03d2SFabiano Rosas
test_cancel_src_after_complete(QTestState * from,QTestState * to,const char * uri,const char * phase)591*538e03d2SFabiano Rosas static void test_cancel_src_after_complete(QTestState *from, QTestState *to,
592*538e03d2SFabiano Rosas const char *uri, const char *phase)
593*538e03d2SFabiano Rosas {
594*538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }");
595*538e03d2SFabiano Rosas
596*538e03d2SFabiano Rosas wait_for_serial("src_serial");
597*538e03d2SFabiano Rosas migrate_ensure_converge(from);
598*538e03d2SFabiano Rosas
599*538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
600*538e03d2SFabiano Rosas
601*538e03d2SFabiano Rosas migration_event_wait(from, phase);
602*538e03d2SFabiano Rosas migrate_cancel(from);
603*538e03d2SFabiano Rosas
604*538e03d2SFabiano Rosas /*
605*538e03d2SFabiano Rosas * qmp_migrate_cancel() exits early if migration is not running
606*538e03d2SFabiano Rosas * anymore, the status will not change to cancelled.
607*538e03d2SFabiano Rosas */
608*538e03d2SFabiano Rosas wait_for_migration_complete(from);
609*538e03d2SFabiano Rosas wait_for_migration_complete(to);
610*538e03d2SFabiano Rosas }
611*538e03d2SFabiano Rosas
test_cancel_src_after_none(QTestState * from,QTestState * to,const char * uri,const char * phase)612*538e03d2SFabiano Rosas static void test_cancel_src_after_none(QTestState *from, QTestState *to,
613*538e03d2SFabiano Rosas const char *uri, const char *phase)
614*538e03d2SFabiano Rosas {
615*538e03d2SFabiano Rosas /*
616*538e03d2SFabiano Rosas * Test that cancelling without a migration happening does not
617*538e03d2SFabiano Rosas * affect subsequent migrations
618*538e03d2SFabiano Rosas */
619*538e03d2SFabiano Rosas migrate_cancel(to);
620*538e03d2SFabiano Rosas
621*538e03d2SFabiano Rosas wait_for_serial("src_serial");
622*538e03d2SFabiano Rosas migrate_cancel(from);
623*538e03d2SFabiano Rosas
624*538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }");
625*538e03d2SFabiano Rosas
626*538e03d2SFabiano Rosas migrate_ensure_converge(from);
627*538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
628*538e03d2SFabiano Rosas
629*538e03d2SFabiano Rosas wait_for_migration_complete(from);
630*538e03d2SFabiano Rosas wait_for_migration_complete(to);
631*538e03d2SFabiano Rosas }
632*538e03d2SFabiano Rosas
test_cancel_src_pre_switchover(QTestState * from,QTestState * to,const char * uri,const char * phase)633*538e03d2SFabiano Rosas static void test_cancel_src_pre_switchover(QTestState *from, QTestState *to,
634*538e03d2SFabiano Rosas const char *uri, const char *phase)
635*538e03d2SFabiano Rosas {
636*538e03d2SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true);
637*538e03d2SFabiano Rosas migrate_set_capability(to, "pause-before-switchover", true);
638*538e03d2SFabiano Rosas
639*538e03d2SFabiano Rosas migrate_set_capability(from, "multifd", true);
640*538e03d2SFabiano Rosas migrate_set_capability(to, "multifd", true);
641*538e03d2SFabiano Rosas
642*538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }");
643*538e03d2SFabiano Rosas
644*538e03d2SFabiano Rosas wait_for_serial("src_serial");
645*538e03d2SFabiano Rosas migrate_ensure_converge(from);
646*538e03d2SFabiano Rosas
647*538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}");
648*538e03d2SFabiano Rosas
649*538e03d2SFabiano Rosas migration_event_wait(from, phase);
650*538e03d2SFabiano Rosas migrate_cancel(from);
651*538e03d2SFabiano Rosas migration_event_wait(from, "cancelling");
652*538e03d2SFabiano Rosas
653*538e03d2SFabiano Rosas wait_for_migration_status(from, "cancelled",
654*538e03d2SFabiano Rosas (const char * []) { "completed", NULL });
655*538e03d2SFabiano Rosas
656*538e03d2SFabiano Rosas wait_for_migration_status(to, "failed",
657*538e03d2SFabiano Rosas (const char * []) { "completed", NULL });
658*538e03d2SFabiano Rosas }
659*538e03d2SFabiano Rosas
test_cancel_src_after_status(void * opaque)660*538e03d2SFabiano Rosas static void test_cancel_src_after_status(void *opaque)
661*538e03d2SFabiano Rosas {
662*538e03d2SFabiano Rosas const char *test_path = opaque;
663*538e03d2SFabiano Rosas g_autofree char *phase = g_path_get_basename(test_path);
664*538e03d2SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
665*538e03d2SFabiano Rosas QTestState *from, *to;
666*538e03d2SFabiano Rosas MigrateStart args = {
667*538e03d2SFabiano Rosas .hide_stderr = true,
668*538e03d2SFabiano Rosas };
669*538e03d2SFabiano Rosas
670*538e03d2SFabiano Rosas if (migrate_start(&from, &to, "defer", &args)) {
671*538e03d2SFabiano Rosas return;
672*538e03d2SFabiano Rosas }
673*538e03d2SFabiano Rosas
674*538e03d2SFabiano Rosas if (g_str_equal(phase, "cancelling") ||
675*538e03d2SFabiano Rosas g_str_equal(phase, "cancelled")) {
676*538e03d2SFabiano Rosas test_cancel_src_after_cancelled(from, to, uri, phase);
677*538e03d2SFabiano Rosas
678*538e03d2SFabiano Rosas } else if (g_str_equal(phase, "completed")) {
679*538e03d2SFabiano Rosas test_cancel_src_after_complete(from, to, uri, phase);
680*538e03d2SFabiano Rosas
681*538e03d2SFabiano Rosas } else if (g_str_equal(phase, "failed")) {
682*538e03d2SFabiano Rosas test_cancel_src_after_failed(from, to, uri, phase);
683*538e03d2SFabiano Rosas
684*538e03d2SFabiano Rosas } else if (g_str_equal(phase, "none")) {
685*538e03d2SFabiano Rosas test_cancel_src_after_none(from, to, uri, phase);
686*538e03d2SFabiano Rosas
687*538e03d2SFabiano Rosas } else {
688*538e03d2SFabiano Rosas /* any state that comes before pre-switchover */
689*538e03d2SFabiano Rosas test_cancel_src_pre_switchover(from, to, uri, phase);
690*538e03d2SFabiano Rosas }
691*538e03d2SFabiano Rosas
692*538e03d2SFabiano Rosas migrate_end(from, to, false);
693*538e03d2SFabiano Rosas }
694*538e03d2SFabiano Rosas
calc_dirty_rate(QTestState * who,uint64_t calc_time)6958a645544SFabiano Rosas static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
6968a645544SFabiano Rosas {
6978a645544SFabiano Rosas qtest_qmp_assert_success(who,
6988a645544SFabiano Rosas "{ 'execute': 'calc-dirty-rate',"
6998a645544SFabiano Rosas "'arguments': { "
7008a645544SFabiano Rosas "'calc-time': %" PRIu64 ","
7018a645544SFabiano Rosas "'mode': 'dirty-ring' }}",
7028a645544SFabiano Rosas calc_time);
7038a645544SFabiano Rosas }
7048a645544SFabiano Rosas
query_dirty_rate(QTestState * who)7058a645544SFabiano Rosas static QDict *query_dirty_rate(QTestState *who)
7068a645544SFabiano Rosas {
7078a645544SFabiano Rosas return qtest_qmp_assert_success_ref(who,
7088a645544SFabiano Rosas "{ 'execute': 'query-dirty-rate' }");
7098a645544SFabiano Rosas }
7108a645544SFabiano Rosas
dirtylimit_set_all(QTestState * who,uint64_t dirtyrate)7118a645544SFabiano Rosas static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate)
7128a645544SFabiano Rosas {
7138a645544SFabiano Rosas qtest_qmp_assert_success(who,
7148a645544SFabiano Rosas "{ 'execute': 'set-vcpu-dirty-limit',"
7158a645544SFabiano Rosas "'arguments': { "
7168a645544SFabiano Rosas "'dirty-rate': %" PRIu64 " } }",
7178a645544SFabiano Rosas dirtyrate);
7188a645544SFabiano Rosas }
7198a645544SFabiano Rosas
cancel_vcpu_dirty_limit(QTestState * who)7208a645544SFabiano Rosas static void cancel_vcpu_dirty_limit(QTestState *who)
7218a645544SFabiano Rosas {
7228a645544SFabiano Rosas qtest_qmp_assert_success(who,
7238a645544SFabiano Rosas "{ 'execute': 'cancel-vcpu-dirty-limit' }");
7248a645544SFabiano Rosas }
7258a645544SFabiano Rosas
query_vcpu_dirty_limit(QTestState * who)7268a645544SFabiano Rosas static QDict *query_vcpu_dirty_limit(QTestState *who)
7278a645544SFabiano Rosas {
7288a645544SFabiano Rosas QDict *rsp;
7298a645544SFabiano Rosas
7308a645544SFabiano Rosas rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }");
7318a645544SFabiano Rosas g_assert(!qdict_haskey(rsp, "error"));
7328a645544SFabiano Rosas g_assert(qdict_haskey(rsp, "return"));
7338a645544SFabiano Rosas
7348a645544SFabiano Rosas return rsp;
7358a645544SFabiano Rosas }
7368a645544SFabiano Rosas
calc_dirtyrate_ready(QTestState * who)7378a645544SFabiano Rosas static bool calc_dirtyrate_ready(QTestState *who)
7388a645544SFabiano Rosas {
7398a645544SFabiano Rosas QDict *rsp_return;
7408a645544SFabiano Rosas const char *status;
7418a645544SFabiano Rosas bool ready;
7428a645544SFabiano Rosas
7438a645544SFabiano Rosas rsp_return = query_dirty_rate(who);
7448a645544SFabiano Rosas g_assert(rsp_return);
7458a645544SFabiano Rosas
7468a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status");
7478a645544SFabiano Rosas g_assert(status);
7488a645544SFabiano Rosas ready = g_strcmp0(status, "measuring");
7498a645544SFabiano Rosas qobject_unref(rsp_return);
7508a645544SFabiano Rosas
7518a645544SFabiano Rosas return ready;
7528a645544SFabiano Rosas }
7538a645544SFabiano Rosas
wait_for_calc_dirtyrate_complete(QTestState * who,int64_t time_s)7548a645544SFabiano Rosas static void wait_for_calc_dirtyrate_complete(QTestState *who,
7558a645544SFabiano Rosas int64_t time_s)
7568a645544SFabiano Rosas {
7578a645544SFabiano Rosas int max_try_count = 10000;
7588a645544SFabiano Rosas usleep(time_s * 1000000);
7598a645544SFabiano Rosas
7608a645544SFabiano Rosas while (!calc_dirtyrate_ready(who) && max_try_count--) {
7618a645544SFabiano Rosas usleep(1000);
7628a645544SFabiano Rosas }
7638a645544SFabiano Rosas
7648a645544SFabiano Rosas /*
7658a645544SFabiano Rosas * Set the timeout with 10 s(max_try_count * 1000us),
7668a645544SFabiano Rosas * if dirtyrate measurement not complete, fail test.
7678a645544SFabiano Rosas */
7688a645544SFabiano Rosas g_assert_cmpint(max_try_count, !=, 0);
7698a645544SFabiano Rosas }
7708a645544SFabiano Rosas
get_dirty_rate(QTestState * who)7718a645544SFabiano Rosas static int64_t get_dirty_rate(QTestState *who)
7728a645544SFabiano Rosas {
7738a645544SFabiano Rosas QDict *rsp_return;
7748a645544SFabiano Rosas const char *status;
7758a645544SFabiano Rosas QList *rates;
7768a645544SFabiano Rosas const QListEntry *entry;
7778a645544SFabiano Rosas QDict *rate;
7788a645544SFabiano Rosas int64_t dirtyrate;
7798a645544SFabiano Rosas
7808a645544SFabiano Rosas rsp_return = query_dirty_rate(who);
7818a645544SFabiano Rosas g_assert(rsp_return);
7828a645544SFabiano Rosas
7838a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status");
7848a645544SFabiano Rosas g_assert(status);
7858a645544SFabiano Rosas g_assert_cmpstr(status, ==, "measured");
7868a645544SFabiano Rosas
7878a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate");
7888a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates));
7898a645544SFabiano Rosas
7908a645544SFabiano Rosas entry = qlist_first(rates);
7918a645544SFabiano Rosas g_assert(entry);
7928a645544SFabiano Rosas
7938a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry));
7948a645544SFabiano Rosas g_assert(rate);
7958a645544SFabiano Rosas
7968a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1);
7978a645544SFabiano Rosas
7988a645544SFabiano Rosas qobject_unref(rsp_return);
7998a645544SFabiano Rosas return dirtyrate;
8008a645544SFabiano Rosas }
8018a645544SFabiano Rosas
get_limit_rate(QTestState * who)8028a645544SFabiano Rosas static int64_t get_limit_rate(QTestState *who)
8038a645544SFabiano Rosas {
8048a645544SFabiano Rosas QDict *rsp_return;
8058a645544SFabiano Rosas QList *rates;
8068a645544SFabiano Rosas const QListEntry *entry;
8078a645544SFabiano Rosas QDict *rate;
8088a645544SFabiano Rosas int64_t dirtyrate;
8098a645544SFabiano Rosas
8108a645544SFabiano Rosas rsp_return = query_vcpu_dirty_limit(who);
8118a645544SFabiano Rosas g_assert(rsp_return);
8128a645544SFabiano Rosas
8138a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "return");
8148a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates));
8158a645544SFabiano Rosas
8168a645544SFabiano Rosas entry = qlist_first(rates);
8178a645544SFabiano Rosas g_assert(entry);
8188a645544SFabiano Rosas
8198a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry));
8208a645544SFabiano Rosas g_assert(rate);
8218a645544SFabiano Rosas
8228a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "limit-rate", -1);
8238a645544SFabiano Rosas
8248a645544SFabiano Rosas qobject_unref(rsp_return);
8258a645544SFabiano Rosas return dirtyrate;
8268a645544SFabiano Rosas }
8278a645544SFabiano Rosas
dirtylimit_start_vm(void)8288a645544SFabiano Rosas static QTestState *dirtylimit_start_vm(void)
8298a645544SFabiano Rosas {
8308a645544SFabiano Rosas QTestState *vm = NULL;
8318a645544SFabiano Rosas g_autofree gchar *cmd = NULL;
8328a645544SFabiano Rosas const char *bootpath;
8338a645544SFabiano Rosas
8348a645544SFabiano Rosas bootpath = bootfile_create(qtest_get_arch(), tmpfs, false);
8358a645544SFabiano Rosas cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
8368a645544SFabiano Rosas "-name dirtylimit-test,debug-threads=on "
8378a645544SFabiano Rosas "-m 150M -smp 1 "
8388a645544SFabiano Rosas "-serial file:%s/vm_serial "
8398a645544SFabiano Rosas "-drive file=%s,format=raw ",
8408a645544SFabiano Rosas tmpfs, bootpath);
8418a645544SFabiano Rosas
8428a645544SFabiano Rosas vm = qtest_init(cmd);
8438a645544SFabiano Rosas return vm;
8448a645544SFabiano Rosas }
8458a645544SFabiano Rosas
dirtylimit_stop_vm(QTestState * vm)8468a645544SFabiano Rosas static void dirtylimit_stop_vm(QTestState *vm)
8478a645544SFabiano Rosas {
8488a645544SFabiano Rosas g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, "vm_serial");
8498a645544SFabiano Rosas
8508a645544SFabiano Rosas qtest_quit(vm);
8518a645544SFabiano Rosas unlink(path);
8528a645544SFabiano Rosas }
8538a645544SFabiano Rosas
test_vcpu_dirty_limit(void)8548a645544SFabiano Rosas static void test_vcpu_dirty_limit(void)
8558a645544SFabiano Rosas {
8568a645544SFabiano Rosas QTestState *vm;
8578a645544SFabiano Rosas int64_t origin_rate;
8588a645544SFabiano Rosas int64_t quota_rate;
8598a645544SFabiano Rosas int64_t rate ;
8608a645544SFabiano Rosas int max_try_count = 20;
8618a645544SFabiano Rosas int hit = 0;
8628a645544SFabiano Rosas
8638a645544SFabiano Rosas /* Start vm for vcpu dirtylimit test */
8648a645544SFabiano Rosas vm = dirtylimit_start_vm();
8658a645544SFabiano Rosas
8668a645544SFabiano Rosas /* Wait for the first serial output from the vm*/
8678a645544SFabiano Rosas wait_for_serial("vm_serial");
8688a645544SFabiano Rosas
8698a645544SFabiano Rosas /* Do dirtyrate measurement with calc time equals 1s */
8708a645544SFabiano Rosas calc_dirty_rate(vm, 1);
8718a645544SFabiano Rosas
8728a645544SFabiano Rosas /* Sleep calc time and wait for calc dirtyrate complete */
8738a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1);
8748a645544SFabiano Rosas
8758a645544SFabiano Rosas /* Query original dirty page rate */
8768a645544SFabiano Rosas origin_rate = get_dirty_rate(vm);
8778a645544SFabiano Rosas
8788a645544SFabiano Rosas /* VM booted from bootsect should dirty memory steadily */
8798a645544SFabiano Rosas assert(origin_rate != 0);
8808a645544SFabiano Rosas
8818a645544SFabiano Rosas /* Setup quota dirty page rate at half of origin */
8828a645544SFabiano Rosas quota_rate = origin_rate / 2;
8838a645544SFabiano Rosas
8848a645544SFabiano Rosas /* Set dirtylimit */
8858a645544SFabiano Rosas dirtylimit_set_all(vm, quota_rate);
8868a645544SFabiano Rosas
8878a645544SFabiano Rosas /*
8888a645544SFabiano Rosas * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit
8898a645544SFabiano Rosas * works literally
8908a645544SFabiano Rosas */
8918a645544SFabiano Rosas g_assert_cmpint(quota_rate, ==, get_limit_rate(vm));
8928a645544SFabiano Rosas
8938a645544SFabiano Rosas /* Sleep a bit to check if it take effect */
8948a645544SFabiano Rosas usleep(2000000);
8958a645544SFabiano Rosas
8968a645544SFabiano Rosas /*
8978a645544SFabiano Rosas * Check if dirtylimit take effect realistically, set the
8988a645544SFabiano Rosas * timeout with 20 s(max_try_count * 1s), if dirtylimit
8998a645544SFabiano Rosas * doesn't take effect, fail test.
9008a645544SFabiano Rosas */
9018a645544SFabiano Rosas while (--max_try_count) {
9028a645544SFabiano Rosas calc_dirty_rate(vm, 1);
9038a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1);
9048a645544SFabiano Rosas rate = get_dirty_rate(vm);
9058a645544SFabiano Rosas
9068a645544SFabiano Rosas /*
9078a645544SFabiano Rosas * Assume hitting if current rate is less
9088a645544SFabiano Rosas * than quota rate (within accepting error)
9098a645544SFabiano Rosas */
9108a645544SFabiano Rosas if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
9118a645544SFabiano Rosas hit = 1;
9128a645544SFabiano Rosas break;
9138a645544SFabiano Rosas }
9148a645544SFabiano Rosas }
9158a645544SFabiano Rosas
9168a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1);
9178a645544SFabiano Rosas
9188a645544SFabiano Rosas hit = 0;
9198a645544SFabiano Rosas max_try_count = 20;
9208a645544SFabiano Rosas
9218a645544SFabiano Rosas /* Check if dirtylimit cancellation take effect */
9228a645544SFabiano Rosas cancel_vcpu_dirty_limit(vm);
9238a645544SFabiano Rosas while (--max_try_count) {
9248a645544SFabiano Rosas calc_dirty_rate(vm, 1);
9258a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1);
9268a645544SFabiano Rosas rate = get_dirty_rate(vm);
9278a645544SFabiano Rosas
9288a645544SFabiano Rosas /*
9298a645544SFabiano Rosas * Assume dirtylimit be canceled if current rate is
9308a645544SFabiano Rosas * greater than quota rate (within accepting error)
9318a645544SFabiano Rosas */
9328a645544SFabiano Rosas if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
9338a645544SFabiano Rosas hit = 1;
9348a645544SFabiano Rosas break;
9358a645544SFabiano Rosas }
9368a645544SFabiano Rosas }
9378a645544SFabiano Rosas
9388a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1);
9398a645544SFabiano Rosas dirtylimit_stop_vm(vm);
9408a645544SFabiano Rosas }
9418a645544SFabiano Rosas
migrate_dirty_limit_wait_showup(QTestState * from,const int64_t period,const int64_t value)9428a645544SFabiano Rosas static void migrate_dirty_limit_wait_showup(QTestState *from,
9438a645544SFabiano Rosas const int64_t period,
9448a645544SFabiano Rosas const int64_t value)
9458a645544SFabiano Rosas {
9468a645544SFabiano Rosas /* Enable dirty limit capability */
9478a645544SFabiano Rosas migrate_set_capability(from, "dirty-limit", true);
9488a645544SFabiano Rosas
9498a645544SFabiano Rosas /* Set dirty limit parameters */
9508a645544SFabiano Rosas migrate_set_parameter_int(from, "x-vcpu-dirty-limit-period", period);
9518a645544SFabiano Rosas migrate_set_parameter_int(from, "vcpu-dirty-limit", value);
9528a645544SFabiano Rosas
9538a645544SFabiano Rosas /* Make sure migrate can't converge */
9548a645544SFabiano Rosas migrate_ensure_non_converge(from);
9558a645544SFabiano Rosas
9568a645544SFabiano Rosas /* To check limit rate after precopy */
9578a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true);
9588a645544SFabiano Rosas
9598a645544SFabiano Rosas /* Wait for the serial output from the source */
9608a645544SFabiano Rosas wait_for_serial("src_serial");
9618a645544SFabiano Rosas }
9628a645544SFabiano Rosas
9638a645544SFabiano Rosas /*
9648a645544SFabiano Rosas * This test does:
9658a645544SFabiano Rosas * source destination
9668a645544SFabiano Rosas * start vm
9678a645544SFabiano Rosas * start incoming vm
9688a645544SFabiano Rosas * migrate
9698a645544SFabiano Rosas * wait dirty limit to begin
9708a645544SFabiano Rosas * cancel migrate
9718a645544SFabiano Rosas * cancellation check
9728a645544SFabiano Rosas * restart incoming vm
9738a645544SFabiano Rosas * migrate
9748a645544SFabiano Rosas * wait dirty limit to begin
9758a645544SFabiano Rosas * wait pre-switchover event
9768a645544SFabiano Rosas * convergence condition check
9778a645544SFabiano Rosas *
9788a645544SFabiano Rosas * And see if dirty limit migration works correctly.
9798a645544SFabiano Rosas * This test case involves many passes, so it runs in slow mode only.
9808a645544SFabiano Rosas */
test_dirty_limit(void)9818a645544SFabiano Rosas static void test_dirty_limit(void)
9828a645544SFabiano Rosas {
9838a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
9848a645544SFabiano Rosas QTestState *from, *to;
9858a645544SFabiano Rosas int64_t remaining;
9868a645544SFabiano Rosas uint64_t throttle_us_per_full;
9878a645544SFabiano Rosas /*
9888a645544SFabiano Rosas * We want the test to be stable and as fast as possible.
9898a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without dirty limit,
9908a645544SFabiano Rosas * so we need to decrease a bandwidth.
9918a645544SFabiano Rosas */
9928a645544SFabiano Rosas const int64_t dirtylimit_period = 1000, dirtylimit_value = 50;
9938a645544SFabiano Rosas const int64_t max_bandwidth = 400000000; /* ~400Mb/s */
9948a645544SFabiano Rosas const int64_t downtime_limit = 250; /* 250ms */
9958a645544SFabiano Rosas /*
9968a645544SFabiano Rosas * We migrate through unix-socket (> 500Mb/s).
9978a645544SFabiano Rosas * Thus, expected migration speed ~= bandwidth limit (< 500Mb/s).
9988a645544SFabiano Rosas * So, we can predict expected_threshold
9998a645544SFabiano Rosas */
10008a645544SFabiano Rosas const int64_t expected_threshold = max_bandwidth * downtime_limit / 1000;
10018a645544SFabiano Rosas int max_try_count = 10;
10028a645544SFabiano Rosas MigrateCommon args = {
10038a645544SFabiano Rosas .start = {
10048a645544SFabiano Rosas .hide_stderr = true,
10058a645544SFabiano Rosas .use_dirty_ring = true,
10068a645544SFabiano Rosas },
10078a645544SFabiano Rosas .listen_uri = uri,
10088a645544SFabiano Rosas .connect_uri = uri,
10098a645544SFabiano Rosas };
10108a645544SFabiano Rosas
10118a645544SFabiano Rosas /* Start src, dst vm */
10128a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) {
10138a645544SFabiano Rosas return;
10148a645544SFabiano Rosas }
10158a645544SFabiano Rosas
10168a645544SFabiano Rosas /* Prepare for dirty limit migration and wait src vm show up */
10178a645544SFabiano Rosas migrate_dirty_limit_wait_showup(from, dirtylimit_period, dirtylimit_value);
10188a645544SFabiano Rosas
10198a645544SFabiano Rosas /* Start migrate */
10208a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}");
10218a645544SFabiano Rosas
10228a645544SFabiano Rosas /* Wait for dirty limit throttle begin */
10238a645544SFabiano Rosas throttle_us_per_full = 0;
10248a645544SFabiano Rosas while (throttle_us_per_full == 0) {
10258a645544SFabiano Rosas throttle_us_per_full =
10268a645544SFabiano Rosas read_migrate_property_int(from,
10278a645544SFabiano Rosas "dirty-limit-throttle-time-per-round");
10288a645544SFabiano Rosas usleep(100);
10298a645544SFabiano Rosas g_assert_false(get_src()->stop_seen);
10308a645544SFabiano Rosas }
10318a645544SFabiano Rosas
10328a645544SFabiano Rosas /* Now cancel migrate and wait for dirty limit throttle switch off */
10338a645544SFabiano Rosas migrate_cancel(from);
10348a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL);
10358a645544SFabiano Rosas
1036cd196679SFabiano Rosas /* destination always fails after cancel */
1037cd196679SFabiano Rosas migration_event_wait(to, "failed");
1038cd196679SFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE);
1039cd196679SFabiano Rosas qtest_quit(to);
1040cd196679SFabiano Rosas
10418a645544SFabiano Rosas /* Check if dirty limit throttle switched off, set timeout 1ms */
10428a645544SFabiano Rosas do {
10438a645544SFabiano Rosas throttle_us_per_full =
10448a645544SFabiano Rosas read_migrate_property_int(from,
10458a645544SFabiano Rosas "dirty-limit-throttle-time-per-round");
10468a645544SFabiano Rosas usleep(100);
10478a645544SFabiano Rosas g_assert_false(get_src()->stop_seen);
10488a645544SFabiano Rosas } while (throttle_us_per_full != 0 && --max_try_count);
10498a645544SFabiano Rosas
10508a645544SFabiano Rosas /* Assert dirty limit is not in service */
10518a645544SFabiano Rosas g_assert_cmpint(throttle_us_per_full, ==, 0);
10528a645544SFabiano Rosas
10538a645544SFabiano Rosas args = (MigrateCommon) {
10548a645544SFabiano Rosas .start = {
10558a645544SFabiano Rosas .only_target = true,
10568a645544SFabiano Rosas .use_dirty_ring = true,
10578a645544SFabiano Rosas },
10588a645544SFabiano Rosas .listen_uri = uri,
10598a645544SFabiano Rosas .connect_uri = uri,
10608a645544SFabiano Rosas };
10618a645544SFabiano Rosas
10628a645544SFabiano Rosas /* Restart dst vm, src vm already show up so we needn't wait anymore */
10638a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) {
10648a645544SFabiano Rosas return;
10658a645544SFabiano Rosas }
10668a645544SFabiano Rosas
10678a645544SFabiano Rosas /* Start migrate */
10688a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}");
10698a645544SFabiano Rosas
10708a645544SFabiano Rosas /* Wait for dirty limit throttle begin */
10718a645544SFabiano Rosas throttle_us_per_full = 0;
10728a645544SFabiano Rosas while (throttle_us_per_full == 0) {
10738a645544SFabiano Rosas throttle_us_per_full =
10748a645544SFabiano Rosas read_migrate_property_int(from,
10758a645544SFabiano Rosas "dirty-limit-throttle-time-per-round");
10768a645544SFabiano Rosas usleep(100);
10778a645544SFabiano Rosas g_assert_false(get_src()->stop_seen);
10788a645544SFabiano Rosas }
10798a645544SFabiano Rosas
10808a645544SFabiano Rosas /*
10818a645544SFabiano Rosas * The dirty limit rate should equals the return value of
10828a645544SFabiano Rosas * query-vcpu-dirty-limit if dirty limit cap set
10838a645544SFabiano Rosas */
10848a645544SFabiano Rosas g_assert_cmpint(dirtylimit_value, ==, get_limit_rate(from));
10858a645544SFabiano Rosas
10868a645544SFabiano Rosas /* Now, we have tested if dirty limit works, let it converge */
10878a645544SFabiano Rosas migrate_set_parameter_int(from, "downtime-limit", downtime_limit);
10888a645544SFabiano Rosas migrate_set_parameter_int(from, "max-bandwidth", max_bandwidth);
10898a645544SFabiano Rosas
10908a645544SFabiano Rosas /*
10918a645544SFabiano Rosas * Wait for pre-switchover status to check if migration
10928a645544SFabiano Rosas * satisfy the convergence condition
10938a645544SFabiano Rosas */
10948a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL);
10958a645544SFabiano Rosas
10968a645544SFabiano Rosas remaining = read_ram_property_int(from, "remaining");
10978a645544SFabiano Rosas g_assert_cmpint(remaining, <,
10988a645544SFabiano Rosas (expected_threshold + expected_threshold / 100));
10998a645544SFabiano Rosas
11008a645544SFabiano Rosas migrate_continue(from, "pre-switchover");
11018a645544SFabiano Rosas
11028a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME");
11038a645544SFabiano Rosas
11048a645544SFabiano Rosas wait_for_serial("dest_serial");
11058a645544SFabiano Rosas wait_for_migration_complete(from);
11068a645544SFabiano Rosas
11078a645544SFabiano Rosas migrate_end(from, to, true);
11088a645544SFabiano Rosas }
11098a645544SFabiano Rosas
migration_test_add_precopy_smoke(MigrationTestEnv * env)111043ab3fb3SFabiano Rosas static void migration_test_add_precopy_smoke(MigrationTestEnv *env)
11118a645544SFabiano Rosas {
11128a645544SFabiano Rosas if (env->is_x86) {
11138a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/live",
11148a645544SFabiano Rosas test_precopy_unix_suspend_live);
11158a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/notlive",
11168a645544SFabiano Rosas test_precopy_unix_suspend_notlive);
11178a645544SFabiano Rosas }
11188a645544SFabiano Rosas
11198a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/plain",
11208a645544SFabiano Rosas test_precopy_unix_plain);
11218a645544SFabiano Rosas
11228a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain", test_precopy_tcp_plain);
112343ab3fb3SFabiano Rosas migration_test_add("/migration/multifd/tcp/uri/plain/none",
112443ab3fb3SFabiano Rosas test_multifd_tcp_uri_none);
112543ab3fb3SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/cancel",
112643ab3fb3SFabiano Rosas test_multifd_tcp_cancel);
112743ab3fb3SFabiano Rosas }
112843ab3fb3SFabiano Rosas
migration_test_add_precopy(MigrationTestEnv * env)112943ab3fb3SFabiano Rosas void migration_test_add_precopy(MigrationTestEnv *env)
113043ab3fb3SFabiano Rosas {
113143ab3fb3SFabiano Rosas tmpfs = env->tmpfs;
113243ab3fb3SFabiano Rosas
113343ab3fb3SFabiano Rosas migration_test_add_precopy_smoke(env);
113443ab3fb3SFabiano Rosas
113543ab3fb3SFabiano Rosas if (!env->full_set) {
113643ab3fb3SFabiano Rosas return;
113743ab3fb3SFabiano Rosas }
11388a645544SFabiano Rosas
11398a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain/switchover-ack",
11408a645544SFabiano Rosas test_precopy_tcp_switchover_ack);
11418a645544SFabiano Rosas
11428a645544SFabiano Rosas #ifndef _WIN32
11438a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/tcp",
11448a645544SFabiano Rosas test_precopy_fd_socket);
11458a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/file",
11468a645544SFabiano Rosas test_precopy_fd_file);
11478a645544SFabiano Rosas #endif
11488a645544SFabiano Rosas
11498a645544SFabiano Rosas /*
11508a645544SFabiano Rosas * See explanation why this test is slow on function definition
11518a645544SFabiano Rosas */
11528a645544SFabiano Rosas if (g_test_slow()) {
11538a645544SFabiano Rosas migration_test_add("/migration/auto_converge",
11548a645544SFabiano Rosas test_auto_converge);
11558a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64") &&
11568a645544SFabiano Rosas env->has_kvm && env->has_dirty_ring) {
11578a645544SFabiano Rosas migration_test_add("/dirty_limit",
11588a645544SFabiano Rosas test_dirty_limit);
11598a645544SFabiano Rosas }
11608a645544SFabiano Rosas }
11618a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/channels/plain/none",
11628a645544SFabiano Rosas test_multifd_tcp_channels_none);
11638a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/legacy",
11648a645544SFabiano Rosas test_multifd_tcp_zero_page_legacy);
11658a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/none",
11668a645544SFabiano Rosas test_multifd_tcp_no_zero_page);
11678a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64")
11688a645544SFabiano Rosas && env->has_kvm && env->has_dirty_ring) {
11698a645544SFabiano Rosas
11708a645544SFabiano Rosas migration_test_add("/migration/dirty_ring",
11718a645544SFabiano Rosas test_precopy_unix_dirty_ring);
11728a645544SFabiano Rosas if (qtest_has_machine("pc") && g_test_slow()) {
11738a645544SFabiano Rosas migration_test_add("/migration/vcpu_dirty_limit",
11748a645544SFabiano Rosas test_vcpu_dirty_limit);
11758a645544SFabiano Rosas }
11768a645544SFabiano Rosas }
1177*538e03d2SFabiano Rosas
1178*538e03d2SFabiano Rosas /* ensure new status don't go unnoticed */
1179*538e03d2SFabiano Rosas assert(MIGRATION_STATUS__MAX == 15);
1180*538e03d2SFabiano Rosas
1181*538e03d2SFabiano Rosas for (int i = MIGRATION_STATUS_NONE; i < MIGRATION_STATUS__MAX; i++) {
1182*538e03d2SFabiano Rosas switch (i) {
1183*538e03d2SFabiano Rosas case MIGRATION_STATUS_DEVICE: /* happens too fast */
1184*538e03d2SFabiano Rosas case MIGRATION_STATUS_WAIT_UNPLUG: /* no support in tests */
1185*538e03d2SFabiano Rosas case MIGRATION_STATUS_COLO: /* no support in tests */
1186*538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_ACTIVE: /* postcopy can't be cancelled */
1187*538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_PAUSED:
1188*538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_RECOVER_SETUP:
1189*538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_RECOVER:
1190*538e03d2SFabiano Rosas continue;
1191*538e03d2SFabiano Rosas default:
1192*538e03d2SFabiano Rosas migration_test_add_suffix("/migration/cancel/src/after/",
1193*538e03d2SFabiano Rosas MigrationStatus_str(i),
1194*538e03d2SFabiano Rosas test_cancel_src_after_status);
1195*538e03d2SFabiano Rosas }
1196*538e03d2SFabiano Rosas }
11978a645544SFabiano Rosas }
1198