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" 23538e03d2SFabiano 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 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 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 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 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 1027d9849c3SLi Zhijian #ifdef CONFIG_RDMA 1037d9849c3SLi Zhijian 1047d9849c3SLi Zhijian #define RDMA_MIGRATION_HELPER "scripts/rdma-migration-helper.sh" 1057d9849c3SLi Zhijian static int new_rdma_link(char *buffer) 1067d9849c3SLi Zhijian { 1077d9849c3SLi Zhijian char cmd[256]; 1087d9849c3SLi Zhijian bool verbose = g_getenv("QTEST_LOG"); 1097d9849c3SLi Zhijian 1107d9849c3SLi Zhijian snprintf(cmd, sizeof(cmd), "%s detect %s", RDMA_MIGRATION_HELPER, 1117d9849c3SLi Zhijian verbose ? "" : "2>/dev/null"); 1127d9849c3SLi Zhijian 1137d9849c3SLi Zhijian FILE *pipe = popen(cmd, "r"); 1147d9849c3SLi Zhijian if (pipe == NULL) { 1157d9849c3SLi Zhijian perror("Failed to run script"); 1167d9849c3SLi Zhijian return -1; 1177d9849c3SLi Zhijian } 1187d9849c3SLi Zhijian 1197d9849c3SLi Zhijian int idx = 0; 1207d9849c3SLi Zhijian while (fgets(buffer + idx, 128 - idx, pipe) != NULL) { 1217d9849c3SLi Zhijian idx += strlen(buffer); 1227d9849c3SLi Zhijian } 1237d9849c3SLi Zhijian 1247d9849c3SLi Zhijian int status = pclose(pipe); 1257d9849c3SLi Zhijian if (status == -1) { 1267d9849c3SLi Zhijian perror("Error reported by pclose()"); 1277d9849c3SLi Zhijian return -1; 1287d9849c3SLi Zhijian } else if (WIFEXITED(status)) { 1297d9849c3SLi Zhijian return WEXITSTATUS(status); 1307d9849c3SLi Zhijian } 1317d9849c3SLi Zhijian 1327d9849c3SLi Zhijian return -1; 1337d9849c3SLi Zhijian } 1347d9849c3SLi Zhijian 1357d9849c3SLi Zhijian static void test_precopy_rdma_plain(void) 1367d9849c3SLi Zhijian { 1377d9849c3SLi Zhijian char buffer[128] = {}; 1387d9849c3SLi Zhijian 1397d9849c3SLi Zhijian if (new_rdma_link(buffer)) { 1407d9849c3SLi Zhijian g_test_skip("No rdma link available\n" 1417d9849c3SLi Zhijian "# To enable the test:\n" 1427d9849c3SLi Zhijian "# Run \'" RDMA_MIGRATION_HELPER " setup\' with root to " 1437d9849c3SLi Zhijian "setup a new rdma/rxe link and rerun the test\n" 1447d9849c3SLi Zhijian "# Optional: run 'scripts/rdma-migration-helper.sh clean' " 1457d9849c3SLi Zhijian "to revert the 'setup'"); 1467d9849c3SLi Zhijian return; 1477d9849c3SLi Zhijian } 1487d9849c3SLi Zhijian 1497d9849c3SLi Zhijian /* 1507d9849c3SLi Zhijian * TODO: query a free port instead of hard code. 1517d9849c3SLi Zhijian * 29200=('R'+'D'+'M'+'A')*100 1527d9849c3SLi Zhijian **/ 1537d9849c3SLi Zhijian g_autofree char *uri = g_strdup_printf("rdma:%s:29200", buffer); 1547d9849c3SLi Zhijian 1557d9849c3SLi Zhijian MigrateCommon args = { 1567d9849c3SLi Zhijian .listen_uri = uri, 1577d9849c3SLi Zhijian .connect_uri = uri, 1587d9849c3SLi Zhijian }; 1597d9849c3SLi Zhijian 1607d9849c3SLi Zhijian test_precopy_common(&args); 1617d9849c3SLi Zhijian } 1627d9849c3SLi Zhijian #endif 1637d9849c3SLi Zhijian 1648a645544SFabiano Rosas static void test_precopy_tcp_plain(void) 1658a645544SFabiano Rosas { 1668a645544SFabiano Rosas MigrateCommon args = { 1678a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0", 1688a645544SFabiano Rosas }; 1698a645544SFabiano Rosas 1708a645544SFabiano Rosas test_precopy_common(&args); 1718a645544SFabiano Rosas } 1728a645544SFabiano Rosas 1738a645544SFabiano Rosas static void test_precopy_tcp_switchover_ack(void) 1748a645544SFabiano Rosas { 1758a645544SFabiano Rosas MigrateCommon args = { 1768a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0", 177*115cec9dSPrasad Pandit .start = { 178*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_RETURN_PATH] = true, 179*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_SWITCHOVER_ACK] = true, 180*115cec9dSPrasad Pandit }, 1818a645544SFabiano Rosas /* 1828a645544SFabiano Rosas * Source VM must be running in order to consider the switchover ACK 1838a645544SFabiano Rosas * when deciding to do switchover or not. 1848a645544SFabiano Rosas */ 1858a645544SFabiano Rosas .live = true, 1868a645544SFabiano Rosas }; 1878a645544SFabiano Rosas 1888a645544SFabiano Rosas test_precopy_common(&args); 1898a645544SFabiano Rosas } 1908a645544SFabiano Rosas 1918a645544SFabiano Rosas #ifndef _WIN32 1928a645544SFabiano Rosas static void *migrate_hook_start_fd(QTestState *from, 1938a645544SFabiano Rosas QTestState *to) 1948a645544SFabiano Rosas { 1958a645544SFabiano Rosas int ret; 1968a645544SFabiano Rosas int pair[2]; 1978a645544SFabiano Rosas 1988a645544SFabiano Rosas /* Create two connected sockets for migration */ 1998a645544SFabiano Rosas ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair); 2008a645544SFabiano Rosas g_assert_cmpint(ret, ==, 0); 2018a645544SFabiano Rosas 2028a645544SFabiano Rosas /* Send the 1st socket to the target */ 2038a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &pair[0], 1, 2048a645544SFabiano Rosas "{ 'execute': 'getfd'," 2058a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2068a645544SFabiano Rosas close(pair[0]); 2078a645544SFabiano Rosas 2088a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 20943ca9d18SSteve Sistare migrate_incoming_qmp(to, "fd:fd-mig", NULL, "{}"); 2108a645544SFabiano Rosas 2118a645544SFabiano Rosas /* Send the 2nd socket to the target */ 2128a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &pair[1], 1, 2138a645544SFabiano Rosas "{ 'execute': 'getfd'," 2148a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2158a645544SFabiano Rosas close(pair[1]); 2168a645544SFabiano Rosas 2178a645544SFabiano Rosas return NULL; 2188a645544SFabiano Rosas } 2198a645544SFabiano Rosas 2208a645544SFabiano Rosas static void migrate_hook_end_fd(QTestState *from, 2218a645544SFabiano Rosas QTestState *to, 2228a645544SFabiano Rosas void *opaque) 2238a645544SFabiano Rosas { 2248a645544SFabiano Rosas QDict *rsp; 2258a645544SFabiano Rosas const char *error_desc; 2268a645544SFabiano Rosas 2278a645544SFabiano Rosas /* Test closing fds */ 2288a645544SFabiano Rosas /* 2298a645544SFabiano Rosas * We assume, that QEMU removes named fd from its list, 2308a645544SFabiano Rosas * so this should fail. 2318a645544SFabiano Rosas */ 2328a645544SFabiano Rosas rsp = qtest_qmp(from, 2338a645544SFabiano Rosas "{ 'execute': 'closefd'," 2348a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2358a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error")); 2368a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); 2378a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); 2388a645544SFabiano Rosas qobject_unref(rsp); 2398a645544SFabiano Rosas 2408a645544SFabiano Rosas rsp = qtest_qmp(to, 2418a645544SFabiano Rosas "{ 'execute': 'closefd'," 2428a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2438a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error")); 2448a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); 2458a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); 2468a645544SFabiano Rosas qobject_unref(rsp); 2478a645544SFabiano Rosas } 2488a645544SFabiano Rosas 2498a645544SFabiano Rosas static void test_precopy_fd_socket(void) 2508a645544SFabiano Rosas { 2518a645544SFabiano Rosas MigrateCommon args = { 2528a645544SFabiano Rosas .listen_uri = "defer", 2538a645544SFabiano Rosas .connect_uri = "fd:fd-mig", 2548a645544SFabiano Rosas .start_hook = migrate_hook_start_fd, 2558a645544SFabiano Rosas .end_hook = migrate_hook_end_fd, 2568a645544SFabiano Rosas }; 2578a645544SFabiano Rosas test_precopy_common(&args); 2588a645544SFabiano Rosas } 2598a645544SFabiano Rosas 2608a645544SFabiano Rosas static void *migrate_hook_start_precopy_fd_file(QTestState *from, 2618a645544SFabiano Rosas QTestState *to) 2628a645544SFabiano Rosas { 2638a645544SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME); 2648a645544SFabiano Rosas int src_flags = O_CREAT | O_RDWR; 2658a645544SFabiano Rosas int dst_flags = O_CREAT | O_RDWR; 2668a645544SFabiano Rosas int fds[2]; 2678a645544SFabiano Rosas 2688a645544SFabiano Rosas fds[0] = open(file, src_flags, 0660); 2698a645544SFabiano Rosas assert(fds[0] != -1); 2708a645544SFabiano Rosas 2718a645544SFabiano Rosas fds[1] = open(file, dst_flags, 0660); 2728a645544SFabiano Rosas assert(fds[1] != -1); 2738a645544SFabiano Rosas 2748a645544SFabiano Rosas 2758a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &fds[0], 1, 2768a645544SFabiano Rosas "{ 'execute': 'getfd'," 2778a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2788a645544SFabiano Rosas 2798a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &fds[1], 1, 2808a645544SFabiano Rosas "{ 'execute': 'getfd'," 2818a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 2828a645544SFabiano Rosas 2838a645544SFabiano Rosas close(fds[0]); 2848a645544SFabiano Rosas close(fds[1]); 2858a645544SFabiano Rosas 2868a645544SFabiano Rosas return NULL; 2878a645544SFabiano Rosas } 2888a645544SFabiano Rosas 2898a645544SFabiano Rosas static void test_precopy_fd_file(void) 2908a645544SFabiano Rosas { 2918a645544SFabiano Rosas MigrateCommon args = { 2928a645544SFabiano Rosas .listen_uri = "defer", 2938a645544SFabiano Rosas .connect_uri = "fd:fd-mig", 2948a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_fd_file, 2958a645544SFabiano Rosas .end_hook = migrate_hook_end_fd, 2968a645544SFabiano Rosas }; 2978a645544SFabiano Rosas test_file_common(&args, true); 2988a645544SFabiano Rosas } 2998a645544SFabiano Rosas #endif /* _WIN32 */ 3008a645544SFabiano Rosas 3018a645544SFabiano Rosas /* 3028a645544SFabiano Rosas * The way auto_converge works, we need to do too many passes to 3038a645544SFabiano Rosas * run this test. Auto_converge logic is only run once every 3048a645544SFabiano Rosas * three iterations, so: 3058a645544SFabiano Rosas * 3068a645544SFabiano Rosas * - 3 iterations without auto_converge enabled 3078a645544SFabiano Rosas * - 3 iterations with pct = 5 3088a645544SFabiano Rosas * - 3 iterations with pct = 30 3098a645544SFabiano Rosas * - 3 iterations with pct = 55 3108a645544SFabiano Rosas * - 3 iterations with pct = 80 3118a645544SFabiano Rosas * - 3 iterations with pct = 95 (max(95, 80 + 25)) 3128a645544SFabiano Rosas * 3138a645544SFabiano Rosas * To make things even worse, we need to run the initial stage at 3148a645544SFabiano Rosas * 3MB/s so we enter autoconverge even when host is (over)loaded. 3158a645544SFabiano Rosas */ 3168a645544SFabiano Rosas static void test_auto_converge(void) 3178a645544SFabiano Rosas { 3188a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 3198a645544SFabiano Rosas MigrateStart args = {}; 3208a645544SFabiano Rosas QTestState *from, *to; 3218a645544SFabiano Rosas int64_t percentage; 3228a645544SFabiano Rosas 3238a645544SFabiano Rosas /* 3248a645544SFabiano Rosas * We want the test to be stable and as fast as possible. 3258a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without throttling, 3268a645544SFabiano Rosas * so we need to decrease a bandwidth. 3278a645544SFabiano Rosas */ 3288a645544SFabiano Rosas const int64_t init_pct = 5, inc_pct = 25, max_pct = 95; 3298a645544SFabiano Rosas uint64_t prev_dirty_sync_cnt, dirty_sync_cnt; 3308a645544SFabiano Rosas int max_try_count, hit = 0; 3318a645544SFabiano Rosas 3328a645544SFabiano Rosas if (migrate_start(&from, &to, uri, &args)) { 3338a645544SFabiano Rosas return; 3348a645544SFabiano Rosas } 3358a645544SFabiano Rosas 3368a645544SFabiano Rosas migrate_set_capability(from, "auto-converge", true); 3378a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct); 3388a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct); 3398a645544SFabiano Rosas migrate_set_parameter_int(from, "max-cpu-throttle", max_pct); 3408a645544SFabiano Rosas 3418a645544SFabiano Rosas /* 3428a645544SFabiano Rosas * Set the initial parameters so that the migration could not converge 3438a645544SFabiano Rosas * without throttling. 3448a645544SFabiano Rosas */ 3458a645544SFabiano Rosas migrate_ensure_non_converge(from); 3468a645544SFabiano Rosas 3478a645544SFabiano Rosas /* To check remaining size after precopy */ 3488a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true); 3498a645544SFabiano Rosas 3508a645544SFabiano Rosas /* Wait for the first serial output from the source */ 3518a645544SFabiano Rosas wait_for_serial("src_serial"); 3528a645544SFabiano Rosas 3538a645544SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 3548a645544SFabiano Rosas 3558a645544SFabiano Rosas /* Wait for throttling begins */ 3568a645544SFabiano Rosas percentage = 0; 3578a645544SFabiano Rosas do { 3588a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage"); 3598a645544SFabiano Rosas if (percentage != 0) { 3608a645544SFabiano Rosas break; 3618a645544SFabiano Rosas } 3628a645544SFabiano Rosas usleep(20); 3638a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 3648a645544SFabiano Rosas } while (true); 3658a645544SFabiano Rosas /* The first percentage of throttling should be at least init_pct */ 3668a645544SFabiano Rosas g_assert_cmpint(percentage, >=, init_pct); 3678a645544SFabiano Rosas 3688a645544SFabiano Rosas /* 3698a645544SFabiano Rosas * End the loop when the dirty sync count greater than 1. 3708a645544SFabiano Rosas */ 3718a645544SFabiano Rosas while ((dirty_sync_cnt = get_migration_pass(from)) < 2) { 3728a645544SFabiano Rosas usleep(1000 * 1000); 3738a645544SFabiano Rosas } 3748a645544SFabiano Rosas 3758a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt; 3768a645544SFabiano Rosas 3778a645544SFabiano Rosas /* 3788a645544SFabiano Rosas * The RAMBlock dirty sync count must changes in 5 seconds, here we set 3798a645544SFabiano Rosas * the timeout to 10 seconds to ensure it changes. 3808a645544SFabiano Rosas * 3818a645544SFabiano Rosas * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s, 3828a645544SFabiano Rosas * while the qtest mem is >= 100MB, one iteration takes at least 33s (100/3) 3838a645544SFabiano Rosas * to complete; this ensures that the RAMBlock dirty sync occurs. 3848a645544SFabiano Rosas */ 3858a645544SFabiano Rosas max_try_count = 10; 3868a645544SFabiano Rosas while (--max_try_count) { 3878a645544SFabiano Rosas dirty_sync_cnt = get_migration_pass(from); 3888a645544SFabiano Rosas if (dirty_sync_cnt != prev_dirty_sync_cnt) { 3898a645544SFabiano Rosas hit = 1; 3908a645544SFabiano Rosas break; 3918a645544SFabiano Rosas } 3928a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt; 3938a645544SFabiano Rosas sleep(1); 3948a645544SFabiano Rosas } 3958a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 3968a645544SFabiano Rosas 3978a645544SFabiano Rosas /* Now, when we tested that throttling works, let it converge */ 3988a645544SFabiano Rosas migrate_ensure_converge(from); 3998a645544SFabiano Rosas 4008a645544SFabiano Rosas /* 4018a645544SFabiano Rosas * Wait for pre-switchover status to check last throttle percentage 4028a645544SFabiano Rosas * and remaining. These values will be zeroed later 4038a645544SFabiano Rosas */ 4048a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL); 4058a645544SFabiano Rosas 4068a645544SFabiano Rosas /* The final percentage of throttling shouldn't be greater than max_pct */ 4078a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage"); 4088a645544SFabiano Rosas g_assert_cmpint(percentage, <=, max_pct); 4098a645544SFabiano Rosas migrate_continue(from, "pre-switchover"); 4108a645544SFabiano Rosas 4118a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME"); 4128a645544SFabiano Rosas 4138a645544SFabiano Rosas wait_for_serial("dest_serial"); 4148a645544SFabiano Rosas wait_for_migration_complete(from); 4158a645544SFabiano Rosas 4168a645544SFabiano Rosas migrate_end(from, to, true); 4178a645544SFabiano Rosas } 4188a645544SFabiano Rosas 4198a645544SFabiano Rosas static void * 4208a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd(QTestState *from, 4218a645544SFabiano Rosas QTestState *to) 4228a645544SFabiano Rosas { 4238a645544SFabiano Rosas return migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 4248a645544SFabiano Rosas } 4258a645544SFabiano Rosas 4268a645544SFabiano Rosas static void * 4278a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_zero_page_legacy(QTestState *from, 4288a645544SFabiano Rosas QTestState *to) 4298a645544SFabiano Rosas { 4308a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 4318a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "legacy"); 4328a645544SFabiano Rosas return NULL; 4338a645544SFabiano Rosas } 4348a645544SFabiano Rosas 4358a645544SFabiano Rosas static void * 4368a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_no_zero_page(QTestState *from, 4378a645544SFabiano Rosas QTestState *to) 4388a645544SFabiano Rosas { 4398a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 4408a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "none"); 4418a645544SFabiano Rosas return NULL; 4428a645544SFabiano Rosas } 4438a645544SFabiano Rosas 4448a645544SFabiano Rosas static void test_multifd_tcp_uri_none(void) 4458a645544SFabiano Rosas { 4468a645544SFabiano Rosas MigrateCommon args = { 4478a645544SFabiano Rosas .listen_uri = "defer", 4488a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd, 449*115cec9dSPrasad Pandit .start = { 450*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_MULTIFD] = true, 451*115cec9dSPrasad Pandit }, 4528a645544SFabiano Rosas /* 4538a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 4548a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 4558a645544SFabiano Rosas * everything will work alright even if guest page is changing. 4568a645544SFabiano Rosas */ 4578a645544SFabiano Rosas .live = true, 4588a645544SFabiano Rosas }; 4598a645544SFabiano Rosas test_precopy_common(&args); 4608a645544SFabiano Rosas } 4618a645544SFabiano Rosas 4628a645544SFabiano Rosas static void test_multifd_tcp_zero_page_legacy(void) 4638a645544SFabiano Rosas { 4648a645544SFabiano Rosas MigrateCommon args = { 4658a645544SFabiano Rosas .listen_uri = "defer", 4668a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_zero_page_legacy, 467*115cec9dSPrasad Pandit .start = { 468*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_MULTIFD] = true, 469*115cec9dSPrasad Pandit }, 4708a645544SFabiano Rosas /* 4718a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 4728a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 4738a645544SFabiano Rosas * everything will work alright even if guest page is changing. 4748a645544SFabiano Rosas */ 4758a645544SFabiano Rosas .live = true, 4768a645544SFabiano Rosas }; 4778a645544SFabiano Rosas test_precopy_common(&args); 4788a645544SFabiano Rosas } 4798a645544SFabiano Rosas 4808a645544SFabiano Rosas static void test_multifd_tcp_no_zero_page(void) 4818a645544SFabiano Rosas { 4828a645544SFabiano Rosas MigrateCommon args = { 4838a645544SFabiano Rosas .listen_uri = "defer", 4848a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_no_zero_page, 485*115cec9dSPrasad Pandit .start = { 486*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_MULTIFD] = true, 487*115cec9dSPrasad Pandit }, 4888a645544SFabiano Rosas /* 4898a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 4908a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 4918a645544SFabiano Rosas * everything will work alright even if guest page is changing. 4928a645544SFabiano Rosas */ 4938a645544SFabiano Rosas .live = true, 4948a645544SFabiano Rosas }; 4958a645544SFabiano Rosas test_precopy_common(&args); 4968a645544SFabiano Rosas } 4978a645544SFabiano Rosas 4988a645544SFabiano Rosas static void test_multifd_tcp_channels_none(void) 4998a645544SFabiano Rosas { 5008a645544SFabiano Rosas MigrateCommon args = { 5018a645544SFabiano Rosas .listen_uri = "defer", 5028a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd, 5038a645544SFabiano Rosas .live = true, 504*115cec9dSPrasad Pandit .start = { 505*115cec9dSPrasad Pandit .caps[MIGRATION_CAPABILITY_MULTIFD] = true, 506*115cec9dSPrasad Pandit }, 5078a645544SFabiano Rosas .connect_channels = ("[ { 'channel-type': 'main'," 5088a645544SFabiano Rosas " 'addr': { 'transport': 'socket'," 5098a645544SFabiano Rosas " 'type': 'inet'," 5108a645544SFabiano Rosas " 'host': '127.0.0.1'," 5118a645544SFabiano Rosas " 'port': '0' } } ]"), 5128a645544SFabiano Rosas }; 5138a645544SFabiano Rosas test_precopy_common(&args); 5148a645544SFabiano Rosas } 5158a645544SFabiano Rosas 5168a645544SFabiano Rosas /* 5178a645544SFabiano Rosas * This test does: 5188a645544SFabiano Rosas * source target 5198a645544SFabiano Rosas * migrate_incoming 5208a645544SFabiano Rosas * migrate 5218a645544SFabiano Rosas * migrate_cancel 5228a645544SFabiano Rosas * launch another target 5238a645544SFabiano Rosas * migrate 5248a645544SFabiano Rosas * 5258a645544SFabiano Rosas * And see that it works 5268a645544SFabiano Rosas */ 5278a645544SFabiano Rosas static void test_multifd_tcp_cancel(void) 5288a645544SFabiano Rosas { 5298a645544SFabiano Rosas MigrateStart args = { 5308a645544SFabiano Rosas .hide_stderr = true, 5318a645544SFabiano Rosas }; 5328a645544SFabiano Rosas QTestState *from, *to, *to2; 5338a645544SFabiano Rosas 5348a645544SFabiano Rosas if (migrate_start(&from, &to, "defer", &args)) { 5358a645544SFabiano Rosas return; 5368a645544SFabiano Rosas } 5378a645544SFabiano Rosas 5388a645544SFabiano Rosas migrate_ensure_non_converge(from); 5398a645544SFabiano Rosas migrate_prepare_for_dirty_mem(from); 5408a645544SFabiano Rosas 5418a645544SFabiano Rosas migrate_set_parameter_int(from, "multifd-channels", 16); 5428a645544SFabiano Rosas migrate_set_parameter_int(to, "multifd-channels", 16); 5438a645544SFabiano Rosas 5448a645544SFabiano Rosas migrate_set_capability(from, "multifd", true); 5458a645544SFabiano Rosas migrate_set_capability(to, "multifd", true); 5468a645544SFabiano Rosas 5478a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 54843ca9d18SSteve Sistare migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}"); 5498a645544SFabiano Rosas 5508a645544SFabiano Rosas /* Wait for the first serial output from the source */ 5518a645544SFabiano Rosas wait_for_serial("src_serial"); 5528a645544SFabiano Rosas 5538a645544SFabiano Rosas migrate_qmp(from, to, NULL, NULL, "{}"); 5548a645544SFabiano Rosas 5558a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to); 5568a645544SFabiano Rosas 5578a645544SFabiano Rosas migrate_cancel(from); 5588a645544SFabiano Rosas 5598a645544SFabiano Rosas /* Make sure QEMU process "to" exited */ 5608a645544SFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE); 5618a645544SFabiano Rosas qtest_wait_qemu(to); 5628a645544SFabiano Rosas qtest_quit(to); 5638a645544SFabiano Rosas 5648a645544SFabiano Rosas /* 5658a645544SFabiano Rosas * Ensure the source QEMU finishes its cancellation process before we 5668a645544SFabiano Rosas * proceed with the setup of the next migration. The migrate_start() 5678a645544SFabiano Rosas * function and others might want to interact with the source in a way that 5688a645544SFabiano Rosas * is not possible while the migration is not canceled properly. For 5698a645544SFabiano Rosas * example, setting migration capabilities when the migration is still 5708a645544SFabiano Rosas * running leads to an error. 5718a645544SFabiano Rosas */ 5728a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL); 5738a645544SFabiano Rosas 5748a645544SFabiano Rosas args = (MigrateStart){ 5758a645544SFabiano Rosas .only_target = true, 5768a645544SFabiano Rosas }; 5778a645544SFabiano Rosas 5788a645544SFabiano Rosas if (migrate_start(&from, &to2, "defer", &args)) { 5798a645544SFabiano Rosas return; 5808a645544SFabiano Rosas } 5818a645544SFabiano Rosas 5828a645544SFabiano Rosas migrate_set_parameter_int(to2, "multifd-channels", 16); 5838a645544SFabiano Rosas 5848a645544SFabiano Rosas migrate_set_capability(to2, "multifd", true); 5858a645544SFabiano Rosas 5868a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 58743ca9d18SSteve Sistare migrate_incoming_qmp(to2, "tcp:127.0.0.1:0", NULL, "{}"); 5888a645544SFabiano Rosas 5898a645544SFabiano Rosas migrate_ensure_non_converge(from); 5908a645544SFabiano Rosas 5918a645544SFabiano Rosas migrate_qmp(from, to2, NULL, NULL, "{}"); 5928a645544SFabiano Rosas 5938a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to2); 5948a645544SFabiano Rosas 5958a645544SFabiano Rosas migrate_ensure_converge(from); 5968a645544SFabiano Rosas 5978a645544SFabiano Rosas wait_for_stop(from, get_src()); 5988a645544SFabiano Rosas qtest_qmp_eventwait(to2, "RESUME"); 5998a645544SFabiano Rosas 6008a645544SFabiano Rosas wait_for_serial("dest_serial"); 6018a645544SFabiano Rosas wait_for_migration_complete(from); 6028a645544SFabiano Rosas migrate_end(from, to2, true); 6038a645544SFabiano Rosas } 6048a645544SFabiano Rosas 605538e03d2SFabiano Rosas static void test_cancel_src_after_failed(QTestState *from, QTestState *to, 606538e03d2SFabiano Rosas const char *uri, const char *phase) 607538e03d2SFabiano Rosas { 608538e03d2SFabiano Rosas /* 609538e03d2SFabiano Rosas * No migrate_incoming_qmp() at the start to force source into 610538e03d2SFabiano Rosas * failed state during migrate_qmp(). 611538e03d2SFabiano Rosas */ 612538e03d2SFabiano Rosas 613538e03d2SFabiano Rosas wait_for_serial("src_serial"); 614538e03d2SFabiano Rosas migrate_ensure_converge(from); 615538e03d2SFabiano Rosas 616538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 617538e03d2SFabiano Rosas 618538e03d2SFabiano Rosas migration_event_wait(from, phase); 619538e03d2SFabiano Rosas migrate_cancel(from); 620538e03d2SFabiano Rosas 621538e03d2SFabiano Rosas /* cancelling will not move the migration out of 'failed' */ 622538e03d2SFabiano Rosas 623538e03d2SFabiano Rosas wait_for_migration_status(from, "failed", 624538e03d2SFabiano Rosas (const char * []) { "completed", NULL }); 625538e03d2SFabiano Rosas 626538e03d2SFabiano Rosas /* 627538e03d2SFabiano Rosas * Not waiting for the destination because it never started 628538e03d2SFabiano Rosas * migration. 629538e03d2SFabiano Rosas */ 630538e03d2SFabiano Rosas } 631538e03d2SFabiano Rosas 632538e03d2SFabiano Rosas static void test_cancel_src_after_cancelled(QTestState *from, QTestState *to, 633538e03d2SFabiano Rosas const char *uri, const char *phase) 634538e03d2SFabiano Rosas { 635538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }"); 636538e03d2SFabiano Rosas 637538e03d2SFabiano Rosas wait_for_serial("src_serial"); 638538e03d2SFabiano Rosas migrate_ensure_converge(from); 639538e03d2SFabiano Rosas 640538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 641538e03d2SFabiano Rosas 642538e03d2SFabiano Rosas /* To move to cancelled/cancelling */ 643538e03d2SFabiano Rosas migrate_cancel(from); 644538e03d2SFabiano Rosas migration_event_wait(from, phase); 645538e03d2SFabiano Rosas 646538e03d2SFabiano Rosas /* The migrate_cancel under test */ 647538e03d2SFabiano Rosas migrate_cancel(from); 648538e03d2SFabiano Rosas 649538e03d2SFabiano Rosas wait_for_migration_status(from, "cancelled", 650538e03d2SFabiano Rosas (const char * []) { "completed", NULL }); 651538e03d2SFabiano Rosas 652538e03d2SFabiano Rosas wait_for_migration_status(to, "failed", 653538e03d2SFabiano Rosas (const char * []) { "completed", NULL }); 654538e03d2SFabiano Rosas } 655538e03d2SFabiano Rosas 656538e03d2SFabiano Rosas static void test_cancel_src_after_complete(QTestState *from, QTestState *to, 657538e03d2SFabiano Rosas const char *uri, const char *phase) 658538e03d2SFabiano Rosas { 659538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }"); 660538e03d2SFabiano Rosas 661538e03d2SFabiano Rosas wait_for_serial("src_serial"); 662538e03d2SFabiano Rosas migrate_ensure_converge(from); 663538e03d2SFabiano Rosas 664538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 665538e03d2SFabiano Rosas 666538e03d2SFabiano Rosas migration_event_wait(from, phase); 667538e03d2SFabiano Rosas migrate_cancel(from); 668538e03d2SFabiano Rosas 669538e03d2SFabiano Rosas /* 670538e03d2SFabiano Rosas * qmp_migrate_cancel() exits early if migration is not running 671538e03d2SFabiano Rosas * anymore, the status will not change to cancelled. 672538e03d2SFabiano Rosas */ 673538e03d2SFabiano Rosas wait_for_migration_complete(from); 674538e03d2SFabiano Rosas wait_for_migration_complete(to); 675538e03d2SFabiano Rosas } 676538e03d2SFabiano Rosas 677538e03d2SFabiano Rosas static void test_cancel_src_after_none(QTestState *from, QTestState *to, 678538e03d2SFabiano Rosas const char *uri, const char *phase) 679538e03d2SFabiano Rosas { 680538e03d2SFabiano Rosas /* 681538e03d2SFabiano Rosas * Test that cancelling without a migration happening does not 682538e03d2SFabiano Rosas * affect subsequent migrations 683538e03d2SFabiano Rosas */ 684538e03d2SFabiano Rosas migrate_cancel(to); 685538e03d2SFabiano Rosas 686538e03d2SFabiano Rosas wait_for_serial("src_serial"); 687538e03d2SFabiano Rosas migrate_cancel(from); 688538e03d2SFabiano Rosas 689538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }"); 690538e03d2SFabiano Rosas 691538e03d2SFabiano Rosas migrate_ensure_converge(from); 692538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 693538e03d2SFabiano Rosas 694538e03d2SFabiano Rosas wait_for_migration_complete(from); 695538e03d2SFabiano Rosas wait_for_migration_complete(to); 696538e03d2SFabiano Rosas } 697538e03d2SFabiano Rosas 698538e03d2SFabiano Rosas static void test_cancel_src_pre_switchover(QTestState *from, QTestState *to, 699538e03d2SFabiano Rosas const char *uri, const char *phase) 700538e03d2SFabiano Rosas { 701538e03d2SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true); 702538e03d2SFabiano Rosas migrate_set_capability(to, "pause-before-switchover", true); 703538e03d2SFabiano Rosas 704538e03d2SFabiano Rosas migrate_set_capability(from, "multifd", true); 705538e03d2SFabiano Rosas migrate_set_capability(to, "multifd", true); 706538e03d2SFabiano Rosas 707538e03d2SFabiano Rosas migrate_incoming_qmp(to, uri, NULL, "{ 'exit-on-error': false }"); 708538e03d2SFabiano Rosas 709538e03d2SFabiano Rosas wait_for_serial("src_serial"); 710538e03d2SFabiano Rosas migrate_ensure_converge(from); 711538e03d2SFabiano Rosas 712538e03d2SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 713538e03d2SFabiano Rosas 714538e03d2SFabiano Rosas migration_event_wait(from, phase); 715538e03d2SFabiano Rosas migrate_cancel(from); 716538e03d2SFabiano Rosas migration_event_wait(from, "cancelling"); 717538e03d2SFabiano Rosas 718538e03d2SFabiano Rosas wait_for_migration_status(from, "cancelled", 719538e03d2SFabiano Rosas (const char * []) { "completed", NULL }); 720538e03d2SFabiano Rosas 721538e03d2SFabiano Rosas wait_for_migration_status(to, "failed", 722538e03d2SFabiano Rosas (const char * []) { "completed", NULL }); 723538e03d2SFabiano Rosas } 724538e03d2SFabiano Rosas 725538e03d2SFabiano Rosas static void test_cancel_src_after_status(void *opaque) 726538e03d2SFabiano Rosas { 727538e03d2SFabiano Rosas const char *test_path = opaque; 728538e03d2SFabiano Rosas g_autofree char *phase = g_path_get_basename(test_path); 729538e03d2SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 730538e03d2SFabiano Rosas QTestState *from, *to; 731538e03d2SFabiano Rosas MigrateStart args = { 732538e03d2SFabiano Rosas .hide_stderr = true, 733538e03d2SFabiano Rosas }; 734538e03d2SFabiano Rosas 735538e03d2SFabiano Rosas if (migrate_start(&from, &to, "defer", &args)) { 736538e03d2SFabiano Rosas return; 737538e03d2SFabiano Rosas } 738538e03d2SFabiano Rosas 739538e03d2SFabiano Rosas if (g_str_equal(phase, "cancelling") || 740538e03d2SFabiano Rosas g_str_equal(phase, "cancelled")) { 741538e03d2SFabiano Rosas test_cancel_src_after_cancelled(from, to, uri, phase); 742538e03d2SFabiano Rosas 743538e03d2SFabiano Rosas } else if (g_str_equal(phase, "completed")) { 744538e03d2SFabiano Rosas test_cancel_src_after_complete(from, to, uri, phase); 745538e03d2SFabiano Rosas 746538e03d2SFabiano Rosas } else if (g_str_equal(phase, "failed")) { 747538e03d2SFabiano Rosas test_cancel_src_after_failed(from, to, uri, phase); 748538e03d2SFabiano Rosas 749538e03d2SFabiano Rosas } else if (g_str_equal(phase, "none")) { 750538e03d2SFabiano Rosas test_cancel_src_after_none(from, to, uri, phase); 751538e03d2SFabiano Rosas 752538e03d2SFabiano Rosas } else { 753538e03d2SFabiano Rosas /* any state that comes before pre-switchover */ 754538e03d2SFabiano Rosas test_cancel_src_pre_switchover(from, to, uri, phase); 755538e03d2SFabiano Rosas } 756538e03d2SFabiano Rosas 757538e03d2SFabiano Rosas migrate_end(from, to, false); 758538e03d2SFabiano Rosas } 759538e03d2SFabiano Rosas 7608a645544SFabiano Rosas static void calc_dirty_rate(QTestState *who, uint64_t calc_time) 7618a645544SFabiano Rosas { 7628a645544SFabiano Rosas qtest_qmp_assert_success(who, 7638a645544SFabiano Rosas "{ 'execute': 'calc-dirty-rate'," 7648a645544SFabiano Rosas "'arguments': { " 7658a645544SFabiano Rosas "'calc-time': %" PRIu64 "," 7668a645544SFabiano Rosas "'mode': 'dirty-ring' }}", 7678a645544SFabiano Rosas calc_time); 7688a645544SFabiano Rosas } 7698a645544SFabiano Rosas 7708a645544SFabiano Rosas static QDict *query_dirty_rate(QTestState *who) 7718a645544SFabiano Rosas { 7728a645544SFabiano Rosas return qtest_qmp_assert_success_ref(who, 7738a645544SFabiano Rosas "{ 'execute': 'query-dirty-rate' }"); 7748a645544SFabiano Rosas } 7758a645544SFabiano Rosas 7768a645544SFabiano Rosas static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate) 7778a645544SFabiano Rosas { 7788a645544SFabiano Rosas qtest_qmp_assert_success(who, 7798a645544SFabiano Rosas "{ 'execute': 'set-vcpu-dirty-limit'," 7808a645544SFabiano Rosas "'arguments': { " 7818a645544SFabiano Rosas "'dirty-rate': %" PRIu64 " } }", 7828a645544SFabiano Rosas dirtyrate); 7838a645544SFabiano Rosas } 7848a645544SFabiano Rosas 7858a645544SFabiano Rosas static void cancel_vcpu_dirty_limit(QTestState *who) 7868a645544SFabiano Rosas { 7878a645544SFabiano Rosas qtest_qmp_assert_success(who, 7888a645544SFabiano Rosas "{ 'execute': 'cancel-vcpu-dirty-limit' }"); 7898a645544SFabiano Rosas } 7908a645544SFabiano Rosas 7918a645544SFabiano Rosas static QDict *query_vcpu_dirty_limit(QTestState *who) 7928a645544SFabiano Rosas { 7938a645544SFabiano Rosas QDict *rsp; 7948a645544SFabiano Rosas 7958a645544SFabiano Rosas rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }"); 7968a645544SFabiano Rosas g_assert(!qdict_haskey(rsp, "error")); 7978a645544SFabiano Rosas g_assert(qdict_haskey(rsp, "return")); 7988a645544SFabiano Rosas 7998a645544SFabiano Rosas return rsp; 8008a645544SFabiano Rosas } 8018a645544SFabiano Rosas 8028a645544SFabiano Rosas static bool calc_dirtyrate_ready(QTestState *who) 8038a645544SFabiano Rosas { 8048a645544SFabiano Rosas QDict *rsp_return; 8058a645544SFabiano Rosas const char *status; 8068a645544SFabiano Rosas bool ready; 8078a645544SFabiano Rosas 8088a645544SFabiano Rosas rsp_return = query_dirty_rate(who); 8098a645544SFabiano Rosas g_assert(rsp_return); 8108a645544SFabiano Rosas 8118a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status"); 8128a645544SFabiano Rosas g_assert(status); 8138a645544SFabiano Rosas ready = g_strcmp0(status, "measuring"); 8148a645544SFabiano Rosas qobject_unref(rsp_return); 8158a645544SFabiano Rosas 8168a645544SFabiano Rosas return ready; 8178a645544SFabiano Rosas } 8188a645544SFabiano Rosas 8198a645544SFabiano Rosas static void wait_for_calc_dirtyrate_complete(QTestState *who, 8208a645544SFabiano Rosas int64_t time_s) 8218a645544SFabiano Rosas { 8228a645544SFabiano Rosas int max_try_count = 10000; 8238a645544SFabiano Rosas usleep(time_s * 1000000); 8248a645544SFabiano Rosas 8258a645544SFabiano Rosas while (!calc_dirtyrate_ready(who) && max_try_count--) { 8268a645544SFabiano Rosas usleep(1000); 8278a645544SFabiano Rosas } 8288a645544SFabiano Rosas 8298a645544SFabiano Rosas /* 8308a645544SFabiano Rosas * Set the timeout with 10 s(max_try_count * 1000us), 8318a645544SFabiano Rosas * if dirtyrate measurement not complete, fail test. 8328a645544SFabiano Rosas */ 8338a645544SFabiano Rosas g_assert_cmpint(max_try_count, !=, 0); 8348a645544SFabiano Rosas } 8358a645544SFabiano Rosas 8368a645544SFabiano Rosas static int64_t get_dirty_rate(QTestState *who) 8378a645544SFabiano Rosas { 8388a645544SFabiano Rosas QDict *rsp_return; 8398a645544SFabiano Rosas const char *status; 8408a645544SFabiano Rosas QList *rates; 8418a645544SFabiano Rosas const QListEntry *entry; 8428a645544SFabiano Rosas QDict *rate; 8438a645544SFabiano Rosas int64_t dirtyrate; 8448a645544SFabiano Rosas 8458a645544SFabiano Rosas rsp_return = query_dirty_rate(who); 8468a645544SFabiano Rosas g_assert(rsp_return); 8478a645544SFabiano Rosas 8488a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status"); 8498a645544SFabiano Rosas g_assert(status); 8508a645544SFabiano Rosas g_assert_cmpstr(status, ==, "measured"); 8518a645544SFabiano Rosas 8528a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate"); 8538a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates)); 8548a645544SFabiano Rosas 8558a645544SFabiano Rosas entry = qlist_first(rates); 8568a645544SFabiano Rosas g_assert(entry); 8578a645544SFabiano Rosas 8588a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry)); 8598a645544SFabiano Rosas g_assert(rate); 8608a645544SFabiano Rosas 8618a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1); 8628a645544SFabiano Rosas 8638a645544SFabiano Rosas qobject_unref(rsp_return); 8648a645544SFabiano Rosas return dirtyrate; 8658a645544SFabiano Rosas } 8668a645544SFabiano Rosas 8678a645544SFabiano Rosas static int64_t get_limit_rate(QTestState *who) 8688a645544SFabiano Rosas { 8698a645544SFabiano Rosas QDict *rsp_return; 8708a645544SFabiano Rosas QList *rates; 8718a645544SFabiano Rosas const QListEntry *entry; 8728a645544SFabiano Rosas QDict *rate; 8738a645544SFabiano Rosas int64_t dirtyrate; 8748a645544SFabiano Rosas 8758a645544SFabiano Rosas rsp_return = query_vcpu_dirty_limit(who); 8768a645544SFabiano Rosas g_assert(rsp_return); 8778a645544SFabiano Rosas 8788a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "return"); 8798a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates)); 8808a645544SFabiano Rosas 8818a645544SFabiano Rosas entry = qlist_first(rates); 8828a645544SFabiano Rosas g_assert(entry); 8838a645544SFabiano Rosas 8848a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry)); 8858a645544SFabiano Rosas g_assert(rate); 8868a645544SFabiano Rosas 8878a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "limit-rate", -1); 8888a645544SFabiano Rosas 8898a645544SFabiano Rosas qobject_unref(rsp_return); 8908a645544SFabiano Rosas return dirtyrate; 8918a645544SFabiano Rosas } 8928a645544SFabiano Rosas 8938a645544SFabiano Rosas static QTestState *dirtylimit_start_vm(void) 8948a645544SFabiano Rosas { 8958a645544SFabiano Rosas QTestState *vm = NULL; 8968a645544SFabiano Rosas g_autofree gchar *cmd = NULL; 8978a645544SFabiano Rosas const char *bootpath; 8988a645544SFabiano Rosas 8998a645544SFabiano Rosas bootpath = bootfile_create(qtest_get_arch(), tmpfs, false); 9008a645544SFabiano Rosas cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 " 9018a645544SFabiano Rosas "-name dirtylimit-test,debug-threads=on " 9028a645544SFabiano Rosas "-m 150M -smp 1 " 9038a645544SFabiano Rosas "-serial file:%s/vm_serial " 9048a645544SFabiano Rosas "-drive file=%s,format=raw ", 9058a645544SFabiano Rosas tmpfs, bootpath); 9068a645544SFabiano Rosas 9078a645544SFabiano Rosas vm = qtest_init(cmd); 9088a645544SFabiano Rosas return vm; 9098a645544SFabiano Rosas } 9108a645544SFabiano Rosas 9118a645544SFabiano Rosas static void dirtylimit_stop_vm(QTestState *vm) 9128a645544SFabiano Rosas { 9138a645544SFabiano Rosas g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, "vm_serial"); 9148a645544SFabiano Rosas 9158a645544SFabiano Rosas qtest_quit(vm); 9168a645544SFabiano Rosas unlink(path); 9178a645544SFabiano Rosas } 9188a645544SFabiano Rosas 9198a645544SFabiano Rosas static void test_vcpu_dirty_limit(void) 9208a645544SFabiano Rosas { 9218a645544SFabiano Rosas QTestState *vm; 9228a645544SFabiano Rosas int64_t origin_rate; 9238a645544SFabiano Rosas int64_t quota_rate; 9248a645544SFabiano Rosas int64_t rate ; 9258a645544SFabiano Rosas int max_try_count = 20; 9268a645544SFabiano Rosas int hit = 0; 9278a645544SFabiano Rosas 9288a645544SFabiano Rosas /* Start vm for vcpu dirtylimit test */ 9298a645544SFabiano Rosas vm = dirtylimit_start_vm(); 9308a645544SFabiano Rosas 9318a645544SFabiano Rosas /* Wait for the first serial output from the vm*/ 9328a645544SFabiano Rosas wait_for_serial("vm_serial"); 9338a645544SFabiano Rosas 9348a645544SFabiano Rosas /* Do dirtyrate measurement with calc time equals 1s */ 9358a645544SFabiano Rosas calc_dirty_rate(vm, 1); 9368a645544SFabiano Rosas 9378a645544SFabiano Rosas /* Sleep calc time and wait for calc dirtyrate complete */ 9388a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 9398a645544SFabiano Rosas 9408a645544SFabiano Rosas /* Query original dirty page rate */ 9418a645544SFabiano Rosas origin_rate = get_dirty_rate(vm); 9428a645544SFabiano Rosas 9438a645544SFabiano Rosas /* VM booted from bootsect should dirty memory steadily */ 9448a645544SFabiano Rosas assert(origin_rate != 0); 9458a645544SFabiano Rosas 9468a645544SFabiano Rosas /* Setup quota dirty page rate at half of origin */ 9478a645544SFabiano Rosas quota_rate = origin_rate / 2; 9488a645544SFabiano Rosas 9498a645544SFabiano Rosas /* Set dirtylimit */ 9508a645544SFabiano Rosas dirtylimit_set_all(vm, quota_rate); 9518a645544SFabiano Rosas 9528a645544SFabiano Rosas /* 9538a645544SFabiano Rosas * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit 9548a645544SFabiano Rosas * works literally 9558a645544SFabiano Rosas */ 9568a645544SFabiano Rosas g_assert_cmpint(quota_rate, ==, get_limit_rate(vm)); 9578a645544SFabiano Rosas 9588a645544SFabiano Rosas /* Sleep a bit to check if it take effect */ 9598a645544SFabiano Rosas usleep(2000000); 9608a645544SFabiano Rosas 9618a645544SFabiano Rosas /* 9628a645544SFabiano Rosas * Check if dirtylimit take effect realistically, set the 9638a645544SFabiano Rosas * timeout with 20 s(max_try_count * 1s), if dirtylimit 9648a645544SFabiano Rosas * doesn't take effect, fail test. 9658a645544SFabiano Rosas */ 9668a645544SFabiano Rosas while (--max_try_count) { 9678a645544SFabiano Rosas calc_dirty_rate(vm, 1); 9688a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 9698a645544SFabiano Rosas rate = get_dirty_rate(vm); 9708a645544SFabiano Rosas 9718a645544SFabiano Rosas /* 9728a645544SFabiano Rosas * Assume hitting if current rate is less 9738a645544SFabiano Rosas * than quota rate (within accepting error) 9748a645544SFabiano Rosas */ 9758a645544SFabiano Rosas if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) { 9768a645544SFabiano Rosas hit = 1; 9778a645544SFabiano Rosas break; 9788a645544SFabiano Rosas } 9798a645544SFabiano Rosas } 9808a645544SFabiano Rosas 9818a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 9828a645544SFabiano Rosas 9838a645544SFabiano Rosas hit = 0; 9848a645544SFabiano Rosas max_try_count = 20; 9858a645544SFabiano Rosas 9868a645544SFabiano Rosas /* Check if dirtylimit cancellation take effect */ 9878a645544SFabiano Rosas cancel_vcpu_dirty_limit(vm); 9888a645544SFabiano Rosas while (--max_try_count) { 9898a645544SFabiano Rosas calc_dirty_rate(vm, 1); 9908a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 9918a645544SFabiano Rosas rate = get_dirty_rate(vm); 9928a645544SFabiano Rosas 9938a645544SFabiano Rosas /* 9948a645544SFabiano Rosas * Assume dirtylimit be canceled if current rate is 9958a645544SFabiano Rosas * greater than quota rate (within accepting error) 9968a645544SFabiano Rosas */ 9978a645544SFabiano Rosas if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) { 9988a645544SFabiano Rosas hit = 1; 9998a645544SFabiano Rosas break; 10008a645544SFabiano Rosas } 10018a645544SFabiano Rosas } 10028a645544SFabiano Rosas 10038a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 10048a645544SFabiano Rosas dirtylimit_stop_vm(vm); 10058a645544SFabiano Rosas } 10068a645544SFabiano Rosas 10078a645544SFabiano Rosas static void migrate_dirty_limit_wait_showup(QTestState *from, 10088a645544SFabiano Rosas const int64_t period, 10098a645544SFabiano Rosas const int64_t value) 10108a645544SFabiano Rosas { 10118a645544SFabiano Rosas /* Enable dirty limit capability */ 10128a645544SFabiano Rosas migrate_set_capability(from, "dirty-limit", true); 10138a645544SFabiano Rosas 10148a645544SFabiano Rosas /* Set dirty limit parameters */ 10158a645544SFabiano Rosas migrate_set_parameter_int(from, "x-vcpu-dirty-limit-period", period); 10168a645544SFabiano Rosas migrate_set_parameter_int(from, "vcpu-dirty-limit", value); 10178a645544SFabiano Rosas 10188a645544SFabiano Rosas /* Make sure migrate can't converge */ 10198a645544SFabiano Rosas migrate_ensure_non_converge(from); 10208a645544SFabiano Rosas 10218a645544SFabiano Rosas /* To check limit rate after precopy */ 10228a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true); 10238a645544SFabiano Rosas 10248a645544SFabiano Rosas /* Wait for the serial output from the source */ 10258a645544SFabiano Rosas wait_for_serial("src_serial"); 10268a645544SFabiano Rosas } 10278a645544SFabiano Rosas 10288a645544SFabiano Rosas /* 10298a645544SFabiano Rosas * This test does: 10308a645544SFabiano Rosas * source destination 10318a645544SFabiano Rosas * start vm 10328a645544SFabiano Rosas * start incoming vm 10338a645544SFabiano Rosas * migrate 10348a645544SFabiano Rosas * wait dirty limit to begin 10358a645544SFabiano Rosas * cancel migrate 10368a645544SFabiano Rosas * cancellation check 10378a645544SFabiano Rosas * restart incoming vm 10388a645544SFabiano Rosas * migrate 10398a645544SFabiano Rosas * wait dirty limit to begin 10408a645544SFabiano Rosas * wait pre-switchover event 10418a645544SFabiano Rosas * convergence condition check 10428a645544SFabiano Rosas * 10438a645544SFabiano Rosas * And see if dirty limit migration works correctly. 10448a645544SFabiano Rosas * This test case involves many passes, so it runs in slow mode only. 10458a645544SFabiano Rosas */ 10468a645544SFabiano Rosas static void test_dirty_limit(void) 10478a645544SFabiano Rosas { 10488a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 10498a645544SFabiano Rosas QTestState *from, *to; 10508a645544SFabiano Rosas int64_t remaining; 10518a645544SFabiano Rosas uint64_t throttle_us_per_full; 10528a645544SFabiano Rosas /* 10538a645544SFabiano Rosas * We want the test to be stable and as fast as possible. 10548a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without dirty limit, 10558a645544SFabiano Rosas * so we need to decrease a bandwidth. 10568a645544SFabiano Rosas */ 10578a645544SFabiano Rosas const int64_t dirtylimit_period = 1000, dirtylimit_value = 50; 10588a645544SFabiano Rosas const int64_t max_bandwidth = 400000000; /* ~400Mb/s */ 10598a645544SFabiano Rosas const int64_t downtime_limit = 250; /* 250ms */ 10608a645544SFabiano Rosas /* 10618a645544SFabiano Rosas * We migrate through unix-socket (> 500Mb/s). 10628a645544SFabiano Rosas * Thus, expected migration speed ~= bandwidth limit (< 500Mb/s). 10638a645544SFabiano Rosas * So, we can predict expected_threshold 10648a645544SFabiano Rosas */ 10658a645544SFabiano Rosas const int64_t expected_threshold = max_bandwidth * downtime_limit / 1000; 10668a645544SFabiano Rosas int max_try_count = 10; 10678a645544SFabiano Rosas MigrateCommon args = { 10688a645544SFabiano Rosas .start = { 10698a645544SFabiano Rosas .hide_stderr = true, 10708a645544SFabiano Rosas .use_dirty_ring = true, 10718a645544SFabiano Rosas }, 10728a645544SFabiano Rosas .listen_uri = uri, 10738a645544SFabiano Rosas .connect_uri = uri, 10748a645544SFabiano Rosas }; 10758a645544SFabiano Rosas 10768a645544SFabiano Rosas /* Start src, dst vm */ 10778a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) { 10788a645544SFabiano Rosas return; 10798a645544SFabiano Rosas } 10808a645544SFabiano Rosas 10818a645544SFabiano Rosas /* Prepare for dirty limit migration and wait src vm show up */ 10828a645544SFabiano Rosas migrate_dirty_limit_wait_showup(from, dirtylimit_period, dirtylimit_value); 10838a645544SFabiano Rosas 10848a645544SFabiano Rosas /* Start migrate */ 10858a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}"); 10868a645544SFabiano Rosas 10878a645544SFabiano Rosas /* Wait for dirty limit throttle begin */ 10888a645544SFabiano Rosas throttle_us_per_full = 0; 10898a645544SFabiano Rosas while (throttle_us_per_full == 0) { 10908a645544SFabiano Rosas throttle_us_per_full = 10918a645544SFabiano Rosas read_migrate_property_int(from, 10928a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 10938a645544SFabiano Rosas usleep(100); 10948a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 10958a645544SFabiano Rosas } 10968a645544SFabiano Rosas 10978a645544SFabiano Rosas /* Now cancel migrate and wait for dirty limit throttle switch off */ 10988a645544SFabiano Rosas migrate_cancel(from); 10998a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL); 11008a645544SFabiano Rosas 1101cd196679SFabiano Rosas /* destination always fails after cancel */ 1102cd196679SFabiano Rosas migration_event_wait(to, "failed"); 1103cd196679SFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE); 1104cd196679SFabiano Rosas qtest_quit(to); 1105cd196679SFabiano Rosas 11068a645544SFabiano Rosas /* Check if dirty limit throttle switched off, set timeout 1ms */ 11078a645544SFabiano Rosas do { 11088a645544SFabiano Rosas throttle_us_per_full = 11098a645544SFabiano Rosas read_migrate_property_int(from, 11108a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 11118a645544SFabiano Rosas usleep(100); 11128a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 11138a645544SFabiano Rosas } while (throttle_us_per_full != 0 && --max_try_count); 11148a645544SFabiano Rosas 11158a645544SFabiano Rosas /* Assert dirty limit is not in service */ 11168a645544SFabiano Rosas g_assert_cmpint(throttle_us_per_full, ==, 0); 11178a645544SFabiano Rosas 11188a645544SFabiano Rosas args = (MigrateCommon) { 11198a645544SFabiano Rosas .start = { 11208a645544SFabiano Rosas .only_target = true, 11218a645544SFabiano Rosas .use_dirty_ring = true, 11228a645544SFabiano Rosas }, 11238a645544SFabiano Rosas .listen_uri = uri, 11248a645544SFabiano Rosas .connect_uri = uri, 11258a645544SFabiano Rosas }; 11268a645544SFabiano Rosas 11278a645544SFabiano Rosas /* Restart dst vm, src vm already show up so we needn't wait anymore */ 11288a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) { 11298a645544SFabiano Rosas return; 11308a645544SFabiano Rosas } 11318a645544SFabiano Rosas 11328a645544SFabiano Rosas /* Start migrate */ 11338a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}"); 11348a645544SFabiano Rosas 11358a645544SFabiano Rosas /* Wait for dirty limit throttle begin */ 11368a645544SFabiano Rosas throttle_us_per_full = 0; 11378a645544SFabiano Rosas while (throttle_us_per_full == 0) { 11388a645544SFabiano Rosas throttle_us_per_full = 11398a645544SFabiano Rosas read_migrate_property_int(from, 11408a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 11418a645544SFabiano Rosas usleep(100); 11428a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 11438a645544SFabiano Rosas } 11448a645544SFabiano Rosas 11458a645544SFabiano Rosas /* 11468a645544SFabiano Rosas * The dirty limit rate should equals the return value of 11478a645544SFabiano Rosas * query-vcpu-dirty-limit if dirty limit cap set 11488a645544SFabiano Rosas */ 11498a645544SFabiano Rosas g_assert_cmpint(dirtylimit_value, ==, get_limit_rate(from)); 11508a645544SFabiano Rosas 11518a645544SFabiano Rosas /* Now, we have tested if dirty limit works, let it converge */ 11528a645544SFabiano Rosas migrate_set_parameter_int(from, "downtime-limit", downtime_limit); 11538a645544SFabiano Rosas migrate_set_parameter_int(from, "max-bandwidth", max_bandwidth); 11548a645544SFabiano Rosas 11558a645544SFabiano Rosas /* 11568a645544SFabiano Rosas * Wait for pre-switchover status to check if migration 11578a645544SFabiano Rosas * satisfy the convergence condition 11588a645544SFabiano Rosas */ 11598a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL); 11608a645544SFabiano Rosas 11618a645544SFabiano Rosas remaining = read_ram_property_int(from, "remaining"); 11628a645544SFabiano Rosas g_assert_cmpint(remaining, <, 11638a645544SFabiano Rosas (expected_threshold + expected_threshold / 100)); 11648a645544SFabiano Rosas 11658a645544SFabiano Rosas migrate_continue(from, "pre-switchover"); 11668a645544SFabiano Rosas 11678a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME"); 11688a645544SFabiano Rosas 11698a645544SFabiano Rosas wait_for_serial("dest_serial"); 11708a645544SFabiano Rosas wait_for_migration_complete(from); 11718a645544SFabiano Rosas 11728a645544SFabiano Rosas migrate_end(from, to, true); 11738a645544SFabiano Rosas } 11748a645544SFabiano Rosas 117543ab3fb3SFabiano Rosas static void migration_test_add_precopy_smoke(MigrationTestEnv *env) 11768a645544SFabiano Rosas { 11778a645544SFabiano Rosas if (env->is_x86) { 11788a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/live", 11798a645544SFabiano Rosas test_precopy_unix_suspend_live); 11808a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/notlive", 11818a645544SFabiano Rosas test_precopy_unix_suspend_notlive); 11828a645544SFabiano Rosas } 11838a645544SFabiano Rosas 11848a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/plain", 11858a645544SFabiano Rosas test_precopy_unix_plain); 11868a645544SFabiano Rosas 11878a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain", test_precopy_tcp_plain); 118843ab3fb3SFabiano Rosas migration_test_add("/migration/multifd/tcp/uri/plain/none", 118943ab3fb3SFabiano Rosas test_multifd_tcp_uri_none); 119043ab3fb3SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/cancel", 119143ab3fb3SFabiano Rosas test_multifd_tcp_cancel); 11927d9849c3SLi Zhijian #ifdef CONFIG_RDMA 11937d9849c3SLi Zhijian migration_test_add("/migration/precopy/rdma/plain", 11947d9849c3SLi Zhijian test_precopy_rdma_plain); 11957d9849c3SLi Zhijian #endif 119643ab3fb3SFabiano Rosas } 119743ab3fb3SFabiano Rosas 119843ab3fb3SFabiano Rosas void migration_test_add_precopy(MigrationTestEnv *env) 119943ab3fb3SFabiano Rosas { 120043ab3fb3SFabiano Rosas tmpfs = env->tmpfs; 120143ab3fb3SFabiano Rosas 120243ab3fb3SFabiano Rosas migration_test_add_precopy_smoke(env); 120343ab3fb3SFabiano Rosas 120443ab3fb3SFabiano Rosas if (!env->full_set) { 120543ab3fb3SFabiano Rosas return; 120643ab3fb3SFabiano Rosas } 12078a645544SFabiano Rosas 12088a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain/switchover-ack", 12098a645544SFabiano Rosas test_precopy_tcp_switchover_ack); 12108a645544SFabiano Rosas 12118a645544SFabiano Rosas #ifndef _WIN32 12128a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/tcp", 12138a645544SFabiano Rosas test_precopy_fd_socket); 12148a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/file", 12158a645544SFabiano Rosas test_precopy_fd_file); 12168a645544SFabiano Rosas #endif 12178a645544SFabiano Rosas 12188a645544SFabiano Rosas /* 12198a645544SFabiano Rosas * See explanation why this test is slow on function definition 12208a645544SFabiano Rosas */ 12218a645544SFabiano Rosas if (g_test_slow()) { 12228a645544SFabiano Rosas migration_test_add("/migration/auto_converge", 12238a645544SFabiano Rosas test_auto_converge); 12248a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64") && 12258a645544SFabiano Rosas env->has_kvm && env->has_dirty_ring) { 12268a645544SFabiano Rosas migration_test_add("/dirty_limit", 12278a645544SFabiano Rosas test_dirty_limit); 12288a645544SFabiano Rosas } 12298a645544SFabiano Rosas } 12308a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/channels/plain/none", 12318a645544SFabiano Rosas test_multifd_tcp_channels_none); 12328a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/legacy", 12338a645544SFabiano Rosas test_multifd_tcp_zero_page_legacy); 12348a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/none", 12358a645544SFabiano Rosas test_multifd_tcp_no_zero_page); 12368a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64") 12378a645544SFabiano Rosas && env->has_kvm && env->has_dirty_ring) { 12388a645544SFabiano Rosas 12398a645544SFabiano Rosas migration_test_add("/migration/dirty_ring", 12408a645544SFabiano Rosas test_precopy_unix_dirty_ring); 12418a645544SFabiano Rosas if (qtest_has_machine("pc") && g_test_slow()) { 12428a645544SFabiano Rosas migration_test_add("/migration/vcpu_dirty_limit", 12438a645544SFabiano Rosas test_vcpu_dirty_limit); 12448a645544SFabiano Rosas } 12458a645544SFabiano Rosas } 1246538e03d2SFabiano Rosas 1247538e03d2SFabiano Rosas /* ensure new status don't go unnoticed */ 1248538e03d2SFabiano Rosas assert(MIGRATION_STATUS__MAX == 15); 1249538e03d2SFabiano Rosas 1250538e03d2SFabiano Rosas for (int i = MIGRATION_STATUS_NONE; i < MIGRATION_STATUS__MAX; i++) { 1251538e03d2SFabiano Rosas switch (i) { 1252538e03d2SFabiano Rosas case MIGRATION_STATUS_DEVICE: /* happens too fast */ 1253538e03d2SFabiano Rosas case MIGRATION_STATUS_WAIT_UNPLUG: /* no support in tests */ 1254538e03d2SFabiano Rosas case MIGRATION_STATUS_COLO: /* no support in tests */ 1255538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_ACTIVE: /* postcopy can't be cancelled */ 1256538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_PAUSED: 1257538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_RECOVER_SETUP: 1258538e03d2SFabiano Rosas case MIGRATION_STATUS_POSTCOPY_RECOVER: 1259538e03d2SFabiano Rosas continue; 1260538e03d2SFabiano Rosas default: 1261538e03d2SFabiano Rosas migration_test_add_suffix("/migration/cancel/src/after/", 1262538e03d2SFabiano Rosas MigrationStatus_str(i), 1263538e03d2SFabiano Rosas test_cancel_src_after_status); 1264538e03d2SFabiano Rosas } 1265538e03d2SFabiano Rosas } 12668a645544SFabiano Rosas } 1267