1*8a645544SFabiano Rosas /* 2*8a645544SFabiano Rosas * QTest testcase for precopy migration 3*8a645544SFabiano Rosas * 4*8a645544SFabiano Rosas * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates 5*8a645544SFabiano Rosas * based on the vhost-user-test.c that is: 6*8a645544SFabiano Rosas * Copyright (c) 2014 Virtual Open Systems Sarl. 7*8a645544SFabiano Rosas * 8*8a645544SFabiano Rosas * This work is licensed under the terms of the GNU GPL, version 2 or later. 9*8a645544SFabiano Rosas * See the COPYING file in the top-level directory. 10*8a645544SFabiano Rosas * 11*8a645544SFabiano Rosas */ 12*8a645544SFabiano Rosas 13*8a645544SFabiano Rosas #include "qemu/osdep.h" 14*8a645544SFabiano Rosas #include "chardev/char.h" 15*8a645544SFabiano Rosas #include "crypto/tlscredspsk.h" 16*8a645544SFabiano Rosas #include "libqtest.h" 17*8a645544SFabiano Rosas #include "migration/bootfile.h" 18*8a645544SFabiano Rosas #include "migration/framework.h" 19*8a645544SFabiano Rosas #include "migration/migration-qmp.h" 20*8a645544SFabiano Rosas #include "migration/migration-util.h" 21*8a645544SFabiano Rosas #include "ppc-util.h" 22*8a645544SFabiano Rosas #include "qapi/qmp/qlist.h" 23*8a645544SFabiano Rosas #include "qemu/module.h" 24*8a645544SFabiano Rosas #include "qemu/option.h" 25*8a645544SFabiano Rosas #include "qemu/range.h" 26*8a645544SFabiano Rosas #include "qemu/sockets.h" 27*8a645544SFabiano Rosas 28*8a645544SFabiano Rosas 29*8a645544SFabiano Rosas /* 30*8a645544SFabiano Rosas * Dirtylimit stop working if dirty page rate error 31*8a645544SFabiano Rosas * value less than DIRTYLIMIT_TOLERANCE_RANGE 32*8a645544SFabiano Rosas */ 33*8a645544SFabiano Rosas #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */ 34*8a645544SFabiano Rosas 35*8a645544SFabiano Rosas static char *tmpfs; 36*8a645544SFabiano Rosas 37*8a645544SFabiano Rosas static void test_precopy_unix_plain(void) 38*8a645544SFabiano Rosas { 39*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 40*8a645544SFabiano Rosas MigrateCommon args = { 41*8a645544SFabiano Rosas .listen_uri = uri, 42*8a645544SFabiano Rosas .connect_uri = uri, 43*8a645544SFabiano Rosas /* 44*8a645544SFabiano Rosas * The simplest use case of precopy, covering smoke tests of 45*8a645544SFabiano Rosas * get-dirty-log dirty tracking. 46*8a645544SFabiano Rosas */ 47*8a645544SFabiano Rosas .live = true, 48*8a645544SFabiano Rosas }; 49*8a645544SFabiano Rosas 50*8a645544SFabiano Rosas test_precopy_common(&args); 51*8a645544SFabiano Rosas } 52*8a645544SFabiano Rosas 53*8a645544SFabiano Rosas static void test_precopy_unix_suspend_live(void) 54*8a645544SFabiano Rosas { 55*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 56*8a645544SFabiano Rosas MigrateCommon args = { 57*8a645544SFabiano Rosas .listen_uri = uri, 58*8a645544SFabiano Rosas .connect_uri = uri, 59*8a645544SFabiano Rosas /* 60*8a645544SFabiano Rosas * despite being live, the test is fast because the src 61*8a645544SFabiano Rosas * suspends immediately. 62*8a645544SFabiano Rosas */ 63*8a645544SFabiano Rosas .live = true, 64*8a645544SFabiano Rosas .start.suspend_me = true, 65*8a645544SFabiano Rosas }; 66*8a645544SFabiano Rosas 67*8a645544SFabiano Rosas test_precopy_common(&args); 68*8a645544SFabiano Rosas } 69*8a645544SFabiano Rosas 70*8a645544SFabiano Rosas static void test_precopy_unix_suspend_notlive(void) 71*8a645544SFabiano Rosas { 72*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 73*8a645544SFabiano Rosas MigrateCommon args = { 74*8a645544SFabiano Rosas .listen_uri = uri, 75*8a645544SFabiano Rosas .connect_uri = uri, 76*8a645544SFabiano Rosas .start.suspend_me = true, 77*8a645544SFabiano Rosas }; 78*8a645544SFabiano Rosas 79*8a645544SFabiano Rosas test_precopy_common(&args); 80*8a645544SFabiano Rosas } 81*8a645544SFabiano Rosas 82*8a645544SFabiano Rosas static void test_precopy_unix_dirty_ring(void) 83*8a645544SFabiano Rosas { 84*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 85*8a645544SFabiano Rosas MigrateCommon args = { 86*8a645544SFabiano Rosas .start = { 87*8a645544SFabiano Rosas .use_dirty_ring = true, 88*8a645544SFabiano Rosas }, 89*8a645544SFabiano Rosas .listen_uri = uri, 90*8a645544SFabiano Rosas .connect_uri = uri, 91*8a645544SFabiano Rosas /* 92*8a645544SFabiano Rosas * Besides the precopy/unix basic test, cover dirty ring interface 93*8a645544SFabiano Rosas * rather than get-dirty-log. 94*8a645544SFabiano Rosas */ 95*8a645544SFabiano Rosas .live = true, 96*8a645544SFabiano Rosas }; 97*8a645544SFabiano Rosas 98*8a645544SFabiano Rosas test_precopy_common(&args); 99*8a645544SFabiano Rosas } 100*8a645544SFabiano Rosas 101*8a645544SFabiano Rosas static void test_precopy_tcp_plain(void) 102*8a645544SFabiano Rosas { 103*8a645544SFabiano Rosas MigrateCommon args = { 104*8a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0", 105*8a645544SFabiano Rosas }; 106*8a645544SFabiano Rosas 107*8a645544SFabiano Rosas test_precopy_common(&args); 108*8a645544SFabiano Rosas } 109*8a645544SFabiano Rosas 110*8a645544SFabiano Rosas static void *migrate_hook_start_switchover_ack(QTestState *from, QTestState *to) 111*8a645544SFabiano Rosas { 112*8a645544SFabiano Rosas 113*8a645544SFabiano Rosas migrate_set_capability(from, "return-path", true); 114*8a645544SFabiano Rosas migrate_set_capability(to, "return-path", true); 115*8a645544SFabiano Rosas 116*8a645544SFabiano Rosas migrate_set_capability(from, "switchover-ack", true); 117*8a645544SFabiano Rosas migrate_set_capability(to, "switchover-ack", true); 118*8a645544SFabiano Rosas 119*8a645544SFabiano Rosas return NULL; 120*8a645544SFabiano Rosas } 121*8a645544SFabiano Rosas 122*8a645544SFabiano Rosas static void test_precopy_tcp_switchover_ack(void) 123*8a645544SFabiano Rosas { 124*8a645544SFabiano Rosas MigrateCommon args = { 125*8a645544SFabiano Rosas .listen_uri = "tcp:127.0.0.1:0", 126*8a645544SFabiano Rosas .start_hook = migrate_hook_start_switchover_ack, 127*8a645544SFabiano Rosas /* 128*8a645544SFabiano Rosas * Source VM must be running in order to consider the switchover ACK 129*8a645544SFabiano Rosas * when deciding to do switchover or not. 130*8a645544SFabiano Rosas */ 131*8a645544SFabiano Rosas .live = true, 132*8a645544SFabiano Rosas }; 133*8a645544SFabiano Rosas 134*8a645544SFabiano Rosas test_precopy_common(&args); 135*8a645544SFabiano Rosas } 136*8a645544SFabiano Rosas 137*8a645544SFabiano Rosas #ifndef _WIN32 138*8a645544SFabiano Rosas static void *migrate_hook_start_fd(QTestState *from, 139*8a645544SFabiano Rosas QTestState *to) 140*8a645544SFabiano Rosas { 141*8a645544SFabiano Rosas int ret; 142*8a645544SFabiano Rosas int pair[2]; 143*8a645544SFabiano Rosas 144*8a645544SFabiano Rosas /* Create two connected sockets for migration */ 145*8a645544SFabiano Rosas ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair); 146*8a645544SFabiano Rosas g_assert_cmpint(ret, ==, 0); 147*8a645544SFabiano Rosas 148*8a645544SFabiano Rosas /* Send the 1st socket to the target */ 149*8a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &pair[0], 1, 150*8a645544SFabiano Rosas "{ 'execute': 'getfd'," 151*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 152*8a645544SFabiano Rosas close(pair[0]); 153*8a645544SFabiano Rosas 154*8a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 155*8a645544SFabiano Rosas migrate_incoming_qmp(to, "fd:fd-mig", "{}"); 156*8a645544SFabiano Rosas 157*8a645544SFabiano Rosas /* Send the 2nd socket to the target */ 158*8a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &pair[1], 1, 159*8a645544SFabiano Rosas "{ 'execute': 'getfd'," 160*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 161*8a645544SFabiano Rosas close(pair[1]); 162*8a645544SFabiano Rosas 163*8a645544SFabiano Rosas return NULL; 164*8a645544SFabiano Rosas } 165*8a645544SFabiano Rosas 166*8a645544SFabiano Rosas static void migrate_hook_end_fd(QTestState *from, 167*8a645544SFabiano Rosas QTestState *to, 168*8a645544SFabiano Rosas void *opaque) 169*8a645544SFabiano Rosas { 170*8a645544SFabiano Rosas QDict *rsp; 171*8a645544SFabiano Rosas const char *error_desc; 172*8a645544SFabiano Rosas 173*8a645544SFabiano Rosas /* Test closing fds */ 174*8a645544SFabiano Rosas /* 175*8a645544SFabiano Rosas * We assume, that QEMU removes named fd from its list, 176*8a645544SFabiano Rosas * so this should fail. 177*8a645544SFabiano Rosas */ 178*8a645544SFabiano Rosas rsp = qtest_qmp(from, 179*8a645544SFabiano Rosas "{ 'execute': 'closefd'," 180*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 181*8a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error")); 182*8a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); 183*8a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); 184*8a645544SFabiano Rosas qobject_unref(rsp); 185*8a645544SFabiano Rosas 186*8a645544SFabiano Rosas rsp = qtest_qmp(to, 187*8a645544SFabiano Rosas "{ 'execute': 'closefd'," 188*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 189*8a645544SFabiano Rosas g_assert_true(qdict_haskey(rsp, "error")); 190*8a645544SFabiano Rosas error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); 191*8a645544SFabiano Rosas g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); 192*8a645544SFabiano Rosas qobject_unref(rsp); 193*8a645544SFabiano Rosas } 194*8a645544SFabiano Rosas 195*8a645544SFabiano Rosas static void test_precopy_fd_socket(void) 196*8a645544SFabiano Rosas { 197*8a645544SFabiano Rosas MigrateCommon args = { 198*8a645544SFabiano Rosas .listen_uri = "defer", 199*8a645544SFabiano Rosas .connect_uri = "fd:fd-mig", 200*8a645544SFabiano Rosas .start_hook = migrate_hook_start_fd, 201*8a645544SFabiano Rosas .end_hook = migrate_hook_end_fd, 202*8a645544SFabiano Rosas }; 203*8a645544SFabiano Rosas test_precopy_common(&args); 204*8a645544SFabiano Rosas } 205*8a645544SFabiano Rosas 206*8a645544SFabiano Rosas static void *migrate_hook_start_precopy_fd_file(QTestState *from, 207*8a645544SFabiano Rosas QTestState *to) 208*8a645544SFabiano Rosas { 209*8a645544SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME); 210*8a645544SFabiano Rosas int src_flags = O_CREAT | O_RDWR; 211*8a645544SFabiano Rosas int dst_flags = O_CREAT | O_RDWR; 212*8a645544SFabiano Rosas int fds[2]; 213*8a645544SFabiano Rosas 214*8a645544SFabiano Rosas fds[0] = open(file, src_flags, 0660); 215*8a645544SFabiano Rosas assert(fds[0] != -1); 216*8a645544SFabiano Rosas 217*8a645544SFabiano Rosas fds[1] = open(file, dst_flags, 0660); 218*8a645544SFabiano Rosas assert(fds[1] != -1); 219*8a645544SFabiano Rosas 220*8a645544SFabiano Rosas 221*8a645544SFabiano Rosas qtest_qmp_fds_assert_success(to, &fds[0], 1, 222*8a645544SFabiano Rosas "{ 'execute': 'getfd'," 223*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 224*8a645544SFabiano Rosas 225*8a645544SFabiano Rosas qtest_qmp_fds_assert_success(from, &fds[1], 1, 226*8a645544SFabiano Rosas "{ 'execute': 'getfd'," 227*8a645544SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}"); 228*8a645544SFabiano Rosas 229*8a645544SFabiano Rosas close(fds[0]); 230*8a645544SFabiano Rosas close(fds[1]); 231*8a645544SFabiano Rosas 232*8a645544SFabiano Rosas return NULL; 233*8a645544SFabiano Rosas } 234*8a645544SFabiano Rosas 235*8a645544SFabiano Rosas static void test_precopy_fd_file(void) 236*8a645544SFabiano Rosas { 237*8a645544SFabiano Rosas MigrateCommon args = { 238*8a645544SFabiano Rosas .listen_uri = "defer", 239*8a645544SFabiano Rosas .connect_uri = "fd:fd-mig", 240*8a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_fd_file, 241*8a645544SFabiano Rosas .end_hook = migrate_hook_end_fd, 242*8a645544SFabiano Rosas }; 243*8a645544SFabiano Rosas test_file_common(&args, true); 244*8a645544SFabiano Rosas } 245*8a645544SFabiano Rosas #endif /* _WIN32 */ 246*8a645544SFabiano Rosas 247*8a645544SFabiano Rosas /* 248*8a645544SFabiano Rosas * The way auto_converge works, we need to do too many passes to 249*8a645544SFabiano Rosas * run this test. Auto_converge logic is only run once every 250*8a645544SFabiano Rosas * three iterations, so: 251*8a645544SFabiano Rosas * 252*8a645544SFabiano Rosas * - 3 iterations without auto_converge enabled 253*8a645544SFabiano Rosas * - 3 iterations with pct = 5 254*8a645544SFabiano Rosas * - 3 iterations with pct = 30 255*8a645544SFabiano Rosas * - 3 iterations with pct = 55 256*8a645544SFabiano Rosas * - 3 iterations with pct = 80 257*8a645544SFabiano Rosas * - 3 iterations with pct = 95 (max(95, 80 + 25)) 258*8a645544SFabiano Rosas * 259*8a645544SFabiano Rosas * To make things even worse, we need to run the initial stage at 260*8a645544SFabiano Rosas * 3MB/s so we enter autoconverge even when host is (over)loaded. 261*8a645544SFabiano Rosas */ 262*8a645544SFabiano Rosas static void test_auto_converge(void) 263*8a645544SFabiano Rosas { 264*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 265*8a645544SFabiano Rosas MigrateStart args = {}; 266*8a645544SFabiano Rosas QTestState *from, *to; 267*8a645544SFabiano Rosas int64_t percentage; 268*8a645544SFabiano Rosas 269*8a645544SFabiano Rosas /* 270*8a645544SFabiano Rosas * We want the test to be stable and as fast as possible. 271*8a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without throttling, 272*8a645544SFabiano Rosas * so we need to decrease a bandwidth. 273*8a645544SFabiano Rosas */ 274*8a645544SFabiano Rosas const int64_t init_pct = 5, inc_pct = 25, max_pct = 95; 275*8a645544SFabiano Rosas uint64_t prev_dirty_sync_cnt, dirty_sync_cnt; 276*8a645544SFabiano Rosas int max_try_count, hit = 0; 277*8a645544SFabiano Rosas 278*8a645544SFabiano Rosas if (migrate_start(&from, &to, uri, &args)) { 279*8a645544SFabiano Rosas return; 280*8a645544SFabiano Rosas } 281*8a645544SFabiano Rosas 282*8a645544SFabiano Rosas migrate_set_capability(from, "auto-converge", true); 283*8a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct); 284*8a645544SFabiano Rosas migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct); 285*8a645544SFabiano Rosas migrate_set_parameter_int(from, "max-cpu-throttle", max_pct); 286*8a645544SFabiano Rosas 287*8a645544SFabiano Rosas /* 288*8a645544SFabiano Rosas * Set the initial parameters so that the migration could not converge 289*8a645544SFabiano Rosas * without throttling. 290*8a645544SFabiano Rosas */ 291*8a645544SFabiano Rosas migrate_ensure_non_converge(from); 292*8a645544SFabiano Rosas 293*8a645544SFabiano Rosas /* To check remaining size after precopy */ 294*8a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true); 295*8a645544SFabiano Rosas 296*8a645544SFabiano Rosas /* Wait for the first serial output from the source */ 297*8a645544SFabiano Rosas wait_for_serial("src_serial"); 298*8a645544SFabiano Rosas 299*8a645544SFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 300*8a645544SFabiano Rosas 301*8a645544SFabiano Rosas /* Wait for throttling begins */ 302*8a645544SFabiano Rosas percentage = 0; 303*8a645544SFabiano Rosas do { 304*8a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage"); 305*8a645544SFabiano Rosas if (percentage != 0) { 306*8a645544SFabiano Rosas break; 307*8a645544SFabiano Rosas } 308*8a645544SFabiano Rosas usleep(20); 309*8a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 310*8a645544SFabiano Rosas } while (true); 311*8a645544SFabiano Rosas /* The first percentage of throttling should be at least init_pct */ 312*8a645544SFabiano Rosas g_assert_cmpint(percentage, >=, init_pct); 313*8a645544SFabiano Rosas 314*8a645544SFabiano Rosas /* 315*8a645544SFabiano Rosas * End the loop when the dirty sync count greater than 1. 316*8a645544SFabiano Rosas */ 317*8a645544SFabiano Rosas while ((dirty_sync_cnt = get_migration_pass(from)) < 2) { 318*8a645544SFabiano Rosas usleep(1000 * 1000); 319*8a645544SFabiano Rosas } 320*8a645544SFabiano Rosas 321*8a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt; 322*8a645544SFabiano Rosas 323*8a645544SFabiano Rosas /* 324*8a645544SFabiano Rosas * The RAMBlock dirty sync count must changes in 5 seconds, here we set 325*8a645544SFabiano Rosas * the timeout to 10 seconds to ensure it changes. 326*8a645544SFabiano Rosas * 327*8a645544SFabiano Rosas * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s, 328*8a645544SFabiano Rosas * while the qtest mem is >= 100MB, one iteration takes at least 33s (100/3) 329*8a645544SFabiano Rosas * to complete; this ensures that the RAMBlock dirty sync occurs. 330*8a645544SFabiano Rosas */ 331*8a645544SFabiano Rosas max_try_count = 10; 332*8a645544SFabiano Rosas while (--max_try_count) { 333*8a645544SFabiano Rosas dirty_sync_cnt = get_migration_pass(from); 334*8a645544SFabiano Rosas if (dirty_sync_cnt != prev_dirty_sync_cnt) { 335*8a645544SFabiano Rosas hit = 1; 336*8a645544SFabiano Rosas break; 337*8a645544SFabiano Rosas } 338*8a645544SFabiano Rosas prev_dirty_sync_cnt = dirty_sync_cnt; 339*8a645544SFabiano Rosas sleep(1); 340*8a645544SFabiano Rosas } 341*8a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 342*8a645544SFabiano Rosas 343*8a645544SFabiano Rosas /* Now, when we tested that throttling works, let it converge */ 344*8a645544SFabiano Rosas migrate_ensure_converge(from); 345*8a645544SFabiano Rosas 346*8a645544SFabiano Rosas /* 347*8a645544SFabiano Rosas * Wait for pre-switchover status to check last throttle percentage 348*8a645544SFabiano Rosas * and remaining. These values will be zeroed later 349*8a645544SFabiano Rosas */ 350*8a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL); 351*8a645544SFabiano Rosas 352*8a645544SFabiano Rosas /* The final percentage of throttling shouldn't be greater than max_pct */ 353*8a645544SFabiano Rosas percentage = read_migrate_property_int(from, "cpu-throttle-percentage"); 354*8a645544SFabiano Rosas g_assert_cmpint(percentage, <=, max_pct); 355*8a645544SFabiano Rosas migrate_continue(from, "pre-switchover"); 356*8a645544SFabiano Rosas 357*8a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME"); 358*8a645544SFabiano Rosas 359*8a645544SFabiano Rosas wait_for_serial("dest_serial"); 360*8a645544SFabiano Rosas wait_for_migration_complete(from); 361*8a645544SFabiano Rosas 362*8a645544SFabiano Rosas migrate_end(from, to, true); 363*8a645544SFabiano Rosas } 364*8a645544SFabiano Rosas 365*8a645544SFabiano Rosas static void * 366*8a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd(QTestState *from, 367*8a645544SFabiano Rosas QTestState *to) 368*8a645544SFabiano Rosas { 369*8a645544SFabiano Rosas return migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 370*8a645544SFabiano Rosas } 371*8a645544SFabiano Rosas 372*8a645544SFabiano Rosas static void * 373*8a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_zero_page_legacy(QTestState *from, 374*8a645544SFabiano Rosas QTestState *to) 375*8a645544SFabiano Rosas { 376*8a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 377*8a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "legacy"); 378*8a645544SFabiano Rosas return NULL; 379*8a645544SFabiano Rosas } 380*8a645544SFabiano Rosas 381*8a645544SFabiano Rosas static void * 382*8a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_no_zero_page(QTestState *from, 383*8a645544SFabiano Rosas QTestState *to) 384*8a645544SFabiano Rosas { 385*8a645544SFabiano Rosas migrate_hook_start_precopy_tcp_multifd_common(from, to, "none"); 386*8a645544SFabiano Rosas migrate_set_parameter_str(from, "zero-page-detection", "none"); 387*8a645544SFabiano Rosas return NULL; 388*8a645544SFabiano Rosas } 389*8a645544SFabiano Rosas 390*8a645544SFabiano Rosas static void test_multifd_tcp_uri_none(void) 391*8a645544SFabiano Rosas { 392*8a645544SFabiano Rosas MigrateCommon args = { 393*8a645544SFabiano Rosas .listen_uri = "defer", 394*8a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd, 395*8a645544SFabiano Rosas /* 396*8a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 397*8a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 398*8a645544SFabiano Rosas * everything will work alright even if guest page is changing. 399*8a645544SFabiano Rosas */ 400*8a645544SFabiano Rosas .live = true, 401*8a645544SFabiano Rosas }; 402*8a645544SFabiano Rosas test_precopy_common(&args); 403*8a645544SFabiano Rosas } 404*8a645544SFabiano Rosas 405*8a645544SFabiano Rosas static void test_multifd_tcp_zero_page_legacy(void) 406*8a645544SFabiano Rosas { 407*8a645544SFabiano Rosas MigrateCommon args = { 408*8a645544SFabiano Rosas .listen_uri = "defer", 409*8a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_zero_page_legacy, 410*8a645544SFabiano Rosas /* 411*8a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 412*8a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 413*8a645544SFabiano Rosas * everything will work alright even if guest page is changing. 414*8a645544SFabiano Rosas */ 415*8a645544SFabiano Rosas .live = true, 416*8a645544SFabiano Rosas }; 417*8a645544SFabiano Rosas test_precopy_common(&args); 418*8a645544SFabiano Rosas } 419*8a645544SFabiano Rosas 420*8a645544SFabiano Rosas static void test_multifd_tcp_no_zero_page(void) 421*8a645544SFabiano Rosas { 422*8a645544SFabiano Rosas MigrateCommon args = { 423*8a645544SFabiano Rosas .listen_uri = "defer", 424*8a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd_no_zero_page, 425*8a645544SFabiano Rosas /* 426*8a645544SFabiano Rosas * Multifd is more complicated than most of the features, it 427*8a645544SFabiano Rosas * directly takes guest page buffers when sending, make sure 428*8a645544SFabiano Rosas * everything will work alright even if guest page is changing. 429*8a645544SFabiano Rosas */ 430*8a645544SFabiano Rosas .live = true, 431*8a645544SFabiano Rosas }; 432*8a645544SFabiano Rosas test_precopy_common(&args); 433*8a645544SFabiano Rosas } 434*8a645544SFabiano Rosas 435*8a645544SFabiano Rosas static void test_multifd_tcp_channels_none(void) 436*8a645544SFabiano Rosas { 437*8a645544SFabiano Rosas MigrateCommon args = { 438*8a645544SFabiano Rosas .listen_uri = "defer", 439*8a645544SFabiano Rosas .start_hook = migrate_hook_start_precopy_tcp_multifd, 440*8a645544SFabiano Rosas .live = true, 441*8a645544SFabiano Rosas .connect_channels = ("[ { 'channel-type': 'main'," 442*8a645544SFabiano Rosas " 'addr': { 'transport': 'socket'," 443*8a645544SFabiano Rosas " 'type': 'inet'," 444*8a645544SFabiano Rosas " 'host': '127.0.0.1'," 445*8a645544SFabiano Rosas " 'port': '0' } } ]"), 446*8a645544SFabiano Rosas }; 447*8a645544SFabiano Rosas test_precopy_common(&args); 448*8a645544SFabiano Rosas } 449*8a645544SFabiano Rosas 450*8a645544SFabiano Rosas /* 451*8a645544SFabiano Rosas * This test does: 452*8a645544SFabiano Rosas * source target 453*8a645544SFabiano Rosas * migrate_incoming 454*8a645544SFabiano Rosas * migrate 455*8a645544SFabiano Rosas * migrate_cancel 456*8a645544SFabiano Rosas * launch another target 457*8a645544SFabiano Rosas * migrate 458*8a645544SFabiano Rosas * 459*8a645544SFabiano Rosas * And see that it works 460*8a645544SFabiano Rosas */ 461*8a645544SFabiano Rosas static void test_multifd_tcp_cancel(void) 462*8a645544SFabiano Rosas { 463*8a645544SFabiano Rosas MigrateStart args = { 464*8a645544SFabiano Rosas .hide_stderr = true, 465*8a645544SFabiano Rosas }; 466*8a645544SFabiano Rosas QTestState *from, *to, *to2; 467*8a645544SFabiano Rosas 468*8a645544SFabiano Rosas if (migrate_start(&from, &to, "defer", &args)) { 469*8a645544SFabiano Rosas return; 470*8a645544SFabiano Rosas } 471*8a645544SFabiano Rosas 472*8a645544SFabiano Rosas migrate_ensure_non_converge(from); 473*8a645544SFabiano Rosas migrate_prepare_for_dirty_mem(from); 474*8a645544SFabiano Rosas 475*8a645544SFabiano Rosas migrate_set_parameter_int(from, "multifd-channels", 16); 476*8a645544SFabiano Rosas migrate_set_parameter_int(to, "multifd-channels", 16); 477*8a645544SFabiano Rosas 478*8a645544SFabiano Rosas migrate_set_capability(from, "multifd", true); 479*8a645544SFabiano Rosas migrate_set_capability(to, "multifd", true); 480*8a645544SFabiano Rosas 481*8a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 482*8a645544SFabiano Rosas migrate_incoming_qmp(to, "tcp:127.0.0.1:0", "{}"); 483*8a645544SFabiano Rosas 484*8a645544SFabiano Rosas /* Wait for the first serial output from the source */ 485*8a645544SFabiano Rosas wait_for_serial("src_serial"); 486*8a645544SFabiano Rosas 487*8a645544SFabiano Rosas migrate_qmp(from, to, NULL, NULL, "{}"); 488*8a645544SFabiano Rosas 489*8a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to); 490*8a645544SFabiano Rosas 491*8a645544SFabiano Rosas migrate_cancel(from); 492*8a645544SFabiano Rosas 493*8a645544SFabiano Rosas /* Make sure QEMU process "to" exited */ 494*8a645544SFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE); 495*8a645544SFabiano Rosas qtest_wait_qemu(to); 496*8a645544SFabiano Rosas qtest_quit(to); 497*8a645544SFabiano Rosas 498*8a645544SFabiano Rosas /* 499*8a645544SFabiano Rosas * Ensure the source QEMU finishes its cancellation process before we 500*8a645544SFabiano Rosas * proceed with the setup of the next migration. The migrate_start() 501*8a645544SFabiano Rosas * function and others might want to interact with the source in a way that 502*8a645544SFabiano Rosas * is not possible while the migration is not canceled properly. For 503*8a645544SFabiano Rosas * example, setting migration capabilities when the migration is still 504*8a645544SFabiano Rosas * running leads to an error. 505*8a645544SFabiano Rosas */ 506*8a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL); 507*8a645544SFabiano Rosas 508*8a645544SFabiano Rosas args = (MigrateStart){ 509*8a645544SFabiano Rosas .only_target = true, 510*8a645544SFabiano Rosas }; 511*8a645544SFabiano Rosas 512*8a645544SFabiano Rosas if (migrate_start(&from, &to2, "defer", &args)) { 513*8a645544SFabiano Rosas return; 514*8a645544SFabiano Rosas } 515*8a645544SFabiano Rosas 516*8a645544SFabiano Rosas migrate_set_parameter_int(to2, "multifd-channels", 16); 517*8a645544SFabiano Rosas 518*8a645544SFabiano Rosas migrate_set_capability(to2, "multifd", true); 519*8a645544SFabiano Rosas 520*8a645544SFabiano Rosas /* Start incoming migration from the 1st socket */ 521*8a645544SFabiano Rosas migrate_incoming_qmp(to2, "tcp:127.0.0.1:0", "{}"); 522*8a645544SFabiano Rosas 523*8a645544SFabiano Rosas migrate_ensure_non_converge(from); 524*8a645544SFabiano Rosas 525*8a645544SFabiano Rosas migrate_qmp(from, to2, NULL, NULL, "{}"); 526*8a645544SFabiano Rosas 527*8a645544SFabiano Rosas migrate_wait_for_dirty_mem(from, to2); 528*8a645544SFabiano Rosas 529*8a645544SFabiano Rosas migrate_ensure_converge(from); 530*8a645544SFabiano Rosas 531*8a645544SFabiano Rosas wait_for_stop(from, get_src()); 532*8a645544SFabiano Rosas qtest_qmp_eventwait(to2, "RESUME"); 533*8a645544SFabiano Rosas 534*8a645544SFabiano Rosas wait_for_serial("dest_serial"); 535*8a645544SFabiano Rosas wait_for_migration_complete(from); 536*8a645544SFabiano Rosas migrate_end(from, to2, true); 537*8a645544SFabiano Rosas } 538*8a645544SFabiano Rosas 539*8a645544SFabiano Rosas static void calc_dirty_rate(QTestState *who, uint64_t calc_time) 540*8a645544SFabiano Rosas { 541*8a645544SFabiano Rosas qtest_qmp_assert_success(who, 542*8a645544SFabiano Rosas "{ 'execute': 'calc-dirty-rate'," 543*8a645544SFabiano Rosas "'arguments': { " 544*8a645544SFabiano Rosas "'calc-time': %" PRIu64 "," 545*8a645544SFabiano Rosas "'mode': 'dirty-ring' }}", 546*8a645544SFabiano Rosas calc_time); 547*8a645544SFabiano Rosas } 548*8a645544SFabiano Rosas 549*8a645544SFabiano Rosas static QDict *query_dirty_rate(QTestState *who) 550*8a645544SFabiano Rosas { 551*8a645544SFabiano Rosas return qtest_qmp_assert_success_ref(who, 552*8a645544SFabiano Rosas "{ 'execute': 'query-dirty-rate' }"); 553*8a645544SFabiano Rosas } 554*8a645544SFabiano Rosas 555*8a645544SFabiano Rosas static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate) 556*8a645544SFabiano Rosas { 557*8a645544SFabiano Rosas qtest_qmp_assert_success(who, 558*8a645544SFabiano Rosas "{ 'execute': 'set-vcpu-dirty-limit'," 559*8a645544SFabiano Rosas "'arguments': { " 560*8a645544SFabiano Rosas "'dirty-rate': %" PRIu64 " } }", 561*8a645544SFabiano Rosas dirtyrate); 562*8a645544SFabiano Rosas } 563*8a645544SFabiano Rosas 564*8a645544SFabiano Rosas static void cancel_vcpu_dirty_limit(QTestState *who) 565*8a645544SFabiano Rosas { 566*8a645544SFabiano Rosas qtest_qmp_assert_success(who, 567*8a645544SFabiano Rosas "{ 'execute': 'cancel-vcpu-dirty-limit' }"); 568*8a645544SFabiano Rosas } 569*8a645544SFabiano Rosas 570*8a645544SFabiano Rosas static QDict *query_vcpu_dirty_limit(QTestState *who) 571*8a645544SFabiano Rosas { 572*8a645544SFabiano Rosas QDict *rsp; 573*8a645544SFabiano Rosas 574*8a645544SFabiano Rosas rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }"); 575*8a645544SFabiano Rosas g_assert(!qdict_haskey(rsp, "error")); 576*8a645544SFabiano Rosas g_assert(qdict_haskey(rsp, "return")); 577*8a645544SFabiano Rosas 578*8a645544SFabiano Rosas return rsp; 579*8a645544SFabiano Rosas } 580*8a645544SFabiano Rosas 581*8a645544SFabiano Rosas static bool calc_dirtyrate_ready(QTestState *who) 582*8a645544SFabiano Rosas { 583*8a645544SFabiano Rosas QDict *rsp_return; 584*8a645544SFabiano Rosas const char *status; 585*8a645544SFabiano Rosas bool ready; 586*8a645544SFabiano Rosas 587*8a645544SFabiano Rosas rsp_return = query_dirty_rate(who); 588*8a645544SFabiano Rosas g_assert(rsp_return); 589*8a645544SFabiano Rosas 590*8a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status"); 591*8a645544SFabiano Rosas g_assert(status); 592*8a645544SFabiano Rosas ready = g_strcmp0(status, "measuring"); 593*8a645544SFabiano Rosas qobject_unref(rsp_return); 594*8a645544SFabiano Rosas 595*8a645544SFabiano Rosas return ready; 596*8a645544SFabiano Rosas } 597*8a645544SFabiano Rosas 598*8a645544SFabiano Rosas static void wait_for_calc_dirtyrate_complete(QTestState *who, 599*8a645544SFabiano Rosas int64_t time_s) 600*8a645544SFabiano Rosas { 601*8a645544SFabiano Rosas int max_try_count = 10000; 602*8a645544SFabiano Rosas usleep(time_s * 1000000); 603*8a645544SFabiano Rosas 604*8a645544SFabiano Rosas while (!calc_dirtyrate_ready(who) && max_try_count--) { 605*8a645544SFabiano Rosas usleep(1000); 606*8a645544SFabiano Rosas } 607*8a645544SFabiano Rosas 608*8a645544SFabiano Rosas /* 609*8a645544SFabiano Rosas * Set the timeout with 10 s(max_try_count * 1000us), 610*8a645544SFabiano Rosas * if dirtyrate measurement not complete, fail test. 611*8a645544SFabiano Rosas */ 612*8a645544SFabiano Rosas g_assert_cmpint(max_try_count, !=, 0); 613*8a645544SFabiano Rosas } 614*8a645544SFabiano Rosas 615*8a645544SFabiano Rosas static int64_t get_dirty_rate(QTestState *who) 616*8a645544SFabiano Rosas { 617*8a645544SFabiano Rosas QDict *rsp_return; 618*8a645544SFabiano Rosas const char *status; 619*8a645544SFabiano Rosas QList *rates; 620*8a645544SFabiano Rosas const QListEntry *entry; 621*8a645544SFabiano Rosas QDict *rate; 622*8a645544SFabiano Rosas int64_t dirtyrate; 623*8a645544SFabiano Rosas 624*8a645544SFabiano Rosas rsp_return = query_dirty_rate(who); 625*8a645544SFabiano Rosas g_assert(rsp_return); 626*8a645544SFabiano Rosas 627*8a645544SFabiano Rosas status = qdict_get_str(rsp_return, "status"); 628*8a645544SFabiano Rosas g_assert(status); 629*8a645544SFabiano Rosas g_assert_cmpstr(status, ==, "measured"); 630*8a645544SFabiano Rosas 631*8a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate"); 632*8a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates)); 633*8a645544SFabiano Rosas 634*8a645544SFabiano Rosas entry = qlist_first(rates); 635*8a645544SFabiano Rosas g_assert(entry); 636*8a645544SFabiano Rosas 637*8a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry)); 638*8a645544SFabiano Rosas g_assert(rate); 639*8a645544SFabiano Rosas 640*8a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1); 641*8a645544SFabiano Rosas 642*8a645544SFabiano Rosas qobject_unref(rsp_return); 643*8a645544SFabiano Rosas return dirtyrate; 644*8a645544SFabiano Rosas } 645*8a645544SFabiano Rosas 646*8a645544SFabiano Rosas static int64_t get_limit_rate(QTestState *who) 647*8a645544SFabiano Rosas { 648*8a645544SFabiano Rosas QDict *rsp_return; 649*8a645544SFabiano Rosas QList *rates; 650*8a645544SFabiano Rosas const QListEntry *entry; 651*8a645544SFabiano Rosas QDict *rate; 652*8a645544SFabiano Rosas int64_t dirtyrate; 653*8a645544SFabiano Rosas 654*8a645544SFabiano Rosas rsp_return = query_vcpu_dirty_limit(who); 655*8a645544SFabiano Rosas g_assert(rsp_return); 656*8a645544SFabiano Rosas 657*8a645544SFabiano Rosas rates = qdict_get_qlist(rsp_return, "return"); 658*8a645544SFabiano Rosas g_assert(rates && !qlist_empty(rates)); 659*8a645544SFabiano Rosas 660*8a645544SFabiano Rosas entry = qlist_first(rates); 661*8a645544SFabiano Rosas g_assert(entry); 662*8a645544SFabiano Rosas 663*8a645544SFabiano Rosas rate = qobject_to(QDict, qlist_entry_obj(entry)); 664*8a645544SFabiano Rosas g_assert(rate); 665*8a645544SFabiano Rosas 666*8a645544SFabiano Rosas dirtyrate = qdict_get_try_int(rate, "limit-rate", -1); 667*8a645544SFabiano Rosas 668*8a645544SFabiano Rosas qobject_unref(rsp_return); 669*8a645544SFabiano Rosas return dirtyrate; 670*8a645544SFabiano Rosas } 671*8a645544SFabiano Rosas 672*8a645544SFabiano Rosas static QTestState *dirtylimit_start_vm(void) 673*8a645544SFabiano Rosas { 674*8a645544SFabiano Rosas QTestState *vm = NULL; 675*8a645544SFabiano Rosas g_autofree gchar *cmd = NULL; 676*8a645544SFabiano Rosas const char *bootpath; 677*8a645544SFabiano Rosas 678*8a645544SFabiano Rosas bootpath = bootfile_create(qtest_get_arch(), tmpfs, false); 679*8a645544SFabiano Rosas cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 " 680*8a645544SFabiano Rosas "-name dirtylimit-test,debug-threads=on " 681*8a645544SFabiano Rosas "-m 150M -smp 1 " 682*8a645544SFabiano Rosas "-serial file:%s/vm_serial " 683*8a645544SFabiano Rosas "-drive file=%s,format=raw ", 684*8a645544SFabiano Rosas tmpfs, bootpath); 685*8a645544SFabiano Rosas 686*8a645544SFabiano Rosas vm = qtest_init(cmd); 687*8a645544SFabiano Rosas return vm; 688*8a645544SFabiano Rosas } 689*8a645544SFabiano Rosas 690*8a645544SFabiano Rosas static void dirtylimit_stop_vm(QTestState *vm) 691*8a645544SFabiano Rosas { 692*8a645544SFabiano Rosas g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, "vm_serial"); 693*8a645544SFabiano Rosas 694*8a645544SFabiano Rosas qtest_quit(vm); 695*8a645544SFabiano Rosas unlink(path); 696*8a645544SFabiano Rosas } 697*8a645544SFabiano Rosas 698*8a645544SFabiano Rosas static void test_vcpu_dirty_limit(void) 699*8a645544SFabiano Rosas { 700*8a645544SFabiano Rosas QTestState *vm; 701*8a645544SFabiano Rosas int64_t origin_rate; 702*8a645544SFabiano Rosas int64_t quota_rate; 703*8a645544SFabiano Rosas int64_t rate ; 704*8a645544SFabiano Rosas int max_try_count = 20; 705*8a645544SFabiano Rosas int hit = 0; 706*8a645544SFabiano Rosas 707*8a645544SFabiano Rosas /* Start vm for vcpu dirtylimit test */ 708*8a645544SFabiano Rosas vm = dirtylimit_start_vm(); 709*8a645544SFabiano Rosas 710*8a645544SFabiano Rosas /* Wait for the first serial output from the vm*/ 711*8a645544SFabiano Rosas wait_for_serial("vm_serial"); 712*8a645544SFabiano Rosas 713*8a645544SFabiano Rosas /* Do dirtyrate measurement with calc time equals 1s */ 714*8a645544SFabiano Rosas calc_dirty_rate(vm, 1); 715*8a645544SFabiano Rosas 716*8a645544SFabiano Rosas /* Sleep calc time and wait for calc dirtyrate complete */ 717*8a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 718*8a645544SFabiano Rosas 719*8a645544SFabiano Rosas /* Query original dirty page rate */ 720*8a645544SFabiano Rosas origin_rate = get_dirty_rate(vm); 721*8a645544SFabiano Rosas 722*8a645544SFabiano Rosas /* VM booted from bootsect should dirty memory steadily */ 723*8a645544SFabiano Rosas assert(origin_rate != 0); 724*8a645544SFabiano Rosas 725*8a645544SFabiano Rosas /* Setup quota dirty page rate at half of origin */ 726*8a645544SFabiano Rosas quota_rate = origin_rate / 2; 727*8a645544SFabiano Rosas 728*8a645544SFabiano Rosas /* Set dirtylimit */ 729*8a645544SFabiano Rosas dirtylimit_set_all(vm, quota_rate); 730*8a645544SFabiano Rosas 731*8a645544SFabiano Rosas /* 732*8a645544SFabiano Rosas * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit 733*8a645544SFabiano Rosas * works literally 734*8a645544SFabiano Rosas */ 735*8a645544SFabiano Rosas g_assert_cmpint(quota_rate, ==, get_limit_rate(vm)); 736*8a645544SFabiano Rosas 737*8a645544SFabiano Rosas /* Sleep a bit to check if it take effect */ 738*8a645544SFabiano Rosas usleep(2000000); 739*8a645544SFabiano Rosas 740*8a645544SFabiano Rosas /* 741*8a645544SFabiano Rosas * Check if dirtylimit take effect realistically, set the 742*8a645544SFabiano Rosas * timeout with 20 s(max_try_count * 1s), if dirtylimit 743*8a645544SFabiano Rosas * doesn't take effect, fail test. 744*8a645544SFabiano Rosas */ 745*8a645544SFabiano Rosas while (--max_try_count) { 746*8a645544SFabiano Rosas calc_dirty_rate(vm, 1); 747*8a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 748*8a645544SFabiano Rosas rate = get_dirty_rate(vm); 749*8a645544SFabiano Rosas 750*8a645544SFabiano Rosas /* 751*8a645544SFabiano Rosas * Assume hitting if current rate is less 752*8a645544SFabiano Rosas * than quota rate (within accepting error) 753*8a645544SFabiano Rosas */ 754*8a645544SFabiano Rosas if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) { 755*8a645544SFabiano Rosas hit = 1; 756*8a645544SFabiano Rosas break; 757*8a645544SFabiano Rosas } 758*8a645544SFabiano Rosas } 759*8a645544SFabiano Rosas 760*8a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 761*8a645544SFabiano Rosas 762*8a645544SFabiano Rosas hit = 0; 763*8a645544SFabiano Rosas max_try_count = 20; 764*8a645544SFabiano Rosas 765*8a645544SFabiano Rosas /* Check if dirtylimit cancellation take effect */ 766*8a645544SFabiano Rosas cancel_vcpu_dirty_limit(vm); 767*8a645544SFabiano Rosas while (--max_try_count) { 768*8a645544SFabiano Rosas calc_dirty_rate(vm, 1); 769*8a645544SFabiano Rosas wait_for_calc_dirtyrate_complete(vm, 1); 770*8a645544SFabiano Rosas rate = get_dirty_rate(vm); 771*8a645544SFabiano Rosas 772*8a645544SFabiano Rosas /* 773*8a645544SFabiano Rosas * Assume dirtylimit be canceled if current rate is 774*8a645544SFabiano Rosas * greater than quota rate (within accepting error) 775*8a645544SFabiano Rosas */ 776*8a645544SFabiano Rosas if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) { 777*8a645544SFabiano Rosas hit = 1; 778*8a645544SFabiano Rosas break; 779*8a645544SFabiano Rosas } 780*8a645544SFabiano Rosas } 781*8a645544SFabiano Rosas 782*8a645544SFabiano Rosas g_assert_cmpint(hit, ==, 1); 783*8a645544SFabiano Rosas dirtylimit_stop_vm(vm); 784*8a645544SFabiano Rosas } 785*8a645544SFabiano Rosas 786*8a645544SFabiano Rosas static void migrate_dirty_limit_wait_showup(QTestState *from, 787*8a645544SFabiano Rosas const int64_t period, 788*8a645544SFabiano Rosas const int64_t value) 789*8a645544SFabiano Rosas { 790*8a645544SFabiano Rosas /* Enable dirty limit capability */ 791*8a645544SFabiano Rosas migrate_set_capability(from, "dirty-limit", true); 792*8a645544SFabiano Rosas 793*8a645544SFabiano Rosas /* Set dirty limit parameters */ 794*8a645544SFabiano Rosas migrate_set_parameter_int(from, "x-vcpu-dirty-limit-period", period); 795*8a645544SFabiano Rosas migrate_set_parameter_int(from, "vcpu-dirty-limit", value); 796*8a645544SFabiano Rosas 797*8a645544SFabiano Rosas /* Make sure migrate can't converge */ 798*8a645544SFabiano Rosas migrate_ensure_non_converge(from); 799*8a645544SFabiano Rosas 800*8a645544SFabiano Rosas /* To check limit rate after precopy */ 801*8a645544SFabiano Rosas migrate_set_capability(from, "pause-before-switchover", true); 802*8a645544SFabiano Rosas 803*8a645544SFabiano Rosas /* Wait for the serial output from the source */ 804*8a645544SFabiano Rosas wait_for_serial("src_serial"); 805*8a645544SFabiano Rosas } 806*8a645544SFabiano Rosas 807*8a645544SFabiano Rosas /* 808*8a645544SFabiano Rosas * This test does: 809*8a645544SFabiano Rosas * source destination 810*8a645544SFabiano Rosas * start vm 811*8a645544SFabiano Rosas * start incoming vm 812*8a645544SFabiano Rosas * migrate 813*8a645544SFabiano Rosas * wait dirty limit to begin 814*8a645544SFabiano Rosas * cancel migrate 815*8a645544SFabiano Rosas * cancellation check 816*8a645544SFabiano Rosas * restart incoming vm 817*8a645544SFabiano Rosas * migrate 818*8a645544SFabiano Rosas * wait dirty limit to begin 819*8a645544SFabiano Rosas * wait pre-switchover event 820*8a645544SFabiano Rosas * convergence condition check 821*8a645544SFabiano Rosas * 822*8a645544SFabiano Rosas * And see if dirty limit migration works correctly. 823*8a645544SFabiano Rosas * This test case involves many passes, so it runs in slow mode only. 824*8a645544SFabiano Rosas */ 825*8a645544SFabiano Rosas static void test_dirty_limit(void) 826*8a645544SFabiano Rosas { 827*8a645544SFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 828*8a645544SFabiano Rosas QTestState *from, *to; 829*8a645544SFabiano Rosas int64_t remaining; 830*8a645544SFabiano Rosas uint64_t throttle_us_per_full; 831*8a645544SFabiano Rosas /* 832*8a645544SFabiano Rosas * We want the test to be stable and as fast as possible. 833*8a645544SFabiano Rosas * E.g., with 1Gb/s bandwidth migration may pass without dirty limit, 834*8a645544SFabiano Rosas * so we need to decrease a bandwidth. 835*8a645544SFabiano Rosas */ 836*8a645544SFabiano Rosas const int64_t dirtylimit_period = 1000, dirtylimit_value = 50; 837*8a645544SFabiano Rosas const int64_t max_bandwidth = 400000000; /* ~400Mb/s */ 838*8a645544SFabiano Rosas const int64_t downtime_limit = 250; /* 250ms */ 839*8a645544SFabiano Rosas /* 840*8a645544SFabiano Rosas * We migrate through unix-socket (> 500Mb/s). 841*8a645544SFabiano Rosas * Thus, expected migration speed ~= bandwidth limit (< 500Mb/s). 842*8a645544SFabiano Rosas * So, we can predict expected_threshold 843*8a645544SFabiano Rosas */ 844*8a645544SFabiano Rosas const int64_t expected_threshold = max_bandwidth * downtime_limit / 1000; 845*8a645544SFabiano Rosas int max_try_count = 10; 846*8a645544SFabiano Rosas MigrateCommon args = { 847*8a645544SFabiano Rosas .start = { 848*8a645544SFabiano Rosas .hide_stderr = true, 849*8a645544SFabiano Rosas .use_dirty_ring = true, 850*8a645544SFabiano Rosas }, 851*8a645544SFabiano Rosas .listen_uri = uri, 852*8a645544SFabiano Rosas .connect_uri = uri, 853*8a645544SFabiano Rosas }; 854*8a645544SFabiano Rosas 855*8a645544SFabiano Rosas /* Start src, dst vm */ 856*8a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) { 857*8a645544SFabiano Rosas return; 858*8a645544SFabiano Rosas } 859*8a645544SFabiano Rosas 860*8a645544SFabiano Rosas /* Prepare for dirty limit migration and wait src vm show up */ 861*8a645544SFabiano Rosas migrate_dirty_limit_wait_showup(from, dirtylimit_period, dirtylimit_value); 862*8a645544SFabiano Rosas 863*8a645544SFabiano Rosas /* Start migrate */ 864*8a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}"); 865*8a645544SFabiano Rosas 866*8a645544SFabiano Rosas /* Wait for dirty limit throttle begin */ 867*8a645544SFabiano Rosas throttle_us_per_full = 0; 868*8a645544SFabiano Rosas while (throttle_us_per_full == 0) { 869*8a645544SFabiano Rosas throttle_us_per_full = 870*8a645544SFabiano Rosas read_migrate_property_int(from, 871*8a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 872*8a645544SFabiano Rosas usleep(100); 873*8a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 874*8a645544SFabiano Rosas } 875*8a645544SFabiano Rosas 876*8a645544SFabiano Rosas /* Now cancel migrate and wait for dirty limit throttle switch off */ 877*8a645544SFabiano Rosas migrate_cancel(from); 878*8a645544SFabiano Rosas wait_for_migration_status(from, "cancelled", NULL); 879*8a645544SFabiano Rosas 880*8a645544SFabiano Rosas /* Check if dirty limit throttle switched off, set timeout 1ms */ 881*8a645544SFabiano Rosas do { 882*8a645544SFabiano Rosas throttle_us_per_full = 883*8a645544SFabiano Rosas read_migrate_property_int(from, 884*8a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 885*8a645544SFabiano Rosas usleep(100); 886*8a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 887*8a645544SFabiano Rosas } while (throttle_us_per_full != 0 && --max_try_count); 888*8a645544SFabiano Rosas 889*8a645544SFabiano Rosas /* Assert dirty limit is not in service */ 890*8a645544SFabiano Rosas g_assert_cmpint(throttle_us_per_full, ==, 0); 891*8a645544SFabiano Rosas 892*8a645544SFabiano Rosas args = (MigrateCommon) { 893*8a645544SFabiano Rosas .start = { 894*8a645544SFabiano Rosas .only_target = true, 895*8a645544SFabiano Rosas .use_dirty_ring = true, 896*8a645544SFabiano Rosas }, 897*8a645544SFabiano Rosas .listen_uri = uri, 898*8a645544SFabiano Rosas .connect_uri = uri, 899*8a645544SFabiano Rosas }; 900*8a645544SFabiano Rosas 901*8a645544SFabiano Rosas /* Restart dst vm, src vm already show up so we needn't wait anymore */ 902*8a645544SFabiano Rosas if (migrate_start(&from, &to, args.listen_uri, &args.start)) { 903*8a645544SFabiano Rosas return; 904*8a645544SFabiano Rosas } 905*8a645544SFabiano Rosas 906*8a645544SFabiano Rosas /* Start migrate */ 907*8a645544SFabiano Rosas migrate_qmp(from, to, args.connect_uri, NULL, "{}"); 908*8a645544SFabiano Rosas 909*8a645544SFabiano Rosas /* Wait for dirty limit throttle begin */ 910*8a645544SFabiano Rosas throttle_us_per_full = 0; 911*8a645544SFabiano Rosas while (throttle_us_per_full == 0) { 912*8a645544SFabiano Rosas throttle_us_per_full = 913*8a645544SFabiano Rosas read_migrate_property_int(from, 914*8a645544SFabiano Rosas "dirty-limit-throttle-time-per-round"); 915*8a645544SFabiano Rosas usleep(100); 916*8a645544SFabiano Rosas g_assert_false(get_src()->stop_seen); 917*8a645544SFabiano Rosas } 918*8a645544SFabiano Rosas 919*8a645544SFabiano Rosas /* 920*8a645544SFabiano Rosas * The dirty limit rate should equals the return value of 921*8a645544SFabiano Rosas * query-vcpu-dirty-limit if dirty limit cap set 922*8a645544SFabiano Rosas */ 923*8a645544SFabiano Rosas g_assert_cmpint(dirtylimit_value, ==, get_limit_rate(from)); 924*8a645544SFabiano Rosas 925*8a645544SFabiano Rosas /* Now, we have tested if dirty limit works, let it converge */ 926*8a645544SFabiano Rosas migrate_set_parameter_int(from, "downtime-limit", downtime_limit); 927*8a645544SFabiano Rosas migrate_set_parameter_int(from, "max-bandwidth", max_bandwidth); 928*8a645544SFabiano Rosas 929*8a645544SFabiano Rosas /* 930*8a645544SFabiano Rosas * Wait for pre-switchover status to check if migration 931*8a645544SFabiano Rosas * satisfy the convergence condition 932*8a645544SFabiano Rosas */ 933*8a645544SFabiano Rosas wait_for_migration_status(from, "pre-switchover", NULL); 934*8a645544SFabiano Rosas 935*8a645544SFabiano Rosas remaining = read_ram_property_int(from, "remaining"); 936*8a645544SFabiano Rosas g_assert_cmpint(remaining, <, 937*8a645544SFabiano Rosas (expected_threshold + expected_threshold / 100)); 938*8a645544SFabiano Rosas 939*8a645544SFabiano Rosas migrate_continue(from, "pre-switchover"); 940*8a645544SFabiano Rosas 941*8a645544SFabiano Rosas qtest_qmp_eventwait(to, "RESUME"); 942*8a645544SFabiano Rosas 943*8a645544SFabiano Rosas wait_for_serial("dest_serial"); 944*8a645544SFabiano Rosas wait_for_migration_complete(from); 945*8a645544SFabiano Rosas 946*8a645544SFabiano Rosas migrate_end(from, to, true); 947*8a645544SFabiano Rosas } 948*8a645544SFabiano Rosas 949*8a645544SFabiano Rosas void migration_test_add_precopy(MigrationTestEnv *env) 950*8a645544SFabiano Rosas { 951*8a645544SFabiano Rosas tmpfs = env->tmpfs; 952*8a645544SFabiano Rosas 953*8a645544SFabiano Rosas if (env->is_x86) { 954*8a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/live", 955*8a645544SFabiano Rosas test_precopy_unix_suspend_live); 956*8a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/notlive", 957*8a645544SFabiano Rosas test_precopy_unix_suspend_notlive); 958*8a645544SFabiano Rosas } 959*8a645544SFabiano Rosas 960*8a645544SFabiano Rosas migration_test_add("/migration/precopy/unix/plain", 961*8a645544SFabiano Rosas test_precopy_unix_plain); 962*8a645544SFabiano Rosas 963*8a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain", test_precopy_tcp_plain); 964*8a645544SFabiano Rosas 965*8a645544SFabiano Rosas migration_test_add("/migration/precopy/tcp/plain/switchover-ack", 966*8a645544SFabiano Rosas test_precopy_tcp_switchover_ack); 967*8a645544SFabiano Rosas 968*8a645544SFabiano Rosas #ifndef _WIN32 969*8a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/tcp", 970*8a645544SFabiano Rosas test_precopy_fd_socket); 971*8a645544SFabiano Rosas migration_test_add("/migration/precopy/fd/file", 972*8a645544SFabiano Rosas test_precopy_fd_file); 973*8a645544SFabiano Rosas #endif 974*8a645544SFabiano Rosas 975*8a645544SFabiano Rosas /* 976*8a645544SFabiano Rosas * See explanation why this test is slow on function definition 977*8a645544SFabiano Rosas */ 978*8a645544SFabiano Rosas if (g_test_slow()) { 979*8a645544SFabiano Rosas migration_test_add("/migration/auto_converge", 980*8a645544SFabiano Rosas test_auto_converge); 981*8a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64") && 982*8a645544SFabiano Rosas env->has_kvm && env->has_dirty_ring) { 983*8a645544SFabiano Rosas migration_test_add("/dirty_limit", 984*8a645544SFabiano Rosas test_dirty_limit); 985*8a645544SFabiano Rosas } 986*8a645544SFabiano Rosas } 987*8a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/uri/plain/none", 988*8a645544SFabiano Rosas test_multifd_tcp_uri_none); 989*8a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/channels/plain/none", 990*8a645544SFabiano Rosas test_multifd_tcp_channels_none); 991*8a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/legacy", 992*8a645544SFabiano Rosas test_multifd_tcp_zero_page_legacy); 993*8a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zero-page/none", 994*8a645544SFabiano Rosas test_multifd_tcp_no_zero_page); 995*8a645544SFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/cancel", 996*8a645544SFabiano Rosas test_multifd_tcp_cancel); 997*8a645544SFabiano Rosas if (g_str_equal(env->arch, "x86_64") 998*8a645544SFabiano Rosas && env->has_kvm && env->has_dirty_ring) { 999*8a645544SFabiano Rosas 1000*8a645544SFabiano Rosas migration_test_add("/migration/dirty_ring", 1001*8a645544SFabiano Rosas test_precopy_unix_dirty_ring); 1002*8a645544SFabiano Rosas if (qtest_has_machine("pc") && g_test_slow()) { 1003*8a645544SFabiano Rosas migration_test_add("/migration/vcpu_dirty_limit", 1004*8a645544SFabiano Rosas test_vcpu_dirty_limit); 1005*8a645544SFabiano Rosas } 1006*8a645544SFabiano Rosas } 1007*8a645544SFabiano Rosas } 1008