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