11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth * QTest testcase for migration
31e8a1faeSThomas Huth *
41e8a1faeSThomas Huth * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
51e8a1faeSThomas Huth * based on the vhost-user-test.c that is:
61e8a1faeSThomas Huth * Copyright (c) 2014 Virtual Open Systems Sarl.
71e8a1faeSThomas Huth *
81e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later.
91e8a1faeSThomas Huth * See the COPYING file in the top-level directory.
101e8a1faeSThomas Huth *
111e8a1faeSThomas Huth */
121e8a1faeSThomas Huth
131e8a1faeSThomas Huth #include "qemu/osdep.h"
141e8a1faeSThomas Huth
15907b5105SMarc-André Lureau #include "libqtest.h"
161e8a1faeSThomas Huth #include "qapi/qmp/qdict.h"
171e8a1faeSThomas Huth #include "qemu/module.h"
181e8a1faeSThomas Huth #include "qemu/option.h"
191e8a1faeSThomas Huth #include "qemu/range.h"
201e8a1faeSThomas Huth #include "qemu/sockets.h"
211e8a1faeSThomas Huth #include "chardev/char.h"
2258d25e97SDaniel P. Berrangé #include "crypto/tlscredspsk.h"
238aff6f50SHyman Huang(黄勇) #include "qapi/qmp/qlist.h"
24ea6ce910SNicholas Piggin #include "ppc-util.h"
251e8a1faeSThomas Huth
261e8a1faeSThomas Huth #include "migration-helpers.h"
27a2ce7dbdSPaolo Bonzini #include "tests/migration/migration-test.h"
2858d25e97SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
2958d25e97SDaniel P. Berrangé # include "tests/unit/crypto-tls-psk-helpers.h"
30d47b83b1SDaniel P. Berrangé # ifdef CONFIG_TASN1
31d47b83b1SDaniel P. Berrangé # include "tests/unit/crypto-tls-x509-helpers.h"
32d47b83b1SDaniel P. Berrangé # endif /* CONFIG_TASN1 */
3358d25e97SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
341e8a1faeSThomas Huth
3561c32485SPeter Xu /* For dirty ring test; so far only x86_64 is supported */
3661c32485SPeter Xu #if defined(__linux__) && defined(HOST_X86_64)
371f546b70SPeter Xu #include "linux/kvm.h"
381f546b70SPeter Xu #endif
391f546b70SPeter Xu
401e8a1faeSThomas Huth unsigned start_address;
411e8a1faeSThomas Huth unsigned end_address;
421e8a1faeSThomas Huth static bool uffd_feature_thread_id;
43f0649758SSteve Sistare static QTestMigrationState src_state;
44f0649758SSteve Sistare static QTestMigrationState dst_state;
451e8a1faeSThomas Huth
468aff6f50SHyman Huang(黄勇) /*
47e02f56e3SDaniel P. Berrangé * An initial 3 MB offset is used as that corresponds
48e02f56e3SDaniel P. Berrangé * to ~1 sec of data transfer with our bandwidth setting.
49e02f56e3SDaniel P. Berrangé */
50e02f56e3SDaniel P. Berrangé #define MAGIC_OFFSET_BASE (3 * 1024 * 1024)
51e02f56e3SDaniel P. Berrangé /*
52e02f56e3SDaniel P. Berrangé * A further 1k is added to ensure we're not a multiple
53e02f56e3SDaniel P. Berrangé * of TEST_MEM_PAGE_SIZE, thus avoid clash with writes
54e02f56e3SDaniel P. Berrangé * from the migration guest workload.
55e02f56e3SDaniel P. Berrangé */
56e02f56e3SDaniel P. Berrangé #define MAGIC_OFFSET_SHUFFLE 1024
57e02f56e3SDaniel P. Berrangé #define MAGIC_OFFSET (MAGIC_OFFSET_BASE + MAGIC_OFFSET_SHUFFLE)
58e02f56e3SDaniel P. Berrangé #define MAGIC_MARKER 0xFEED12345678CAFEULL
59e02f56e3SDaniel P. Berrangé
60e02f56e3SDaniel P. Berrangé /*
618aff6f50SHyman Huang(黄勇) * Dirtylimit stop working if dirty page rate error
628aff6f50SHyman Huang(黄勇) * value less than DIRTYLIMIT_TOLERANCE_RANGE
638aff6f50SHyman Huang(黄勇) */
648aff6f50SHyman Huang(黄勇) #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */
658aff6f50SHyman Huang(黄勇)
66d864756eSFabiano Rosas #define ANALYZE_SCRIPT "scripts/analyze-migration.py"
67d864756eSFabiano Rosas
683dc35470SFabiano Rosas #define QEMU_VM_FILE_MAGIC 0x5145564d
693dc35470SFabiano Rosas #define FILE_TEST_FILENAME "migfile"
703dc35470SFabiano Rosas #define FILE_TEST_OFFSET 0x1000
7155fc0c2fSFabiano Rosas #define FILE_TEST_MARKER 'X'
725050ad2aSFabiano Rosas #define QEMU_ENV_SRC "QTEST_QEMU_BINARY_SRC"
735050ad2aSFabiano Rosas #define QEMU_ENV_DST "QTEST_QEMU_BINARY_DST"
743dc35470SFabiano Rosas
756cf56a87SPeter Xu typedef enum PostcopyRecoveryFailStage {
766cf56a87SPeter Xu /*
776cf56a87SPeter Xu * "no failure" must be 0 as it's the default. OTOH, real failure
786cf56a87SPeter Xu * cases must be >0 to make sure they trigger by a "if" test.
796cf56a87SPeter Xu */
806cf56a87SPeter Xu POSTCOPY_FAIL_NONE = 0,
816cf56a87SPeter Xu POSTCOPY_FAIL_CHANNEL_ESTABLISH,
826cf56a87SPeter Xu POSTCOPY_FAIL_RECOVERY,
836cf56a87SPeter Xu POSTCOPY_FAIL_MAX
846cf56a87SPeter Xu } PostcopyRecoveryFailStage;
856cf56a87SPeter Xu
861e8a1faeSThomas Huth #if defined(__linux__)
871e8a1faeSThomas Huth #include <sys/syscall.h>
881e8a1faeSThomas Huth #include <sys/vfs.h>
891e8a1faeSThomas Huth #endif
901e8a1faeSThomas Huth
911e8a1faeSThomas Huth #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
921e8a1faeSThomas Huth #include <sys/eventfd.h>
931e8a1faeSThomas Huth #include <sys/ioctl.h>
94d5890ea0SPeter Xu #include "qemu/userfaultfd.h"
951e8a1faeSThomas Huth
ufd_version_check(void)961e8a1faeSThomas Huth static bool ufd_version_check(void)
971e8a1faeSThomas Huth {
981e8a1faeSThomas Huth struct uffdio_api api_struct;
991e8a1faeSThomas Huth uint64_t ioctl_mask;
1001e8a1faeSThomas Huth
101d5890ea0SPeter Xu int ufd = uffd_open(O_CLOEXEC);
1021e8a1faeSThomas Huth
1031e8a1faeSThomas Huth if (ufd == -1) {
1041e8a1faeSThomas Huth g_test_message("Skipping test: userfaultfd not available");
1051e8a1faeSThomas Huth return false;
1061e8a1faeSThomas Huth }
1071e8a1faeSThomas Huth
1081e8a1faeSThomas Huth api_struct.api = UFFD_API;
1091e8a1faeSThomas Huth api_struct.features = 0;
1101e8a1faeSThomas Huth if (ioctl(ufd, UFFDIO_API, &api_struct)) {
1111e8a1faeSThomas Huth g_test_message("Skipping test: UFFDIO_API failed");
1121e8a1faeSThomas Huth return false;
1131e8a1faeSThomas Huth }
1141e8a1faeSThomas Huth uffd_feature_thread_id = api_struct.features & UFFD_FEATURE_THREAD_ID;
1151e8a1faeSThomas Huth
116*19e56616SFabiano Rosas ioctl_mask = (1ULL << _UFFDIO_REGISTER |
117*19e56616SFabiano Rosas 1ULL << _UFFDIO_UNREGISTER);
1181e8a1faeSThomas Huth if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
1191e8a1faeSThomas Huth g_test_message("Skipping test: Missing userfault feature");
1201e8a1faeSThomas Huth return false;
1211e8a1faeSThomas Huth }
1221e8a1faeSThomas Huth
1231e8a1faeSThomas Huth return true;
1241e8a1faeSThomas Huth }
1251e8a1faeSThomas Huth
1261e8a1faeSThomas Huth #else
ufd_version_check(void)1271e8a1faeSThomas Huth static bool ufd_version_check(void)
1281e8a1faeSThomas Huth {
1291e8a1faeSThomas Huth g_test_message("Skipping test: Userfault not available (builtdtime)");
1301e8a1faeSThomas Huth return false;
1311e8a1faeSThomas Huth }
1321e8a1faeSThomas Huth
1331e8a1faeSThomas Huth #endif
1341e8a1faeSThomas Huth
135e5553c1bSBin Meng static char *tmpfs;
136877cec63SJuan Quintela static char *bootpath;
1371e8a1faeSThomas Huth
1381e8a1faeSThomas Huth /* The boot file modifies memory area in [start_address, end_address)
1391e8a1faeSThomas Huth * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
1401e8a1faeSThomas Huth */
1411e8a1faeSThomas Huth #include "tests/migration/i386/a-b-bootblock.h"
1421e8a1faeSThomas Huth #include "tests/migration/aarch64/a-b-kernel.h"
14334cc54fbSNicholas Piggin #include "tests/migration/ppc64/a-b-kernel.h"
1441e8a1faeSThomas Huth #include "tests/migration/s390x/a-b-bios.h"
1451e8a1faeSThomas Huth
bootfile_delete(void)146aee07f25SAkihiko Odaki static void bootfile_delete(void)
147aee07f25SAkihiko Odaki {
148d278455eSPeter Maydell if (!bootpath) {
149d278455eSPeter Maydell return;
150d278455eSPeter Maydell }
151aee07f25SAkihiko Odaki unlink(bootpath);
152aee07f25SAkihiko Odaki g_free(bootpath);
153aee07f25SAkihiko Odaki bootpath = NULL;
154aee07f25SAkihiko Odaki }
155aee07f25SAkihiko Odaki
bootfile_create(char * dir,bool suspend_me)1565014478eSSteve Sistare static void bootfile_create(char *dir, bool suspend_me)
1571e8a1faeSThomas Huth {
1580c690d3eSJuan Quintela const char *arch = qtest_get_arch();
1590c690d3eSJuan Quintela unsigned char *content;
1600c690d3eSJuan Quintela size_t len;
1610c690d3eSJuan Quintela
162aee07f25SAkihiko Odaki bootfile_delete();
1630c690d3eSJuan Quintela bootpath = g_strdup_printf("%s/bootsect", dir);
1640c690d3eSJuan Quintela if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
1650c690d3eSJuan Quintela /* the assembled x86 boot sector should be exactly one sector large */
1660c690d3eSJuan Quintela g_assert(sizeof(x86_bootsect) == 512);
1675014478eSSteve Sistare x86_bootsect[SYM_suspend_me - SYM_start] = suspend_me;
1680c690d3eSJuan Quintela content = x86_bootsect;
1690c690d3eSJuan Quintela len = sizeof(x86_bootsect);
1700c690d3eSJuan Quintela } else if (g_str_equal(arch, "s390x")) {
1710c690d3eSJuan Quintela content = s390x_elf;
1720c690d3eSJuan Quintela len = sizeof(s390x_elf);
1730c690d3eSJuan Quintela } else if (strcmp(arch, "ppc64") == 0) {
17434cc54fbSNicholas Piggin content = ppc64_kernel;
17534cc54fbSNicholas Piggin len = sizeof(ppc64_kernel);
1760c690d3eSJuan Quintela } else if (strcmp(arch, "aarch64") == 0) {
1770c690d3eSJuan Quintela content = aarch64_kernel;
1780c690d3eSJuan Quintela len = sizeof(aarch64_kernel);
1790c690d3eSJuan Quintela g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
1800c690d3eSJuan Quintela } else {
1810c690d3eSJuan Quintela g_assert_not_reached();
1820c690d3eSJuan Quintela }
1830c690d3eSJuan Quintela
1841e8a1faeSThomas Huth FILE *bootfile = fopen(bootpath, "wb");
1851e8a1faeSThomas Huth
1861e8a1faeSThomas Huth g_assert_cmpint(fwrite(content, len, 1, bootfile), ==, 1);
1871e8a1faeSThomas Huth fclose(bootfile);
1881e8a1faeSThomas Huth }
1891e8a1faeSThomas Huth
1901e8a1faeSThomas Huth /*
1911e8a1faeSThomas Huth * Wait for some output in the serial output file,
1921e8a1faeSThomas Huth * we get an 'A' followed by an endless string of 'B's
193b1fdd21eSSteve Sistare * but on the destination we won't have the A (unless we enabled suspend/resume)
1941e8a1faeSThomas Huth */
wait_for_serial(const char * side)1951e8a1faeSThomas Huth static void wait_for_serial(const char *side)
1961e8a1faeSThomas Huth {
197ff7b9b56SPeter Maydell g_autofree char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
1981e8a1faeSThomas Huth FILE *serialfile = fopen(serialpath, "r");
1991e8a1faeSThomas Huth
2001e8a1faeSThomas Huth do {
2011e8a1faeSThomas Huth int readvalue = fgetc(serialfile);
2021e8a1faeSThomas Huth
2031e8a1faeSThomas Huth switch (readvalue) {
2041e8a1faeSThomas Huth case 'A':
2051e8a1faeSThomas Huth /* Fine */
2061e8a1faeSThomas Huth break;
2071e8a1faeSThomas Huth
2081e8a1faeSThomas Huth case 'B':
2091e8a1faeSThomas Huth /* It's alive! */
2101e8a1faeSThomas Huth fclose(serialfile);
2111e8a1faeSThomas Huth return;
2121e8a1faeSThomas Huth
2131e8a1faeSThomas Huth case EOF:
2141e8a1faeSThomas Huth fseek(serialfile, 0, SEEK_SET);
2151e8a1faeSThomas Huth usleep(1000);
2161e8a1faeSThomas Huth break;
2171e8a1faeSThomas Huth
2181e8a1faeSThomas Huth default:
2191e8a1faeSThomas Huth fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
2201e8a1faeSThomas Huth g_assert_not_reached();
2211e8a1faeSThomas Huth }
2221e8a1faeSThomas Huth } while (true);
2231e8a1faeSThomas Huth }
2241e8a1faeSThomas Huth
wait_for_stop(QTestState * who,QTestMigrationState * state)225f0649758SSteve Sistare static void wait_for_stop(QTestState *who, QTestMigrationState *state)
226f0649758SSteve Sistare {
227f0649758SSteve Sistare if (!state->stop_seen) {
228f0649758SSteve Sistare qtest_qmp_eventwait(who, "STOP");
229f0649758SSteve Sistare }
230f0649758SSteve Sistare }
231f0649758SSteve Sistare
wait_for_resume(QTestState * who,QTestMigrationState * state)232f0649758SSteve Sistare static void wait_for_resume(QTestState *who, QTestMigrationState *state)
233f0649758SSteve Sistare {
234f0649758SSteve Sistare if (!state->resume_seen) {
235f0649758SSteve Sistare qtest_qmp_eventwait(who, "RESUME");
236f0649758SSteve Sistare }
237f0649758SSteve Sistare }
238f0649758SSteve Sistare
wait_for_suspend(QTestState * who,QTestMigrationState * state)239b1fdd21eSSteve Sistare static void wait_for_suspend(QTestState *who, QTestMigrationState *state)
240b1fdd21eSSteve Sistare {
241b1fdd21eSSteve Sistare if (state->suspend_me && !state->suspend_seen) {
242b1fdd21eSSteve Sistare qtest_qmp_eventwait(who, "SUSPEND");
243b1fdd21eSSteve Sistare }
244b1fdd21eSSteve Sistare }
245b1fdd21eSSteve Sistare
2461e8a1faeSThomas Huth /*
2471e8a1faeSThomas Huth * It's tricky to use qemu's migration event capability with qtest,
2481e8a1faeSThomas Huth * events suddenly appearing confuse the qmp()/hmp() responses.
2491e8a1faeSThomas Huth */
2501e8a1faeSThomas Huth
read_ram_property_int(QTestState * who,const char * property)2511e8a1faeSThomas Huth static int64_t read_ram_property_int(QTestState *who, const char *property)
2521e8a1faeSThomas Huth {
2531e8a1faeSThomas Huth QDict *rsp_return, *rsp_ram;
2541e8a1faeSThomas Huth int64_t result;
2551e8a1faeSThomas Huth
256fd3540adSDaniel P. Berrangé rsp_return = migrate_query_not_failed(who);
2571e8a1faeSThomas Huth if (!qdict_haskey(rsp_return, "ram")) {
2581e8a1faeSThomas Huth /* Still in setup */
2591e8a1faeSThomas Huth result = 0;
2601e8a1faeSThomas Huth } else {
2611e8a1faeSThomas Huth rsp_ram = qdict_get_qdict(rsp_return, "ram");
2621e8a1faeSThomas Huth result = qdict_get_try_int(rsp_ram, property, 0);
2631e8a1faeSThomas Huth }
2641e8a1faeSThomas Huth qobject_unref(rsp_return);
2651e8a1faeSThomas Huth return result;
2661e8a1faeSThomas Huth }
2671e8a1faeSThomas Huth
read_migrate_property_int(QTestState * who,const char * property)2681e8a1faeSThomas Huth static int64_t read_migrate_property_int(QTestState *who, const char *property)
2691e8a1faeSThomas Huth {
2701e8a1faeSThomas Huth QDict *rsp_return;
2711e8a1faeSThomas Huth int64_t result;
2721e8a1faeSThomas Huth
273fd3540adSDaniel P. Berrangé rsp_return = migrate_query_not_failed(who);
2741e8a1faeSThomas Huth result = qdict_get_try_int(rsp_return, property, 0);
2751e8a1faeSThomas Huth qobject_unref(rsp_return);
2761e8a1faeSThomas Huth return result;
2771e8a1faeSThomas Huth }
2781e8a1faeSThomas Huth
get_migration_pass(QTestState * who)2791e8a1faeSThomas Huth static uint64_t get_migration_pass(QTestState *who)
2801e8a1faeSThomas Huth {
2811e8a1faeSThomas Huth return read_ram_property_int(who, "dirty-sync-count");
2821e8a1faeSThomas Huth }
2831e8a1faeSThomas Huth
read_blocktime(QTestState * who)2841e8a1faeSThomas Huth static void read_blocktime(QTestState *who)
2851e8a1faeSThomas Huth {
2861e8a1faeSThomas Huth QDict *rsp_return;
2871e8a1faeSThomas Huth
288fd3540adSDaniel P. Berrangé rsp_return = migrate_query_not_failed(who);
2891e8a1faeSThomas Huth g_assert(qdict_haskey(rsp_return, "postcopy-blocktime"));
2901e8a1faeSThomas Huth qobject_unref(rsp_return);
2911e8a1faeSThomas Huth }
2921e8a1faeSThomas Huth
293f0649758SSteve Sistare /*
294f0649758SSteve Sistare * Wait for two changes in the migration pass count, but bail if we stop.
295f0649758SSteve Sistare */
wait_for_migration_pass(QTestState * who)2961e8a1faeSThomas Huth static void wait_for_migration_pass(QTestState *who)
2971e8a1faeSThomas Huth {
298f0649758SSteve Sistare uint64_t pass, prev_pass = 0, changes = 0;
2991e8a1faeSThomas Huth
300b1fdd21eSSteve Sistare while (changes < 2 && !src_state.stop_seen && !src_state.suspend_seen) {
3011e8a1faeSThomas Huth usleep(1000);
3021e8a1faeSThomas Huth pass = get_migration_pass(who);
303f0649758SSteve Sistare changes += (pass != prev_pass);
304f0649758SSteve Sistare prev_pass = pass;
305f0649758SSteve Sistare }
3061e8a1faeSThomas Huth }
3071e8a1faeSThomas Huth
check_guests_ram(QTestState * who)3081e8a1faeSThomas Huth static void check_guests_ram(QTestState *who)
3091e8a1faeSThomas Huth {
3101e8a1faeSThomas Huth /* Our ASM test will have been incrementing one byte from each page from
3111e8a1faeSThomas Huth * start_address to < end_address in order. This gives us a constraint
3121e8a1faeSThomas Huth * that any page's byte should be equal or less than the previous pages
3131e8a1faeSThomas Huth * byte (mod 256); and they should all be equal except for one transition
3141e8a1faeSThomas Huth * at the point where we meet the incrementer. (We're running this with
3151e8a1faeSThomas Huth * the guest stopped).
3161e8a1faeSThomas Huth */
3171e8a1faeSThomas Huth unsigned address;
3181e8a1faeSThomas Huth uint8_t first_byte;
3191e8a1faeSThomas Huth uint8_t last_byte;
3201e8a1faeSThomas Huth bool hit_edge = false;
3211e8a1faeSThomas Huth int bad = 0;
3221e8a1faeSThomas Huth
3231e8a1faeSThomas Huth qtest_memread(who, start_address, &first_byte, 1);
3241e8a1faeSThomas Huth last_byte = first_byte;
3251e8a1faeSThomas Huth
3261e8a1faeSThomas Huth for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
3271e8a1faeSThomas Huth address += TEST_MEM_PAGE_SIZE)
3281e8a1faeSThomas Huth {
3291e8a1faeSThomas Huth uint8_t b;
3301e8a1faeSThomas Huth qtest_memread(who, address, &b, 1);
3311e8a1faeSThomas Huth if (b != last_byte) {
3321e8a1faeSThomas Huth if (((b + 1) % 256) == last_byte && !hit_edge) {
3331e8a1faeSThomas Huth /* This is OK, the guest stopped at the point of
3341e8a1faeSThomas Huth * incrementing the previous page but didn't get
3351e8a1faeSThomas Huth * to us yet.
3361e8a1faeSThomas Huth */
3371e8a1faeSThomas Huth hit_edge = true;
3381e8a1faeSThomas Huth last_byte = b;
3391e8a1faeSThomas Huth } else {
3401e8a1faeSThomas Huth bad++;
3411e8a1faeSThomas Huth if (bad <= 10) {
3421e8a1faeSThomas Huth fprintf(stderr, "Memory content inconsistency at %x"
3431e8a1faeSThomas Huth " first_byte = %x last_byte = %x current = %x"
3441e8a1faeSThomas Huth " hit_edge = %x\n",
3451e8a1faeSThomas Huth address, first_byte, last_byte, b, hit_edge);
3461e8a1faeSThomas Huth }
3471e8a1faeSThomas Huth }
3481e8a1faeSThomas Huth }
3491e8a1faeSThomas Huth }
3501e8a1faeSThomas Huth if (bad >= 10) {
3511e8a1faeSThomas Huth fprintf(stderr, "and in another %d pages", bad - 10);
3521e8a1faeSThomas Huth }
3531e8a1faeSThomas Huth g_assert(bad == 0);
3541e8a1faeSThomas Huth }
3551e8a1faeSThomas Huth
cleanup(const char * filename)3561e8a1faeSThomas Huth static void cleanup(const char *filename)
3571e8a1faeSThomas Huth {
358ff7b9b56SPeter Maydell g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, filename);
3591e8a1faeSThomas Huth
3601e8a1faeSThomas Huth unlink(path);
3611e8a1faeSThomas Huth }
3621e8a1faeSThomas Huth
migrate_get_parameter_int(QTestState * who,const char * parameter)3631e8a1faeSThomas Huth static long long migrate_get_parameter_int(QTestState *who,
3641e8a1faeSThomas Huth const char *parameter)
3651e8a1faeSThomas Huth {
3661e8a1faeSThomas Huth QDict *rsp;
3671e8a1faeSThomas Huth long long result;
3681e8a1faeSThomas Huth
369aca04069SDaniel P. Berrangé rsp = qtest_qmp_assert_success_ref(
370aca04069SDaniel P. Berrangé who, "{ 'execute': 'query-migrate-parameters' }");
3711e8a1faeSThomas Huth result = qdict_get_int(rsp, parameter);
3721e8a1faeSThomas Huth qobject_unref(rsp);
3731e8a1faeSThomas Huth return result;
3741e8a1faeSThomas Huth }
3751e8a1faeSThomas Huth
migrate_check_parameter_int(QTestState * who,const char * parameter,long long value)3761e8a1faeSThomas Huth static void migrate_check_parameter_int(QTestState *who, const char *parameter,
3771e8a1faeSThomas Huth long long value)
3781e8a1faeSThomas Huth {
3791e8a1faeSThomas Huth long long result;
3801e8a1faeSThomas Huth
3811e8a1faeSThomas Huth result = migrate_get_parameter_int(who, parameter);
3821e8a1faeSThomas Huth g_assert_cmpint(result, ==, value);
3831e8a1faeSThomas Huth }
3841e8a1faeSThomas Huth
migrate_set_parameter_int(QTestState * who,const char * parameter,long long value)3851e8a1faeSThomas Huth static void migrate_set_parameter_int(QTestState *who, const char *parameter,
3861e8a1faeSThomas Huth long long value)
3871e8a1faeSThomas Huth {
38811936f0eSDaniel P. Berrangé qtest_qmp_assert_success(who,
3891e8a1faeSThomas Huth "{ 'execute': 'migrate-set-parameters',"
3901e8a1faeSThomas Huth "'arguments': { %s: %lld } }",
3911e8a1faeSThomas Huth parameter, value);
3921e8a1faeSThomas Huth migrate_check_parameter_int(who, parameter, value);
3931e8a1faeSThomas Huth }
3941e8a1faeSThomas Huth
migrate_get_parameter_str(QTestState * who,const char * parameter)3956a22c544SJuan Quintela static char *migrate_get_parameter_str(QTestState *who,
3966a22c544SJuan Quintela const char *parameter)
3976a22c544SJuan Quintela {
3986a22c544SJuan Quintela QDict *rsp;
3996a22c544SJuan Quintela char *result;
4006a22c544SJuan Quintela
401aca04069SDaniel P. Berrangé rsp = qtest_qmp_assert_success_ref(
402aca04069SDaniel P. Berrangé who, "{ 'execute': 'query-migrate-parameters' }");
4036a22c544SJuan Quintela result = g_strdup(qdict_get_str(rsp, parameter));
4046a22c544SJuan Quintela qobject_unref(rsp);
4056a22c544SJuan Quintela return result;
4066a22c544SJuan Quintela }
4076a22c544SJuan Quintela
migrate_check_parameter_str(QTestState * who,const char * parameter,const char * value)4086a22c544SJuan Quintela static void migrate_check_parameter_str(QTestState *who, const char *parameter,
4096a22c544SJuan Quintela const char *value)
4106a22c544SJuan Quintela {
411ff7b9b56SPeter Maydell g_autofree char *result = migrate_get_parameter_str(who, parameter);
4126a22c544SJuan Quintela g_assert_cmpstr(result, ==, value);
4136a22c544SJuan Quintela }
4146a22c544SJuan Quintela
migrate_set_parameter_str(QTestState * who,const char * parameter,const char * value)4156a22c544SJuan Quintela static void migrate_set_parameter_str(QTestState *who, const char *parameter,
4166a22c544SJuan Quintela const char *value)
4176a22c544SJuan Quintela {
41811936f0eSDaniel P. Berrangé qtest_qmp_assert_success(who,
4196a22c544SJuan Quintela "{ 'execute': 'migrate-set-parameters',"
4206a22c544SJuan Quintela "'arguments': { %s: %s } }",
4216a22c544SJuan Quintela parameter, value);
4226a22c544SJuan Quintela migrate_check_parameter_str(who, parameter, value);
4236a22c544SJuan Quintela }
4246a22c544SJuan Quintela
migrate_get_parameter_bool(QTestState * who,const char * parameter)425408d295dSFabiano Rosas static long long migrate_get_parameter_bool(QTestState *who,
426408d295dSFabiano Rosas const char *parameter)
427408d295dSFabiano Rosas {
428408d295dSFabiano Rosas QDict *rsp;
429408d295dSFabiano Rosas int result;
430408d295dSFabiano Rosas
431408d295dSFabiano Rosas rsp = qtest_qmp_assert_success_ref(
432408d295dSFabiano Rosas who, "{ 'execute': 'query-migrate-parameters' }");
433408d295dSFabiano Rosas result = qdict_get_bool(rsp, parameter);
434408d295dSFabiano Rosas qobject_unref(rsp);
435408d295dSFabiano Rosas return !!result;
436408d295dSFabiano Rosas }
437408d295dSFabiano Rosas
migrate_check_parameter_bool(QTestState * who,const char * parameter,int value)438408d295dSFabiano Rosas static void migrate_check_parameter_bool(QTestState *who, const char *parameter,
439408d295dSFabiano Rosas int value)
440408d295dSFabiano Rosas {
441408d295dSFabiano Rosas int result;
442408d295dSFabiano Rosas
443408d295dSFabiano Rosas result = migrate_get_parameter_bool(who, parameter);
444408d295dSFabiano Rosas g_assert_cmpint(result, ==, value);
445408d295dSFabiano Rosas }
446408d295dSFabiano Rosas
migrate_set_parameter_bool(QTestState * who,const char * parameter,int value)447408d295dSFabiano Rosas static void migrate_set_parameter_bool(QTestState *who, const char *parameter,
448408d295dSFabiano Rosas int value)
449408d295dSFabiano Rosas {
450408d295dSFabiano Rosas qtest_qmp_assert_success(who,
451408d295dSFabiano Rosas "{ 'execute': 'migrate-set-parameters',"
452408d295dSFabiano Rosas "'arguments': { %s: %i } }",
453408d295dSFabiano Rosas parameter, value);
454408d295dSFabiano Rosas migrate_check_parameter_bool(who, parameter, value);
455408d295dSFabiano Rosas }
456408d295dSFabiano Rosas
migrate_ensure_non_converge(QTestState * who)457886dfe9dSDaniel P. Berrangé static void migrate_ensure_non_converge(QTestState *who)
458886dfe9dSDaniel P. Berrangé {
4591bfc8ddeSDr. David Alan Gilbert /* Can't converge with 1ms downtime + 3 mbs bandwidth limit */
4601bfc8ddeSDr. David Alan Gilbert migrate_set_parameter_int(who, "max-bandwidth", 3 * 1000 * 1000);
461886dfe9dSDaniel P. Berrangé migrate_set_parameter_int(who, "downtime-limit", 1);
462886dfe9dSDaniel P. Berrangé }
463886dfe9dSDaniel P. Berrangé
migrate_ensure_converge(QTestState * who)464886dfe9dSDaniel P. Berrangé static void migrate_ensure_converge(QTestState *who)
465886dfe9dSDaniel P. Berrangé {
466886dfe9dSDaniel P. Berrangé /* Should converge with 30s downtime + 1 gbs bandwidth limit */
467886dfe9dSDaniel P. Berrangé migrate_set_parameter_int(who, "max-bandwidth", 1 * 1000 * 1000 * 1000);
468886dfe9dSDaniel P. Berrangé migrate_set_parameter_int(who, "downtime-limit", 30 * 1000);
469886dfe9dSDaniel P. Berrangé }
470886dfe9dSDaniel P. Berrangé
471e02f56e3SDaniel P. Berrangé /*
472e02f56e3SDaniel P. Berrangé * Our goal is to ensure that we run a single full migration
473e02f56e3SDaniel P. Berrangé * iteration, and also dirty memory, ensuring that at least
474e02f56e3SDaniel P. Berrangé * one further iteration is required.
475e02f56e3SDaniel P. Berrangé *
476e02f56e3SDaniel P. Berrangé * We can't directly synchronize with the start of a migration
477e02f56e3SDaniel P. Berrangé * so we have to apply some tricks monitoring memory that is
478e02f56e3SDaniel P. Berrangé * transferred.
479e02f56e3SDaniel P. Berrangé *
480e02f56e3SDaniel P. Berrangé * Initially we set the migration bandwidth to an insanely
481e02f56e3SDaniel P. Berrangé * low value, with tiny max downtime too. This basically
482e02f56e3SDaniel P. Berrangé * guarantees migration will never complete.
483e02f56e3SDaniel P. Berrangé *
484e02f56e3SDaniel P. Berrangé * This will result in a test that is unacceptably slow though,
485e02f56e3SDaniel P. Berrangé * so we can't let the entire migration pass run at this speed.
486e02f56e3SDaniel P. Berrangé * Our intent is to let it run just long enough that we can
487e02f56e3SDaniel P. Berrangé * prove data prior to the marker has been transferred *AND*
488e02f56e3SDaniel P. Berrangé * also prove this transferred data is dirty again.
489e02f56e3SDaniel P. Berrangé *
490e02f56e3SDaniel P. Berrangé * Before migration starts, we write a 64-bit magic marker
491e02f56e3SDaniel P. Berrangé * into a fixed location in the src VM RAM.
492e02f56e3SDaniel P. Berrangé *
493e02f56e3SDaniel P. Berrangé * Then watch dst memory until the marker appears. This is
494e02f56e3SDaniel P. Berrangé * proof that start_address -> MAGIC_OFFSET_BASE has been
495e02f56e3SDaniel P. Berrangé * transferred.
496e02f56e3SDaniel P. Berrangé *
497e02f56e3SDaniel P. Berrangé * Finally we go back to the source and read a byte just
49896420a30SMichael Tokarev * before the marker until we see it flip in value. This
499e02f56e3SDaniel P. Berrangé * is proof that start_address -> MAGIC_OFFSET_BASE
500e02f56e3SDaniel P. Berrangé * is now dirty again.
501e02f56e3SDaniel P. Berrangé *
502e02f56e3SDaniel P. Berrangé * IOW, we're guaranteed at least a 2nd migration pass
503e02f56e3SDaniel P. Berrangé * at this point.
504e02f56e3SDaniel P. Berrangé *
505e02f56e3SDaniel P. Berrangé * We can now let migration run at full speed to finish
506e02f56e3SDaniel P. Berrangé * the test
507e02f56e3SDaniel P. Berrangé */
migrate_prepare_for_dirty_mem(QTestState * from)508e02f56e3SDaniel P. Berrangé static void migrate_prepare_for_dirty_mem(QTestState *from)
509e02f56e3SDaniel P. Berrangé {
510e02f56e3SDaniel P. Berrangé /*
511e02f56e3SDaniel P. Berrangé * The guest workflow iterates from start_address to
512e02f56e3SDaniel P. Berrangé * end_address, writing 1 byte every TEST_MEM_PAGE_SIZE
513e02f56e3SDaniel P. Berrangé * bytes.
514e02f56e3SDaniel P. Berrangé *
515e02f56e3SDaniel P. Berrangé * IOW, if we write to mem at a point which is NOT
516e02f56e3SDaniel P. Berrangé * a multiple of TEST_MEM_PAGE_SIZE, our write won't
517e02f56e3SDaniel P. Berrangé * conflict with the migration workflow.
518e02f56e3SDaniel P. Berrangé *
519e02f56e3SDaniel P. Berrangé * We put in a marker here, that we'll use to determine
520e02f56e3SDaniel P. Berrangé * when the data has been transferred to the dst.
521e02f56e3SDaniel P. Berrangé */
522e02f56e3SDaniel P. Berrangé qtest_writeq(from, start_address + MAGIC_OFFSET, MAGIC_MARKER);
523e02f56e3SDaniel P. Berrangé }
524e02f56e3SDaniel P. Berrangé
migrate_wait_for_dirty_mem(QTestState * from,QTestState * to)525e02f56e3SDaniel P. Berrangé static void migrate_wait_for_dirty_mem(QTestState *from,
526e02f56e3SDaniel P. Berrangé QTestState *to)
527e02f56e3SDaniel P. Berrangé {
528e02f56e3SDaniel P. Berrangé uint64_t watch_address = start_address + MAGIC_OFFSET_BASE;
529e02f56e3SDaniel P. Berrangé uint64_t marker_address = start_address + MAGIC_OFFSET;
530e02f56e3SDaniel P. Berrangé uint8_t watch_byte;
531e02f56e3SDaniel P. Berrangé
532e02f56e3SDaniel P. Berrangé /*
533e02f56e3SDaniel P. Berrangé * Wait for the MAGIC_MARKER to get transferred, as an
534e02f56e3SDaniel P. Berrangé * indicator that a migration pass has made some known
535e02f56e3SDaniel P. Berrangé * amount of progress.
536e02f56e3SDaniel P. Berrangé */
537e02f56e3SDaniel P. Berrangé do {
538e02f56e3SDaniel P. Berrangé usleep(1000 * 10);
539e02f56e3SDaniel P. Berrangé } while (qtest_readq(to, marker_address) != MAGIC_MARKER);
540e02f56e3SDaniel P. Berrangé
541b1fdd21eSSteve Sistare
542b1fdd21eSSteve Sistare /* If suspended, src only iterates once, and watch_byte may never change */
543b1fdd21eSSteve Sistare if (src_state.suspend_me) {
544b1fdd21eSSteve Sistare return;
545b1fdd21eSSteve Sistare }
546b1fdd21eSSteve Sistare
547e02f56e3SDaniel P. Berrangé /*
548e02f56e3SDaniel P. Berrangé * Now ensure that already transferred bytes are
549e02f56e3SDaniel P. Berrangé * dirty again from the guest workload. Note the
550e02f56e3SDaniel P. Berrangé * guest byte value will wrap around and by chance
551e02f56e3SDaniel P. Berrangé * match the original watch_byte. This is harmless
552e02f56e3SDaniel P. Berrangé * as we'll eventually see a different value if we
553e02f56e3SDaniel P. Berrangé * keep watching
554e02f56e3SDaniel P. Berrangé */
555e02f56e3SDaniel P. Berrangé watch_byte = qtest_readb(from, watch_address);
556e02f56e3SDaniel P. Berrangé do {
557e02f56e3SDaniel P. Berrangé usleep(1000 * 10);
558e02f56e3SDaniel P. Berrangé } while (qtest_readb(from, watch_address) == watch_byte);
559e02f56e3SDaniel P. Berrangé }
560e02f56e3SDaniel P. Berrangé
561e02f56e3SDaniel P. Berrangé
migrate_pause(QTestState * who)5621e8a1faeSThomas Huth static void migrate_pause(QTestState *who)
5631e8a1faeSThomas Huth {
564aca04069SDaniel P. Berrangé qtest_qmp_assert_success(who, "{ 'execute': 'migrate-pause' }");
5651e8a1faeSThomas Huth }
5661e8a1faeSThomas Huth
migrate_continue(QTestState * who,const char * state)5671e8a1faeSThomas Huth static void migrate_continue(QTestState *who, const char *state)
5681e8a1faeSThomas Huth {
569aca04069SDaniel P. Berrangé qtest_qmp_assert_success(who,
5701e8a1faeSThomas Huth "{ 'execute': 'migrate-continue',"
5711e8a1faeSThomas Huth " 'arguments': { 'state': %s } }",
5721e8a1faeSThomas Huth state);
5731e8a1faeSThomas Huth }
5741e8a1faeSThomas Huth
migrate_recover(QTestState * who,const char * uri)5751e8a1faeSThomas Huth static void migrate_recover(QTestState *who, const char *uri)
5761e8a1faeSThomas Huth {
577aca04069SDaniel P. Berrangé qtest_qmp_assert_success(who,
5781e8a1faeSThomas Huth "{ 'execute': 'migrate-recover', "
5791e8a1faeSThomas Huth " 'id': 'recover-cmd', "
5801e8a1faeSThomas Huth " 'arguments': { 'uri': %s } }",
5811e8a1faeSThomas Huth uri);
5821e8a1faeSThomas Huth }
5831e8a1faeSThomas Huth
migrate_cancel(QTestState * who)584d795f474SJuan Quintela static void migrate_cancel(QTestState *who)
585d795f474SJuan Quintela {
586aca04069SDaniel P. Berrangé qtest_qmp_assert_success(who, "{ 'execute': 'migrate_cancel' }");
587d795f474SJuan Quintela }
588d795f474SJuan Quintela
migrate_postcopy_start(QTestState * from,QTestState * to)5891e8a1faeSThomas Huth static void migrate_postcopy_start(QTestState *from, QTestState *to)
5901e8a1faeSThomas Huth {
591aca04069SDaniel P. Berrangé qtest_qmp_assert_success(from, "{ 'execute': 'migrate-start-postcopy' }");
5921e8a1faeSThomas Huth
593f0649758SSteve Sistare wait_for_stop(from, &src_state);
5941e8a1faeSThomas Huth qtest_qmp_eventwait(to, "RESUME");
5951e8a1faeSThomas Huth }
5961e8a1faeSThomas Huth
5971e8a1faeSThomas Huth typedef struct {
598a4729501SPeter Xu /*
599a4729501SPeter Xu * QTEST_LOG=1 may override this. When QTEST_LOG=1, we always dump errors
600a4729501SPeter Xu * unconditionally, because it means the user would like to be verbose.
601a4729501SPeter Xu */
6021e8a1faeSThomas Huth bool hide_stderr;
6031e8a1faeSThomas Huth bool use_shmem;
604d795f474SJuan Quintela /* only launch the target process */
605d795f474SJuan Quintela bool only_target;
6061f546b70SPeter Xu /* Use dirty ring if true; dirty logging otherwise */
6071f546b70SPeter Xu bool use_dirty_ring;
60819da6edfSDaniel P. Berrangé const char *opts_source;
60919da6edfSDaniel P. Berrangé const char *opts_target;
6105014478eSSteve Sistare /* suspend the src before migrating to dest. */
6115014478eSSteve Sistare bool suspend_me;
6121e8a1faeSThomas Huth } MigrateStart;
6131e8a1faeSThomas Huth
614312e9dd0SPeter Xu /*
615312e9dd0SPeter Xu * A hook that runs after the src and dst QEMUs have been
616312e9dd0SPeter Xu * created, but before the migration is started. This can
617312e9dd0SPeter Xu * be used to set migration parameters and capabilities.
618312e9dd0SPeter Xu *
619312e9dd0SPeter Xu * Returns: NULL, or a pointer to opaque state to be
620312e9dd0SPeter Xu * later passed to the TestMigrateFinishHook
621312e9dd0SPeter Xu */
622312e9dd0SPeter Xu typedef void * (*TestMigrateStartHook)(QTestState *from,
623312e9dd0SPeter Xu QTestState *to);
624312e9dd0SPeter Xu
625312e9dd0SPeter Xu /*
626312e9dd0SPeter Xu * A hook that runs after the migration has finished,
627312e9dd0SPeter Xu * regardless of whether it succeeded or failed, but
628312e9dd0SPeter Xu * before QEMU has terminated (unless it self-terminated
629312e9dd0SPeter Xu * due to migration error)
630312e9dd0SPeter Xu *
631312e9dd0SPeter Xu * @opaque is a pointer to state previously returned
632312e9dd0SPeter Xu * by the TestMigrateStartHook if any, or NULL.
633312e9dd0SPeter Xu */
634312e9dd0SPeter Xu typedef void (*TestMigrateFinishHook)(QTestState *from,
635312e9dd0SPeter Xu QTestState *to,
636312e9dd0SPeter Xu void *opaque);
637312e9dd0SPeter Xu
638312e9dd0SPeter Xu typedef struct {
639312e9dd0SPeter Xu /* Optional: fine tune start parameters */
640312e9dd0SPeter Xu MigrateStart start;
641312e9dd0SPeter Xu
642312e9dd0SPeter Xu /* Required: the URI for the dst QEMU to listen on */
643312e9dd0SPeter Xu const char *listen_uri;
644312e9dd0SPeter Xu
645312e9dd0SPeter Xu /*
646312e9dd0SPeter Xu * Optional: the URI for the src QEMU to connect to
647312e9dd0SPeter Xu * If NULL, then it will query the dst QEMU for its actual
648312e9dd0SPeter Xu * listening address and use that as the connect address.
649312e9dd0SPeter Xu * This allows for dynamically picking a free TCP port.
650312e9dd0SPeter Xu */
651312e9dd0SPeter Xu const char *connect_uri;
652312e9dd0SPeter Xu
6539d36d62cSHet Gala /*
6549d36d62cSHet Gala * Optional: JSON-formatted list of src QEMU URIs. If a port is
6559d36d62cSHet Gala * defined as '0' in any QDict key a value of '0' will be
6569d36d62cSHet Gala * automatically converted to the correct destination port.
6579d36d62cSHet Gala */
6589d36d62cSHet Gala const char *connect_channels;
6599d36d62cSHet Gala
660312e9dd0SPeter Xu /* Optional: callback to run at start to set migration parameters */
661312e9dd0SPeter Xu TestMigrateStartHook start_hook;
662312e9dd0SPeter Xu /* Optional: callback to run at finish to cleanup */
663312e9dd0SPeter Xu TestMigrateFinishHook finish_hook;
664312e9dd0SPeter Xu
665312e9dd0SPeter Xu /*
666312e9dd0SPeter Xu * Optional: normally we expect the migration process to complete.
667312e9dd0SPeter Xu *
668312e9dd0SPeter Xu * There can be a variety of reasons and stages in which failure
669312e9dd0SPeter Xu * can happen during tests.
670312e9dd0SPeter Xu *
671312e9dd0SPeter Xu * If a failure is expected to happen at time of establishing
672312e9dd0SPeter Xu * the connection, then MIG_TEST_FAIL will indicate that the dst
673312e9dd0SPeter Xu * QEMU is expected to stay running and accept future migration
674312e9dd0SPeter Xu * connections.
675312e9dd0SPeter Xu *
676312e9dd0SPeter Xu * If a failure is expected to happen while processing the
677312e9dd0SPeter Xu * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
678312e9dd0SPeter Xu * that the dst QEMU is expected to quit with non-zero exit status
679312e9dd0SPeter Xu */
680312e9dd0SPeter Xu enum {
681312e9dd0SPeter Xu /* This test should succeed, the default */
682312e9dd0SPeter Xu MIG_TEST_SUCCEED = 0,
683312e9dd0SPeter Xu /* This test should fail, dest qemu should keep alive */
684312e9dd0SPeter Xu MIG_TEST_FAIL,
685312e9dd0SPeter Xu /* This test should fail, dest qemu should fail with abnormal status */
686312e9dd0SPeter Xu MIG_TEST_FAIL_DEST_QUIT_ERR,
6875274274cSFabiano Rosas /* The QMP command for this migration should fail with an error */
6885274274cSFabiano Rosas MIG_TEST_QMP_ERROR,
689312e9dd0SPeter Xu } result;
690312e9dd0SPeter Xu
691e02f56e3SDaniel P. Berrangé /*
692e02f56e3SDaniel P. Berrangé * Optional: set number of migration passes to wait for, if live==true.
693e02f56e3SDaniel P. Berrangé * If zero, then merely wait for a few MB of dirty data
694e02f56e3SDaniel P. Berrangé */
695312e9dd0SPeter Xu unsigned int iterations;
696d1a27b16SPeter Xu
697b861383cSPeter Xu /*
698b861383cSPeter Xu * Optional: whether the guest CPUs should be running during a precopy
699b861383cSPeter Xu * migration test. We used to always run with live but it took much
700b861383cSPeter Xu * longer so we reduced live tests to only the ones that have solid
701b861383cSPeter Xu * reason to be tested live-only. For each of the new test cases for
702b861383cSPeter Xu * precopy please provide justifications to use live explicitly (please
703b861383cSPeter Xu * refer to existing ones with live=true), or use live=off by default.
704b861383cSPeter Xu */
7053c4fb177SDaniel P. Berrangé bool live;
7063c4fb177SDaniel P. Berrangé
707d1a27b16SPeter Xu /* Postcopy specific fields */
708d1a27b16SPeter Xu void *postcopy_data;
7098f6fe915SPeter Xu bool postcopy_preempt;
7106cf56a87SPeter Xu PostcopyRecoveryFailStage postcopy_recovery_fail_stage;
711312e9dd0SPeter Xu } MigrateCommon;
712312e9dd0SPeter Xu
test_migrate_start(QTestState ** from,QTestState ** to,const char * uri,MigrateStart * args)7131e8a1faeSThomas Huth static int test_migrate_start(QTestState **from, QTestState **to,
71419da6edfSDaniel P. Berrangé const char *uri, MigrateStart *args)
7151e8a1faeSThomas Huth {
716ff7b9b56SPeter Maydell g_autofree gchar *arch_source = NULL;
717ff7b9b56SPeter Maydell g_autofree gchar *arch_target = NULL;
718832c732cSJuan Quintela /* options for source and target */
719832c732cSJuan Quintela g_autofree gchar *arch_opts = NULL;
720ff7b9b56SPeter Maydell g_autofree gchar *cmd_source = NULL;
721ff7b9b56SPeter Maydell g_autofree gchar *cmd_target = NULL;
7221e8a1faeSThomas Huth const gchar *ignore_stderr;
723ff7b9b56SPeter Maydell g_autofree char *shmem_opts = NULL;
724ff7b9b56SPeter Maydell g_autofree char *shmem_path = NULL;
72571d36124SJuan Quintela const char *kvm_opts = NULL;
7261e8a1faeSThomas Huth const char *arch = qtest_get_arch();
7271e8a1faeSThomas Huth const char *memory_size;
728c9961391SFabiano Rosas const char *machine_alias, *machine_opts = "";
7295050ad2aSFabiano Rosas g_autofree char *machine = NULL;
7301e8a1faeSThomas Huth
7311e8a1faeSThomas Huth if (args->use_shmem) {
7321e8a1faeSThomas Huth if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
7331e8a1faeSThomas Huth g_test_skip("/dev/shm is not supported");
73419da6edfSDaniel P. Berrangé return -1;
7351e8a1faeSThomas Huth }
7361e8a1faeSThomas Huth }
7371e8a1faeSThomas Huth
738f0649758SSteve Sistare dst_state = (QTestMigrationState) { };
739f0649758SSteve Sistare src_state = (QTestMigrationState) { };
7405014478eSSteve Sistare bootfile_create(tmpfs, args->suspend_me);
741b1fdd21eSSteve Sistare src_state.suspend_me = args->suspend_me;
7425014478eSSteve Sistare
7431e8a1faeSThomas Huth if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
7441e8a1faeSThomas Huth memory_size = "150M";
745fa35b0cbSFabiano Rosas
746fa35b0cbSFabiano Rosas if (g_str_equal(arch, "i386")) {
747c9961391SFabiano Rosas machine_alias = "pc";
748fa35b0cbSFabiano Rosas } else {
749fa35b0cbSFabiano Rosas machine_alias = "q35";
750fa35b0cbSFabiano Rosas }
7513cb9c655SFabiano Rosas arch_opts = g_strdup_printf(
7523cb9c655SFabiano Rosas "-drive if=none,id=d0,file=%s,format=raw "
7533cb9c655SFabiano Rosas "-device ide-hd,drive=d0,secs=1,cyls=1,heads=1", bootpath);
7541e8a1faeSThomas Huth start_address = X86_TEST_MEM_START;
7551e8a1faeSThomas Huth end_address = X86_TEST_MEM_END;
7561e8a1faeSThomas Huth } else if (g_str_equal(arch, "s390x")) {
7571e8a1faeSThomas Huth memory_size = "128M";
758c9961391SFabiano Rosas machine_alias = "s390-ccw-virtio";
759832c732cSJuan Quintela arch_opts = g_strdup_printf("-bios %s", bootpath);
7601e8a1faeSThomas Huth start_address = S390_TEST_MEM_START;
7611e8a1faeSThomas Huth end_address = S390_TEST_MEM_END;
7621e8a1faeSThomas Huth } else if (strcmp(arch, "ppc64") == 0) {
7631e8a1faeSThomas Huth memory_size = "256M";
76416c5c692SLaurent Vivier start_address = PPC_TEST_MEM_START;
76516c5c692SLaurent Vivier end_address = PPC_TEST_MEM_END;
766c9961391SFabiano Rosas machine_alias = "pseries";
767c9961391SFabiano Rosas machine_opts = "vsmt=8";
76834cc54fbSNicholas Piggin arch_opts = g_strdup_printf(
76934cc54fbSNicholas Piggin "-nodefaults -machine " PSERIES_DEFAULT_CAPABILITIES " "
77034cc54fbSNicholas Piggin "-bios %s", bootpath);
7711e8a1faeSThomas Huth } else if (strcmp(arch, "aarch64") == 0) {
7721e8a1faeSThomas Huth memory_size = "150M";
773c9961391SFabiano Rosas machine_alias = "virt";
774bdb0ade6SPeter Xu machine_opts = "gic-version=3";
775c9961391SFabiano Rosas arch_opts = g_strdup_printf("-cpu max -kernel %s", bootpath);
7761e8a1faeSThomas Huth start_address = ARM_TEST_MEM_START;
7771e8a1faeSThomas Huth end_address = ARM_TEST_MEM_END;
7781e8a1faeSThomas Huth } else {
7791e8a1faeSThomas Huth g_assert_not_reached();
7801e8a1faeSThomas Huth }
7811e8a1faeSThomas Huth
782a4729501SPeter Xu if (!getenv("QTEST_LOG") && args->hide_stderr) {
7834dc8be38SBin Meng #ifndef _WIN32
7841e8a1faeSThomas Huth ignore_stderr = "2>/dev/null";
7854dc8be38SBin Meng #else
7864dc8be38SBin Meng /*
7874dc8be38SBin Meng * On Windows the QEMU executable is created via CreateProcess() and
7884dc8be38SBin Meng * IO redirection does not work, so don't bother adding IO redirection
7894dc8be38SBin Meng * to the command line.
7904dc8be38SBin Meng */
7914dc8be38SBin Meng ignore_stderr = "";
7924dc8be38SBin Meng #endif
7931e8a1faeSThomas Huth } else {
7941e8a1faeSThomas Huth ignore_stderr = "";
7951e8a1faeSThomas Huth }
7961e8a1faeSThomas Huth
7971e8a1faeSThomas Huth if (args->use_shmem) {
7981e8a1faeSThomas Huth shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
7991e8a1faeSThomas Huth shmem_opts = g_strdup_printf(
8001e8a1faeSThomas Huth "-object memory-backend-file,id=mem0,size=%s"
8011e8a1faeSThomas Huth ",mem-path=%s,share=on -numa node,memdev=mem0",
8021e8a1faeSThomas Huth memory_size, shmem_path);
8031e8a1faeSThomas Huth }
8041e8a1faeSThomas Huth
80571d36124SJuan Quintela if (args->use_dirty_ring) {
80671d36124SJuan Quintela kvm_opts = ",dirty-ring-size=4096";
80771d36124SJuan Quintela }
80871d36124SJuan Quintela
8096bd92a7cSPaolo Bonzini if (!qtest_has_machine(machine_alias)) {
8106bd92a7cSPaolo Bonzini g_autofree char *msg = g_strdup_printf("machine %s not supported", machine_alias);
8116bd92a7cSPaolo Bonzini g_test_skip(msg);
8126bd92a7cSPaolo Bonzini return -1;
8136bd92a7cSPaolo Bonzini }
8146bd92a7cSPaolo Bonzini
8156c6d2330SFabiano Rosas machine = resolve_machine_version(machine_alias, QEMU_ENV_SRC,
8165050ad2aSFabiano Rosas QEMU_ENV_DST);
8176c6d2330SFabiano Rosas
8185050ad2aSFabiano Rosas g_test_message("Using machine type: %s", machine);
8195050ad2aSFabiano Rosas
820bc28a611SJuan Quintela cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
821c9961391SFabiano Rosas "-machine %s,%s "
8221e8a1faeSThomas Huth "-name source,debug-threads=on "
8231e8a1faeSThomas Huth "-m %s "
8241e8a1faeSThomas Huth "-serial file:%s/src_serial "
825832c732cSJuan Quintela "%s %s %s %s %s",
82671d36124SJuan Quintela kvm_opts ? kvm_opts : "",
8275050ad2aSFabiano Rosas machine, machine_opts,
8281e8a1faeSThomas Huth memory_size, tmpfs,
829832c732cSJuan Quintela arch_opts ? arch_opts : "",
830832c732cSJuan Quintela arch_source ? arch_source : "",
8310368ace8SJuan Quintela shmem_opts ? shmem_opts : "",
83219da6edfSDaniel P. Berrangé args->opts_source ? args->opts_source : "",
8331e8a1faeSThomas Huth ignore_stderr);
834d795f474SJuan Quintela if (!args->only_target) {
8355050ad2aSFabiano Rosas *from = qtest_init_with_env(QEMU_ENV_SRC, cmd_source);
836cdf5ab55SDaniel P. Berrangé qtest_qmp_set_event_callback(*from,
837f0649758SSteve Sistare migrate_watch_for_events,
838f0649758SSteve Sistare &src_state);
839d795f474SJuan Quintela }
8401e8a1faeSThomas Huth
841bc28a611SJuan Quintela cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
842c9961391SFabiano Rosas "-machine %s,%s "
8431e8a1faeSThomas Huth "-name target,debug-threads=on "
8441e8a1faeSThomas Huth "-m %s "
8451e8a1faeSThomas Huth "-serial file:%s/dest_serial "
8461e8a1faeSThomas Huth "-incoming %s "
847832c732cSJuan Quintela "%s %s %s %s %s",
84871d36124SJuan Quintela kvm_opts ? kvm_opts : "",
8495050ad2aSFabiano Rosas machine, machine_opts,
8501e8a1faeSThomas Huth memory_size, tmpfs, uri,
851832c732cSJuan Quintela arch_opts ? arch_opts : "",
852832c732cSJuan Quintela arch_target ? arch_target : "",
8530368ace8SJuan Quintela shmem_opts ? shmem_opts : "",
85419da6edfSDaniel P. Berrangé args->opts_target ? args->opts_target : "",
85519da6edfSDaniel P. Berrangé ignore_stderr);
8565050ad2aSFabiano Rosas *to = qtest_init_with_env(QEMU_ENV_DST, cmd_target);
857266ea334SDaniel P. Berrangé qtest_qmp_set_event_callback(*to,
858f0649758SSteve Sistare migrate_watch_for_events,
859f0649758SSteve Sistare &dst_state);
8601e8a1faeSThomas Huth
8611e8a1faeSThomas Huth /*
8621e8a1faeSThomas Huth * Remove shmem file immediately to avoid memory leak in test failed case.
86396420a30SMichael Tokarev * It's valid because QEMU has already opened this file
8641e8a1faeSThomas Huth */
8651e8a1faeSThomas Huth if (args->use_shmem) {
8661e8a1faeSThomas Huth unlink(shmem_path);
8671e8a1faeSThomas Huth }
8681e8a1faeSThomas Huth
869cd313b66SPeter Xu /*
870cd313b66SPeter Xu * Always enable migration events. Libvirt always uses it, let's try
871cd313b66SPeter Xu * to mimic as closer as that.
872cd313b66SPeter Xu */
873cd313b66SPeter Xu migrate_set_capability(*from, "events", true);
874cd313b66SPeter Xu migrate_set_capability(*to, "events", true);
875cd313b66SPeter Xu
87619da6edfSDaniel P. Berrangé return 0;
8771e8a1faeSThomas Huth }
8781e8a1faeSThomas Huth
test_migrate_end(QTestState * from,QTestState * to,bool test_dest)8791e8a1faeSThomas Huth static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
8801e8a1faeSThomas Huth {
8811e8a1faeSThomas Huth unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
8821e8a1faeSThomas Huth
8831e8a1faeSThomas Huth qtest_quit(from);
8841e8a1faeSThomas Huth
8851e8a1faeSThomas Huth if (test_dest) {
8861e8a1faeSThomas Huth qtest_memread(to, start_address, &dest_byte_a, 1);
8871e8a1faeSThomas Huth
8881e8a1faeSThomas Huth /* Destination still running, wait for a byte to change */
8891e8a1faeSThomas Huth do {
8901e8a1faeSThomas Huth qtest_memread(to, start_address, &dest_byte_b, 1);
8911e8a1faeSThomas Huth usleep(1000 * 10);
8921e8a1faeSThomas Huth } while (dest_byte_a == dest_byte_b);
8931e8a1faeSThomas Huth
894855436dbSDaniel P. Berrangé qtest_qmp_assert_success(to, "{ 'execute' : 'stop'}");
8951e8a1faeSThomas Huth
8961e8a1faeSThomas Huth /* With it stopped, check nothing changes */
8971e8a1faeSThomas Huth qtest_memread(to, start_address, &dest_byte_c, 1);
8981e8a1faeSThomas Huth usleep(1000 * 200);
8991e8a1faeSThomas Huth qtest_memread(to, start_address, &dest_byte_d, 1);
9001e8a1faeSThomas Huth g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
9011e8a1faeSThomas Huth
9021e8a1faeSThomas Huth check_guests_ram(to);
9031e8a1faeSThomas Huth }
9041e8a1faeSThomas Huth
9051e8a1faeSThomas Huth qtest_quit(to);
9061e8a1faeSThomas Huth
9071e8a1faeSThomas Huth cleanup("migsocket");
9081e8a1faeSThomas Huth cleanup("src_serial");
9091e8a1faeSThomas Huth cleanup("dest_serial");
9103dc35470SFabiano Rosas cleanup(FILE_TEST_FILENAME);
9111e8a1faeSThomas Huth }
9121e8a1faeSThomas Huth
91358d25e97SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
91458d25e97SDaniel P. Berrangé struct TestMigrateTLSPSKData {
91558d25e97SDaniel P. Berrangé char *workdir;
91658d25e97SDaniel P. Berrangé char *workdiralt;
91758d25e97SDaniel P. Berrangé char *pskfile;
91858d25e97SDaniel P. Berrangé char *pskfilealt;
91958d25e97SDaniel P. Berrangé };
92058d25e97SDaniel P. Berrangé
92158d25e97SDaniel P. Berrangé static void *
test_migrate_tls_psk_start_common(QTestState * from,QTestState * to,bool mismatch)92258d25e97SDaniel P. Berrangé test_migrate_tls_psk_start_common(QTestState *from,
92358d25e97SDaniel P. Berrangé QTestState *to,
92458d25e97SDaniel P. Berrangé bool mismatch)
92558d25e97SDaniel P. Berrangé {
92658d25e97SDaniel P. Berrangé struct TestMigrateTLSPSKData *data =
92758d25e97SDaniel P. Berrangé g_new0(struct TestMigrateTLSPSKData, 1);
92858d25e97SDaniel P. Berrangé
92958d25e97SDaniel P. Berrangé data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs);
93058d25e97SDaniel P. Berrangé data->pskfile = g_strdup_printf("%s/%s", data->workdir,
93158d25e97SDaniel P. Berrangé QCRYPTO_TLS_CREDS_PSKFILE);
932413bebc0SBin Meng g_mkdir_with_parents(data->workdir, 0700);
93358d25e97SDaniel P. Berrangé test_tls_psk_init(data->pskfile);
93458d25e97SDaniel P. Berrangé
93558d25e97SDaniel P. Berrangé if (mismatch) {
93658d25e97SDaniel P. Berrangé data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs);
93758d25e97SDaniel P. Berrangé data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt,
93858d25e97SDaniel P. Berrangé QCRYPTO_TLS_CREDS_PSKFILE);
939413bebc0SBin Meng g_mkdir_with_parents(data->workdiralt, 0700);
94058d25e97SDaniel P. Berrangé test_tls_psk_init_alt(data->pskfilealt);
94158d25e97SDaniel P. Berrangé }
94258d25e97SDaniel P. Berrangé
943aca04069SDaniel P. Berrangé qtest_qmp_assert_success(from,
94458d25e97SDaniel P. Berrangé "{ 'execute': 'object-add',"
94558d25e97SDaniel P. Berrangé " 'arguments': { 'qom-type': 'tls-creds-psk',"
94658d25e97SDaniel P. Berrangé " 'id': 'tlscredspsk0',"
94758d25e97SDaniel P. Berrangé " 'endpoint': 'client',"
94858d25e97SDaniel P. Berrangé " 'dir': %s,"
94958d25e97SDaniel P. Berrangé " 'username': 'qemu'} }",
95058d25e97SDaniel P. Berrangé data->workdir);
95158d25e97SDaniel P. Berrangé
952aca04069SDaniel P. Berrangé qtest_qmp_assert_success(to,
95358d25e97SDaniel P. Berrangé "{ 'execute': 'object-add',"
95458d25e97SDaniel P. Berrangé " 'arguments': { 'qom-type': 'tls-creds-psk',"
95558d25e97SDaniel P. Berrangé " 'id': 'tlscredspsk0',"
95658d25e97SDaniel P. Berrangé " 'endpoint': 'server',"
95758d25e97SDaniel P. Berrangé " 'dir': %s } }",
95858d25e97SDaniel P. Berrangé mismatch ? data->workdiralt : data->workdir);
95958d25e97SDaniel P. Berrangé
96058d25e97SDaniel P. Berrangé migrate_set_parameter_str(from, "tls-creds", "tlscredspsk0");
96158d25e97SDaniel P. Berrangé migrate_set_parameter_str(to, "tls-creds", "tlscredspsk0");
96258d25e97SDaniel P. Berrangé
96358d25e97SDaniel P. Berrangé return data;
96458d25e97SDaniel P. Berrangé }
96558d25e97SDaniel P. Berrangé
96658d25e97SDaniel P. Berrangé static void *
test_migrate_tls_psk_start_match(QTestState * from,QTestState * to)96758d25e97SDaniel P. Berrangé test_migrate_tls_psk_start_match(QTestState *from,
96858d25e97SDaniel P. Berrangé QTestState *to)
96958d25e97SDaniel P. Berrangé {
97058d25e97SDaniel P. Berrangé return test_migrate_tls_psk_start_common(from, to, false);
97158d25e97SDaniel P. Berrangé }
97258d25e97SDaniel P. Berrangé
97358d25e97SDaniel P. Berrangé static void *
test_migrate_tls_psk_start_mismatch(QTestState * from,QTestState * to)97458d25e97SDaniel P. Berrangé test_migrate_tls_psk_start_mismatch(QTestState *from,
97558d25e97SDaniel P. Berrangé QTestState *to)
97658d25e97SDaniel P. Berrangé {
97758d25e97SDaniel P. Berrangé return test_migrate_tls_psk_start_common(from, to, true);
97858d25e97SDaniel P. Berrangé }
97958d25e97SDaniel P. Berrangé
98058d25e97SDaniel P. Berrangé static void
test_migrate_tls_psk_finish(QTestState * from,QTestState * to,void * opaque)98158d25e97SDaniel P. Berrangé test_migrate_tls_psk_finish(QTestState *from,
98258d25e97SDaniel P. Berrangé QTestState *to,
98358d25e97SDaniel P. Berrangé void *opaque)
98458d25e97SDaniel P. Berrangé {
98558d25e97SDaniel P. Berrangé struct TestMigrateTLSPSKData *data = opaque;
98658d25e97SDaniel P. Berrangé
98758d25e97SDaniel P. Berrangé test_tls_psk_cleanup(data->pskfile);
98858d25e97SDaniel P. Berrangé if (data->pskfilealt) {
98958d25e97SDaniel P. Berrangé test_tls_psk_cleanup(data->pskfilealt);
99058d25e97SDaniel P. Berrangé }
99158d25e97SDaniel P. Berrangé rmdir(data->workdir);
99258d25e97SDaniel P. Berrangé if (data->workdiralt) {
99358d25e97SDaniel P. Berrangé rmdir(data->workdiralt);
99458d25e97SDaniel P. Berrangé }
99558d25e97SDaniel P. Berrangé
99658d25e97SDaniel P. Berrangé g_free(data->workdiralt);
99758d25e97SDaniel P. Berrangé g_free(data->pskfilealt);
99858d25e97SDaniel P. Berrangé g_free(data->workdir);
99958d25e97SDaniel P. Berrangé g_free(data->pskfile);
100058d25e97SDaniel P. Berrangé g_free(data);
100158d25e97SDaniel P. Berrangé }
1002d47b83b1SDaniel P. Berrangé
1003d47b83b1SDaniel P. Berrangé #ifdef CONFIG_TASN1
1004d47b83b1SDaniel P. Berrangé typedef struct {
1005d47b83b1SDaniel P. Berrangé char *workdir;
1006d47b83b1SDaniel P. Berrangé char *keyfile;
1007d47b83b1SDaniel P. Berrangé char *cacert;
1008d47b83b1SDaniel P. Berrangé char *servercert;
1009d47b83b1SDaniel P. Berrangé char *serverkey;
1010d47b83b1SDaniel P. Berrangé char *clientcert;
1011d47b83b1SDaniel P. Berrangé char *clientkey;
1012d47b83b1SDaniel P. Berrangé } TestMigrateTLSX509Data;
1013d47b83b1SDaniel P. Berrangé
1014d47b83b1SDaniel P. Berrangé typedef struct {
1015d47b83b1SDaniel P. Berrangé bool verifyclient;
1016d47b83b1SDaniel P. Berrangé bool clientcert;
1017d47b83b1SDaniel P. Berrangé bool hostileclient;
1018d47b83b1SDaniel P. Berrangé bool authzclient;
1019d47b83b1SDaniel P. Berrangé const char *certhostname;
1020d47b83b1SDaniel P. Berrangé const char *certipaddr;
1021d47b83b1SDaniel P. Berrangé } TestMigrateTLSX509;
1022d47b83b1SDaniel P. Berrangé
1023d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_common(QTestState * from,QTestState * to,TestMigrateTLSX509 * args)1024d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_common(QTestState *from,
1025d47b83b1SDaniel P. Berrangé QTestState *to,
1026d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 *args)
1027d47b83b1SDaniel P. Berrangé {
1028d47b83b1SDaniel P. Berrangé TestMigrateTLSX509Data *data = g_new0(TestMigrateTLSX509Data, 1);
1029d47b83b1SDaniel P. Berrangé
1030d47b83b1SDaniel P. Berrangé data->workdir = g_strdup_printf("%s/tlscredsx5090", tmpfs);
1031d47b83b1SDaniel P. Berrangé data->keyfile = g_strdup_printf("%s/key.pem", data->workdir);
1032d47b83b1SDaniel P. Berrangé
1033d47b83b1SDaniel P. Berrangé data->cacert = g_strdup_printf("%s/ca-cert.pem", data->workdir);
1034d47b83b1SDaniel P. Berrangé data->serverkey = g_strdup_printf("%s/server-key.pem", data->workdir);
1035d47b83b1SDaniel P. Berrangé data->servercert = g_strdup_printf("%s/server-cert.pem", data->workdir);
1036d47b83b1SDaniel P. Berrangé if (args->clientcert) {
1037d47b83b1SDaniel P. Berrangé data->clientkey = g_strdup_printf("%s/client-key.pem", data->workdir);
1038d47b83b1SDaniel P. Berrangé data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir);
1039d47b83b1SDaniel P. Berrangé }
1040d47b83b1SDaniel P. Berrangé
1041413bebc0SBin Meng g_mkdir_with_parents(data->workdir, 0700);
1042d47b83b1SDaniel P. Berrangé
1043d47b83b1SDaniel P. Berrangé test_tls_init(data->keyfile);
10442549f610SBin Meng #ifndef _WIN32
1045d47b83b1SDaniel P. Berrangé g_assert(link(data->keyfile, data->serverkey) == 0);
10462549f610SBin Meng #else
10472549f610SBin Meng g_assert(CreateHardLink(data->serverkey, data->keyfile, NULL) != 0);
10482549f610SBin Meng #endif
1049d47b83b1SDaniel P. Berrangé if (args->clientcert) {
10502549f610SBin Meng #ifndef _WIN32
1051d47b83b1SDaniel P. Berrangé g_assert(link(data->keyfile, data->clientkey) == 0);
10522549f610SBin Meng #else
10532549f610SBin Meng g_assert(CreateHardLink(data->clientkey, data->keyfile, NULL) != 0);
10542549f610SBin Meng #endif
1055d47b83b1SDaniel P. Berrangé }
1056d47b83b1SDaniel P. Berrangé
1057d47b83b1SDaniel P. Berrangé TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert);
1058d47b83b1SDaniel P. Berrangé if (args->clientcert) {
1059d47b83b1SDaniel P. Berrangé TLS_CERT_REQ_SIMPLE_CLIENT(servercertreq, cacertreq,
1060d47b83b1SDaniel P. Berrangé args->hostileclient ?
1061d47b83b1SDaniel P. Berrangé QCRYPTO_TLS_TEST_CLIENT_HOSTILE_NAME :
1062d47b83b1SDaniel P. Berrangé QCRYPTO_TLS_TEST_CLIENT_NAME,
1063d47b83b1SDaniel P. Berrangé data->clientcert);
10642cf6dc41SPeter Maydell test_tls_deinit_cert(&servercertreq);
1065d47b83b1SDaniel P. Berrangé }
1066d47b83b1SDaniel P. Berrangé
1067d47b83b1SDaniel P. Berrangé TLS_CERT_REQ_SIMPLE_SERVER(clientcertreq, cacertreq,
1068d47b83b1SDaniel P. Berrangé data->servercert,
1069d47b83b1SDaniel P. Berrangé args->certhostname,
1070d47b83b1SDaniel P. Berrangé args->certipaddr);
10712cf6dc41SPeter Maydell test_tls_deinit_cert(&clientcertreq);
10722cf6dc41SPeter Maydell test_tls_deinit_cert(&cacertreq);
1073d47b83b1SDaniel P. Berrangé
1074aca04069SDaniel P. Berrangé qtest_qmp_assert_success(from,
1075d47b83b1SDaniel P. Berrangé "{ 'execute': 'object-add',"
1076d47b83b1SDaniel P. Berrangé " 'arguments': { 'qom-type': 'tls-creds-x509',"
1077d47b83b1SDaniel P. Berrangé " 'id': 'tlscredsx509client0',"
1078d47b83b1SDaniel P. Berrangé " 'endpoint': 'client',"
1079d47b83b1SDaniel P. Berrangé " 'dir': %s,"
1080d47b83b1SDaniel P. Berrangé " 'sanity-check': true,"
1081d47b83b1SDaniel P. Berrangé " 'verify-peer': true} }",
1082d47b83b1SDaniel P. Berrangé data->workdir);
1083d47b83b1SDaniel P. Berrangé migrate_set_parameter_str(from, "tls-creds", "tlscredsx509client0");
1084d47b83b1SDaniel P. Berrangé if (args->certhostname) {
1085d47b83b1SDaniel P. Berrangé migrate_set_parameter_str(from, "tls-hostname", args->certhostname);
1086d47b83b1SDaniel P. Berrangé }
1087d47b83b1SDaniel P. Berrangé
1088aca04069SDaniel P. Berrangé qtest_qmp_assert_success(to,
1089d47b83b1SDaniel P. Berrangé "{ 'execute': 'object-add',"
1090d47b83b1SDaniel P. Berrangé " 'arguments': { 'qom-type': 'tls-creds-x509',"
1091d47b83b1SDaniel P. Berrangé " 'id': 'tlscredsx509server0',"
1092d47b83b1SDaniel P. Berrangé " 'endpoint': 'server',"
1093d47b83b1SDaniel P. Berrangé " 'dir': %s,"
1094d47b83b1SDaniel P. Berrangé " 'sanity-check': true,"
1095d47b83b1SDaniel P. Berrangé " 'verify-peer': %i} }",
1096d47b83b1SDaniel P. Berrangé data->workdir, args->verifyclient);
1097d47b83b1SDaniel P. Berrangé migrate_set_parameter_str(to, "tls-creds", "tlscredsx509server0");
1098d47b83b1SDaniel P. Berrangé
1099d47b83b1SDaniel P. Berrangé if (args->authzclient) {
1100aca04069SDaniel P. Berrangé qtest_qmp_assert_success(to,
1101d47b83b1SDaniel P. Berrangé "{ 'execute': 'object-add',"
1102d47b83b1SDaniel P. Berrangé " 'arguments': { 'qom-type': 'authz-simple',"
1103d47b83b1SDaniel P. Berrangé " 'id': 'tlsauthz0',"
1104d47b83b1SDaniel P. Berrangé " 'identity': %s} }",
1105d47b83b1SDaniel P. Berrangé "CN=" QCRYPTO_TLS_TEST_CLIENT_NAME);
1106d47b83b1SDaniel P. Berrangé migrate_set_parameter_str(to, "tls-authz", "tlsauthz0");
1107d47b83b1SDaniel P. Berrangé }
1108d47b83b1SDaniel P. Berrangé
1109d47b83b1SDaniel P. Berrangé return data;
1110d47b83b1SDaniel P. Berrangé }
1111d47b83b1SDaniel P. Berrangé
1112d47b83b1SDaniel P. Berrangé /*
1113d47b83b1SDaniel P. Berrangé * The normal case: match server's cert hostname against
1114d47b83b1SDaniel P. Berrangé * whatever host we were telling QEMU to connect to (if any)
1115d47b83b1SDaniel P. Berrangé */
1116d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_default_host(QTestState * from,QTestState * to)1117d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_default_host(QTestState *from,
1118d47b83b1SDaniel P. Berrangé QTestState *to)
1119d47b83b1SDaniel P. Berrangé {
1120d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1121d47b83b1SDaniel P. Berrangé .verifyclient = true,
1122d47b83b1SDaniel P. Berrangé .clientcert = true,
1123d47b83b1SDaniel P. Berrangé .certipaddr = "127.0.0.1"
1124d47b83b1SDaniel P. Berrangé };
1125d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1126d47b83b1SDaniel P. Berrangé }
1127d47b83b1SDaniel P. Berrangé
1128d47b83b1SDaniel P. Berrangé /*
1129d47b83b1SDaniel P. Berrangé * The unusual case: the server's cert is different from
1130d47b83b1SDaniel P. Berrangé * the address we're telling QEMU to connect to (if any),
1131d47b83b1SDaniel P. Berrangé * so we must give QEMU an explicit hostname to validate
1132d47b83b1SDaniel P. Berrangé */
1133d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_override_host(QTestState * from,QTestState * to)1134d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_override_host(QTestState *from,
1135d47b83b1SDaniel P. Berrangé QTestState *to)
1136d47b83b1SDaniel P. Berrangé {
1137d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1138d47b83b1SDaniel P. Berrangé .verifyclient = true,
1139d47b83b1SDaniel P. Berrangé .clientcert = true,
1140d47b83b1SDaniel P. Berrangé .certhostname = "qemu.org",
1141d47b83b1SDaniel P. Berrangé };
1142d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1143d47b83b1SDaniel P. Berrangé }
1144d47b83b1SDaniel P. Berrangé
1145d47b83b1SDaniel P. Berrangé /*
1146d47b83b1SDaniel P. Berrangé * The unusual case: the server's cert is different from
1147d47b83b1SDaniel P. Berrangé * the address we're telling QEMU to connect to, and so we
1148d47b83b1SDaniel P. Berrangé * expect the client to reject the server
1149d47b83b1SDaniel P. Berrangé */
1150d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_mismatch_host(QTestState * from,QTestState * to)1151d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_mismatch_host(QTestState *from,
1152d47b83b1SDaniel P. Berrangé QTestState *to)
1153d47b83b1SDaniel P. Berrangé {
1154d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1155d47b83b1SDaniel P. Berrangé .verifyclient = true,
1156d47b83b1SDaniel P. Berrangé .clientcert = true,
1157d47b83b1SDaniel P. Berrangé .certipaddr = "10.0.0.1",
1158d47b83b1SDaniel P. Berrangé };
1159d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1160d47b83b1SDaniel P. Berrangé }
1161d47b83b1SDaniel P. Berrangé
1162d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_friendly_client(QTestState * from,QTestState * to)1163d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_friendly_client(QTestState *from,
1164d47b83b1SDaniel P. Berrangé QTestState *to)
1165d47b83b1SDaniel P. Berrangé {
1166d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1167d47b83b1SDaniel P. Berrangé .verifyclient = true,
1168d47b83b1SDaniel P. Berrangé .clientcert = true,
1169d47b83b1SDaniel P. Berrangé .authzclient = true,
1170d47b83b1SDaniel P. Berrangé .certipaddr = "127.0.0.1",
1171d47b83b1SDaniel P. Berrangé };
1172d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1173d47b83b1SDaniel P. Berrangé }
1174d47b83b1SDaniel P. Berrangé
1175d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_hostile_client(QTestState * from,QTestState * to)1176d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_hostile_client(QTestState *from,
1177d47b83b1SDaniel P. Berrangé QTestState *to)
1178d47b83b1SDaniel P. Berrangé {
1179d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1180d47b83b1SDaniel P. Berrangé .verifyclient = true,
1181d47b83b1SDaniel P. Berrangé .clientcert = true,
1182d47b83b1SDaniel P. Berrangé .hostileclient = true,
1183d47b83b1SDaniel P. Berrangé .authzclient = true,
1184d47b83b1SDaniel P. Berrangé .certipaddr = "127.0.0.1",
1185d47b83b1SDaniel P. Berrangé };
1186d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1187d47b83b1SDaniel P. Berrangé }
1188d47b83b1SDaniel P. Berrangé
1189d47b83b1SDaniel P. Berrangé /*
1190d47b83b1SDaniel P. Berrangé * The case with no client certificate presented,
1191d47b83b1SDaniel P. Berrangé * and no server verification
1192d47b83b1SDaniel P. Berrangé */
1193d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_allow_anon_client(QTestState * from,QTestState * to)1194d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_allow_anon_client(QTestState *from,
1195d47b83b1SDaniel P. Berrangé QTestState *to)
1196d47b83b1SDaniel P. Berrangé {
1197d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1198d47b83b1SDaniel P. Berrangé .certipaddr = "127.0.0.1",
1199d47b83b1SDaniel P. Berrangé };
1200d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1201d47b83b1SDaniel P. Berrangé }
1202d47b83b1SDaniel P. Berrangé
1203d47b83b1SDaniel P. Berrangé /*
1204d47b83b1SDaniel P. Berrangé * The case with no client certificate presented,
1205d47b83b1SDaniel P. Berrangé * and server verification rejecting
1206d47b83b1SDaniel P. Berrangé */
1207d47b83b1SDaniel P. Berrangé static void *
test_migrate_tls_x509_start_reject_anon_client(QTestState * from,QTestState * to)1208d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_start_reject_anon_client(QTestState *from,
1209d47b83b1SDaniel P. Berrangé QTestState *to)
1210d47b83b1SDaniel P. Berrangé {
1211d47b83b1SDaniel P. Berrangé TestMigrateTLSX509 args = {
1212d47b83b1SDaniel P. Berrangé .verifyclient = true,
1213d47b83b1SDaniel P. Berrangé .certipaddr = "127.0.0.1",
1214d47b83b1SDaniel P. Berrangé };
1215d47b83b1SDaniel P. Berrangé return test_migrate_tls_x509_start_common(from, to, &args);
1216d47b83b1SDaniel P. Berrangé }
1217d47b83b1SDaniel P. Berrangé
1218d47b83b1SDaniel P. Berrangé static void
test_migrate_tls_x509_finish(QTestState * from,QTestState * to,void * opaque)1219d47b83b1SDaniel P. Berrangé test_migrate_tls_x509_finish(QTestState *from,
1220d47b83b1SDaniel P. Berrangé QTestState *to,
1221d47b83b1SDaniel P. Berrangé void *opaque)
1222d47b83b1SDaniel P. Berrangé {
1223d47b83b1SDaniel P. Berrangé TestMigrateTLSX509Data *data = opaque;
1224d47b83b1SDaniel P. Berrangé
1225d47b83b1SDaniel P. Berrangé test_tls_cleanup(data->keyfile);
1226d47b83b1SDaniel P. Berrangé g_free(data->keyfile);
12270f0a9e4eSThomas Huth
12280f0a9e4eSThomas Huth unlink(data->cacert);
12290f0a9e4eSThomas Huth g_free(data->cacert);
12300f0a9e4eSThomas Huth unlink(data->servercert);
12310f0a9e4eSThomas Huth g_free(data->servercert);
12320f0a9e4eSThomas Huth unlink(data->serverkey);
12330f0a9e4eSThomas Huth g_free(data->serverkey);
12340f0a9e4eSThomas Huth
12350f0a9e4eSThomas Huth if (data->clientcert) {
12360f0a9e4eSThomas Huth unlink(data->clientcert);
12370f0a9e4eSThomas Huth g_free(data->clientcert);
12380f0a9e4eSThomas Huth }
12390f0a9e4eSThomas Huth if (data->clientkey) {
12400f0a9e4eSThomas Huth unlink(data->clientkey);
12410f0a9e4eSThomas Huth g_free(data->clientkey);
12420f0a9e4eSThomas Huth }
12430f0a9e4eSThomas Huth
12440f0a9e4eSThomas Huth rmdir(data->workdir);
12450f0a9e4eSThomas Huth g_free(data->workdir);
12460f0a9e4eSThomas Huth
1247d47b83b1SDaniel P. Berrangé g_free(data);
1248d47b83b1SDaniel P. Berrangé }
1249d47b83b1SDaniel P. Berrangé #endif /* CONFIG_TASN1 */
125058d25e97SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
125158d25e97SDaniel P. Berrangé
migrate_postcopy_prepare(QTestState ** from_ptr,QTestState ** to_ptr,MigrateCommon * args)12521e8a1faeSThomas Huth static int migrate_postcopy_prepare(QTestState **from_ptr,
12531e8a1faeSThomas Huth QTestState **to_ptr,
1254d1a27b16SPeter Xu MigrateCommon *args)
12551e8a1faeSThomas Huth {
12561e8a1faeSThomas Huth QTestState *from, *to;
12571e8a1faeSThomas Huth
125806c48d6bSWei Wang if (test_migrate_start(&from, &to, "defer", &args->start)) {
12591e8a1faeSThomas Huth return -1;
12601e8a1faeSThomas Huth }
12611e8a1faeSThomas Huth
1262d1a27b16SPeter Xu if (args->start_hook) {
1263d1a27b16SPeter Xu args->postcopy_data = args->start_hook(from, to);
1264d1a27b16SPeter Xu }
1265d1a27b16SPeter Xu
12661e8a1faeSThomas Huth migrate_set_capability(from, "postcopy-ram", true);
12671e8a1faeSThomas Huth migrate_set_capability(to, "postcopy-ram", true);
12681e8a1faeSThomas Huth migrate_set_capability(to, "postcopy-blocktime", true);
12691e8a1faeSThomas Huth
12708f6fe915SPeter Xu if (args->postcopy_preempt) {
12718f6fe915SPeter Xu migrate_set_capability(from, "postcopy-preempt", true);
12728f6fe915SPeter Xu migrate_set_capability(to, "postcopy-preempt", true);
12738f6fe915SPeter Xu }
12748f6fe915SPeter Xu
1275886dfe9dSDaniel P. Berrangé migrate_ensure_non_converge(from);
12761e8a1faeSThomas Huth
1277e02f56e3SDaniel P. Berrangé migrate_prepare_for_dirty_mem(from);
127806c48d6bSWei Wang qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming',"
12798e3766eeSHet Gala " 'arguments': { "
12808e3766eeSHet Gala " 'channels': [ { 'channel-type': 'main',"
12818e3766eeSHet Gala " 'addr': { 'transport': 'socket',"
12828e3766eeSHet Gala " 'type': 'inet',"
12838e3766eeSHet Gala " 'host': '127.0.0.1',"
12848e3766eeSHet Gala " 'port': '0' } } ] } }");
1285e02f56e3SDaniel P. Berrangé
12861e8a1faeSThomas Huth /* Wait for the first serial output from the source */
12871e8a1faeSThomas Huth wait_for_serial("src_serial");
12882b58a8b9SSteve Sistare wait_for_suspend(from, &src_state);
12891e8a1faeSThomas Huth
1290d5ee387dSHet Gala migrate_qmp(from, to, NULL, NULL, "{}");
12911e8a1faeSThomas Huth
1292e02f56e3SDaniel P. Berrangé migrate_wait_for_dirty_mem(from, to);
12931e8a1faeSThomas Huth
12941e8a1faeSThomas Huth *from_ptr = from;
12951e8a1faeSThomas Huth *to_ptr = to;
12961e8a1faeSThomas Huth
12971e8a1faeSThomas Huth return 0;
12981e8a1faeSThomas Huth }
12991e8a1faeSThomas Huth
migrate_postcopy_complete(QTestState * from,QTestState * to,MigrateCommon * args)1300d1a27b16SPeter Xu static void migrate_postcopy_complete(QTestState *from, QTestState *to,
1301d1a27b16SPeter Xu MigrateCommon *args)
13021e8a1faeSThomas Huth {
13031e8a1faeSThomas Huth wait_for_migration_complete(from);
13041e8a1faeSThomas Huth
13052b58a8b9SSteve Sistare if (args->start.suspend_me) {
13062b58a8b9SSteve Sistare /* wakeup succeeds only if guest is suspended */
13072b58a8b9SSteve Sistare qtest_qmp_assert_success(to, "{'execute': 'system_wakeup'}");
13082b58a8b9SSteve Sistare }
13092b58a8b9SSteve Sistare
13101e8a1faeSThomas Huth /* Make sure we get at least one "B" on destination */
13111e8a1faeSThomas Huth wait_for_serial("dest_serial");
13121e8a1faeSThomas Huth
13131e8a1faeSThomas Huth if (uffd_feature_thread_id) {
13141e8a1faeSThomas Huth read_blocktime(to);
13151e8a1faeSThomas Huth }
13161e8a1faeSThomas Huth
1317d1a27b16SPeter Xu if (args->finish_hook) {
1318d1a27b16SPeter Xu args->finish_hook(from, to, args->postcopy_data);
1319d1a27b16SPeter Xu args->postcopy_data = NULL;
1320d1a27b16SPeter Xu }
1321d1a27b16SPeter Xu
13221e8a1faeSThomas Huth test_migrate_end(from, to, true);
13231e8a1faeSThomas Huth }
13241e8a1faeSThomas Huth
test_postcopy_common(MigrateCommon * args)1325d1a27b16SPeter Xu static void test_postcopy_common(MigrateCommon *args)
1326d1a27b16SPeter Xu {
1327d1a27b16SPeter Xu QTestState *from, *to;
1328d1a27b16SPeter Xu
1329d1a27b16SPeter Xu if (migrate_postcopy_prepare(&from, &to, args)) {
1330d1a27b16SPeter Xu return;
1331d1a27b16SPeter Xu }
1332d1a27b16SPeter Xu migrate_postcopy_start(from, to);
1333d1a27b16SPeter Xu migrate_postcopy_complete(from, to, args);
1334d1a27b16SPeter Xu }
1335d1a27b16SPeter Xu
test_postcopy(void)13361e8a1faeSThomas Huth static void test_postcopy(void)
13371e8a1faeSThomas Huth {
1338d1a27b16SPeter Xu MigrateCommon args = { };
13391e8a1faeSThomas Huth
1340d1a27b16SPeter Xu test_postcopy_common(&args);
13411e8a1faeSThomas Huth }
1342d1a27b16SPeter Xu
test_postcopy_suspend(void)13432b58a8b9SSteve Sistare static void test_postcopy_suspend(void)
13442b58a8b9SSteve Sistare {
13452b58a8b9SSteve Sistare MigrateCommon args = {
13462b58a8b9SSteve Sistare .start.suspend_me = true,
13472b58a8b9SSteve Sistare };
13482b58a8b9SSteve Sistare
13492b58a8b9SSteve Sistare test_postcopy_common(&args);
13502b58a8b9SSteve Sistare }
13512b58a8b9SSteve Sistare
test_postcopy_preempt(void)13528f6fe915SPeter Xu static void test_postcopy_preempt(void)
13538f6fe915SPeter Xu {
13548f6fe915SPeter Xu MigrateCommon args = {
13558f6fe915SPeter Xu .postcopy_preempt = true,
13568f6fe915SPeter Xu };
13578f6fe915SPeter Xu
13588f6fe915SPeter Xu test_postcopy_common(&args);
13598f6fe915SPeter Xu }
13608f6fe915SPeter Xu
1361d1a27b16SPeter Xu #ifdef CONFIG_GNUTLS
test_postcopy_tls_psk(void)1362d1a27b16SPeter Xu static void test_postcopy_tls_psk(void)
1363d1a27b16SPeter Xu {
1364d1a27b16SPeter Xu MigrateCommon args = {
1365d1a27b16SPeter Xu .start_hook = test_migrate_tls_psk_start_match,
1366d1a27b16SPeter Xu .finish_hook = test_migrate_tls_psk_finish,
1367d1a27b16SPeter Xu };
1368d1a27b16SPeter Xu
1369d1a27b16SPeter Xu test_postcopy_common(&args);
13701e8a1faeSThomas Huth }
13718f6fe915SPeter Xu
test_postcopy_preempt_tls_psk(void)13728f6fe915SPeter Xu static void test_postcopy_preempt_tls_psk(void)
13738f6fe915SPeter Xu {
13748f6fe915SPeter Xu MigrateCommon args = {
13758f6fe915SPeter Xu .postcopy_preempt = true,
13768f6fe915SPeter Xu .start_hook = test_migrate_tls_psk_start_match,
13778f6fe915SPeter Xu .finish_hook = test_migrate_tls_psk_finish,
13788f6fe915SPeter Xu };
13798f6fe915SPeter Xu
13808f6fe915SPeter Xu test_postcopy_common(&args);
13818f6fe915SPeter Xu }
1382d1a27b16SPeter Xu #endif
13831e8a1faeSThomas Huth
wait_for_postcopy_status(QTestState * one,const char * status)13847bca2bb7SFabiano Rosas static void wait_for_postcopy_status(QTestState *one, const char *status)
13857bca2bb7SFabiano Rosas {
13867bca2bb7SFabiano Rosas wait_for_migration_status(one, status,
1387*19e56616SFabiano Rosas (const char * []) {
1388*19e56616SFabiano Rosas "failed", "active",
1389*19e56616SFabiano Rosas "completed", NULL
1390*19e56616SFabiano Rosas });
13917bca2bb7SFabiano Rosas }
13927bca2bb7SFabiano Rosas
postcopy_recover_fail(QTestState * from,QTestState * to,PostcopyRecoveryFailStage stage)13936cf56a87SPeter Xu static void postcopy_recover_fail(QTestState *from, QTestState *to,
13946cf56a87SPeter Xu PostcopyRecoveryFailStage stage)
13957bca2bb7SFabiano Rosas {
13960fd39735SPeter Xu #ifndef _WIN32
13976cf56a87SPeter Xu bool fail_early = (stage == POSTCOPY_FAIL_CHANNEL_ESTABLISH);
13987bca2bb7SFabiano Rosas int ret, pair1[2], pair2[2];
13997bca2bb7SFabiano Rosas char c;
14007bca2bb7SFabiano Rosas
14016cf56a87SPeter Xu g_assert(stage > POSTCOPY_FAIL_NONE && stage < POSTCOPY_FAIL_MAX);
14026cf56a87SPeter Xu
14037bca2bb7SFabiano Rosas /* Create two unrelated socketpairs */
14047bca2bb7SFabiano Rosas ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair1);
14057bca2bb7SFabiano Rosas g_assert_cmpint(ret, ==, 0);
14067bca2bb7SFabiano Rosas
14077bca2bb7SFabiano Rosas ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair2);
14087bca2bb7SFabiano Rosas g_assert_cmpint(ret, ==, 0);
14097bca2bb7SFabiano Rosas
14107bca2bb7SFabiano Rosas /*
14117bca2bb7SFabiano Rosas * Give the guests unpaired ends of the sockets, so they'll all blocked
14127bca2bb7SFabiano Rosas * at reading. This mimics a wrong channel established.
14137bca2bb7SFabiano Rosas */
14147bca2bb7SFabiano Rosas qtest_qmp_fds_assert_success(from, &pair1[0], 1,
14157bca2bb7SFabiano Rosas "{ 'execute': 'getfd',"
14167bca2bb7SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
14177bca2bb7SFabiano Rosas qtest_qmp_fds_assert_success(to, &pair2[0], 1,
14187bca2bb7SFabiano Rosas "{ 'execute': 'getfd',"
14197bca2bb7SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
14207bca2bb7SFabiano Rosas
14217bca2bb7SFabiano Rosas /*
14227bca2bb7SFabiano Rosas * Write the 1st byte as QEMU_VM_COMMAND (0x8) for the dest socket, to
14237bca2bb7SFabiano Rosas * emulate the 1st byte of a real recovery, but stops from there to
14247bca2bb7SFabiano Rosas * keep dest QEMU in RECOVER. This is needed so that we can kick off
14257bca2bb7SFabiano Rosas * the recover process on dest QEMU (by triggering the G_IO_IN event).
14267bca2bb7SFabiano Rosas *
14277bca2bb7SFabiano Rosas * NOTE: this trick is not needed on src QEMUs, because src doesn't
14287bca2bb7SFabiano Rosas * rely on an pre-existing G_IO_IN event, so it will always trigger the
14297bca2bb7SFabiano Rosas * upcoming recovery anyway even if it can read nothing.
14307bca2bb7SFabiano Rosas */
14317bca2bb7SFabiano Rosas #define QEMU_VM_COMMAND 0x08
14327bca2bb7SFabiano Rosas c = QEMU_VM_COMMAND;
14337bca2bb7SFabiano Rosas ret = send(pair2[1], &c, 1, 0);
14347bca2bb7SFabiano Rosas g_assert_cmpint(ret, ==, 1);
14357bca2bb7SFabiano Rosas
14366cf56a87SPeter Xu if (stage == POSTCOPY_FAIL_CHANNEL_ESTABLISH) {
14376cf56a87SPeter Xu /*
14386cf56a87SPeter Xu * This will make src QEMU to fail at an early stage when trying to
14396cf56a87SPeter Xu * resume later, where it shouldn't reach RECOVER stage at all.
14406cf56a87SPeter Xu */
14416cf56a87SPeter Xu close(pair1[1]);
14426cf56a87SPeter Xu }
14436cf56a87SPeter Xu
14447bca2bb7SFabiano Rosas migrate_recover(to, "fd:fd-mig");
1445d5ee387dSHet Gala migrate_qmp(from, to, "fd:fd-mig", NULL, "{'resume': true}");
14467bca2bb7SFabiano Rosas
14477bca2bb7SFabiano Rosas /*
14488dbd24d3SPeter Xu * Source QEMU has an extra RECOVER_SETUP phase, dest doesn't have it.
14498dbd24d3SPeter Xu * Make sure it appears along the way.
14508dbd24d3SPeter Xu */
14518dbd24d3SPeter Xu migration_event_wait(from, "postcopy-recover-setup");
14528dbd24d3SPeter Xu
14536cf56a87SPeter Xu if (fail_early) {
14548dbd24d3SPeter Xu /*
14556cf56a87SPeter Xu * When fails at reconnection, src QEMU will automatically goes
14566cf56a87SPeter Xu * back to PAUSED state. Making sure there is an event in this
14576cf56a87SPeter Xu * case: Libvirt relies on this to detect early reconnection
14586cf56a87SPeter Xu * errors.
14597bca2bb7SFabiano Rosas */
14606cf56a87SPeter Xu migration_event_wait(from, "postcopy-paused");
14616cf56a87SPeter Xu } else {
14626cf56a87SPeter Xu /*
14636cf56a87SPeter Xu * We want to test "fail later" at RECOVER stage here. Make sure
14646cf56a87SPeter Xu * both QEMU instances will go into RECOVER stage first, then test
14656cf56a87SPeter Xu * kicking them out using migrate-pause.
14666cf56a87SPeter Xu *
14676cf56a87SPeter Xu * Explicitly check the RECOVER event on src, that's what Libvirt
14686cf56a87SPeter Xu * relies on, rather than polling.
14696cf56a87SPeter Xu */
14706cf56a87SPeter Xu migration_event_wait(from, "postcopy-recover");
14717bca2bb7SFabiano Rosas wait_for_postcopy_status(from, "postcopy-recover");
14726cf56a87SPeter Xu
14736cf56a87SPeter Xu /* Need an explicit kick on src QEMU in this case */
14746cf56a87SPeter Xu migrate_pause(from);
14756cf56a87SPeter Xu }
14766cf56a87SPeter Xu
14776cf56a87SPeter Xu /*
14786cf56a87SPeter Xu * For all failure cases, we'll reach such states on both sides now.
14796cf56a87SPeter Xu * Check them.
14806cf56a87SPeter Xu */
14816cf56a87SPeter Xu wait_for_postcopy_status(from, "postcopy-paused");
14827bca2bb7SFabiano Rosas wait_for_postcopy_status(to, "postcopy-recover");
14837bca2bb7SFabiano Rosas
14847bca2bb7SFabiano Rosas /*
14856cf56a87SPeter Xu * Kick dest QEMU out too. This is normally not needed in reality
14866cf56a87SPeter Xu * because when the channel is shutdown it should also happen on src.
14876cf56a87SPeter Xu * However here we used separate socket pairs so we need to do that
14886cf56a87SPeter Xu * explicitly.
14897bca2bb7SFabiano Rosas */
14907bca2bb7SFabiano Rosas migrate_pause(to);
14917bca2bb7SFabiano Rosas wait_for_postcopy_status(to, "postcopy-paused");
14927bca2bb7SFabiano Rosas
14937bca2bb7SFabiano Rosas close(pair1[0]);
14947bca2bb7SFabiano Rosas close(pair2[0]);
14957bca2bb7SFabiano Rosas close(pair2[1]);
14966cf56a87SPeter Xu
14976cf56a87SPeter Xu if (stage != POSTCOPY_FAIL_CHANNEL_ESTABLISH) {
14986cf56a87SPeter Xu close(pair1[1]);
14996cf56a87SPeter Xu }
15000fd39735SPeter Xu #endif
15017bca2bb7SFabiano Rosas }
15027bca2bb7SFabiano Rosas
test_postcopy_recovery_common(MigrateCommon * args)1503767fa9cfSPeter Xu static void test_postcopy_recovery_common(MigrateCommon *args)
15041e8a1faeSThomas Huth {
15051e8a1faeSThomas Huth QTestState *from, *to;
1506ff7b9b56SPeter Maydell g_autofree char *uri = NULL;
15071e8a1faeSThomas Huth
1508767fa9cfSPeter Xu /* Always hide errors for postcopy recover tests since they're expected */
1509767fa9cfSPeter Xu args->start.hide_stderr = true;
1510767fa9cfSPeter Xu
1511767fa9cfSPeter Xu if (migrate_postcopy_prepare(&from, &to, args)) {
15121e8a1faeSThomas Huth return;
15131e8a1faeSThomas Huth }
15141e8a1faeSThomas Huth
15151e8a1faeSThomas Huth /* Turn postcopy speed down, 4K/s is slow enough on any machines */
15161e8a1faeSThomas Huth migrate_set_parameter_int(from, "max-postcopy-bandwidth", 4096);
15171e8a1faeSThomas Huth
15181e8a1faeSThomas Huth /* Now we start the postcopy */
15191e8a1faeSThomas Huth migrate_postcopy_start(from, to);
15201e8a1faeSThomas Huth
15211e8a1faeSThomas Huth /*
15221e8a1faeSThomas Huth * Wait until postcopy is really started; we can only run the
15231e8a1faeSThomas Huth * migrate-pause command during a postcopy
15241e8a1faeSThomas Huth */
15251e8a1faeSThomas Huth wait_for_migration_status(from, "postcopy-active", NULL);
15261e8a1faeSThomas Huth
15271e8a1faeSThomas Huth /*
15281e8a1faeSThomas Huth * Manually stop the postcopy migration. This emulates a network
15291e8a1faeSThomas Huth * failure with the migration socket
15301e8a1faeSThomas Huth */
15311e8a1faeSThomas Huth migrate_pause(from);
15321e8a1faeSThomas Huth
15331e8a1faeSThomas Huth /*
15341e8a1faeSThomas Huth * Wait for destination side to reach postcopy-paused state. The
15351e8a1faeSThomas Huth * migrate-recover command can only succeed if destination machine
15361e8a1faeSThomas Huth * is in the paused state
15371e8a1faeSThomas Huth */
15387bca2bb7SFabiano Rosas wait_for_postcopy_status(to, "postcopy-paused");
15397bca2bb7SFabiano Rosas wait_for_postcopy_status(from, "postcopy-paused");
15407bca2bb7SFabiano Rosas
15416cf56a87SPeter Xu if (args->postcopy_recovery_fail_stage) {
15427bca2bb7SFabiano Rosas /*
15437bca2bb7SFabiano Rosas * Test when a wrong socket specified for recover, and then the
15447bca2bb7SFabiano Rosas * ability to kick it out, and continue with a correct socket.
15457bca2bb7SFabiano Rosas */
15466cf56a87SPeter Xu postcopy_recover_fail(from, to, args->postcopy_recovery_fail_stage);
15477bca2bb7SFabiano Rosas /* continue with a good recovery */
15487bca2bb7SFabiano Rosas }
15491e8a1faeSThomas Huth
15501e8a1faeSThomas Huth /*
15511e8a1faeSThomas Huth * Create a new socket to emulate a new channel that is different
15521e8a1faeSThomas Huth * from the broken migration channel; tell the destination to
15531e8a1faeSThomas Huth * listen to the new port
15541e8a1faeSThomas Huth */
15551e8a1faeSThomas Huth uri = g_strdup_printf("unix:%s/migsocket-recover", tmpfs);
15561e8a1faeSThomas Huth migrate_recover(to, uri);
15571e8a1faeSThomas Huth
15581e8a1faeSThomas Huth /*
15591e8a1faeSThomas Huth * Try to rebuild the migration channel using the resume flag and
15601e8a1faeSThomas Huth * the newly created channel
15611e8a1faeSThomas Huth */
1562d5ee387dSHet Gala migrate_qmp(from, to, uri, NULL, "{'resume': true}");
15631e8a1faeSThomas Huth
15641e8a1faeSThomas Huth /* Restore the postcopy bandwidth to unlimited */
15651e8a1faeSThomas Huth migrate_set_parameter_int(from, "max-postcopy-bandwidth", 0);
15661e8a1faeSThomas Huth
1567767fa9cfSPeter Xu migrate_postcopy_complete(from, to, args);
15681e8a1faeSThomas Huth }
15691e8a1faeSThomas Huth
test_postcopy_recovery(void)1570767fa9cfSPeter Xu static void test_postcopy_recovery(void)
1571767fa9cfSPeter Xu {
1572767fa9cfSPeter Xu MigrateCommon args = { };
1573767fa9cfSPeter Xu
1574767fa9cfSPeter Xu test_postcopy_recovery_common(&args);
1575767fa9cfSPeter Xu }
1576767fa9cfSPeter Xu
test_postcopy_recovery_fail_handshake(void)15776cf56a87SPeter Xu static void test_postcopy_recovery_fail_handshake(void)
15787bca2bb7SFabiano Rosas {
15797bca2bb7SFabiano Rosas MigrateCommon args = {
15806cf56a87SPeter Xu .postcopy_recovery_fail_stage = POSTCOPY_FAIL_RECOVERY,
15816cf56a87SPeter Xu };
15826cf56a87SPeter Xu
15836cf56a87SPeter Xu test_postcopy_recovery_common(&args);
15846cf56a87SPeter Xu }
15856cf56a87SPeter Xu
test_postcopy_recovery_fail_reconnect(void)15866cf56a87SPeter Xu static void test_postcopy_recovery_fail_reconnect(void)
15876cf56a87SPeter Xu {
15886cf56a87SPeter Xu MigrateCommon args = {
15896cf56a87SPeter Xu .postcopy_recovery_fail_stage = POSTCOPY_FAIL_CHANNEL_ESTABLISH,
15907bca2bb7SFabiano Rosas };
15917bca2bb7SFabiano Rosas
15927bca2bb7SFabiano Rosas test_postcopy_recovery_common(&args);
15937bca2bb7SFabiano Rosas }
15947bca2bb7SFabiano Rosas
1595767fa9cfSPeter Xu #ifdef CONFIG_GNUTLS
test_postcopy_recovery_tls_psk(void)1596767fa9cfSPeter Xu static void test_postcopy_recovery_tls_psk(void)
1597767fa9cfSPeter Xu {
1598767fa9cfSPeter Xu MigrateCommon args = {
1599767fa9cfSPeter Xu .start_hook = test_migrate_tls_psk_start_match,
1600767fa9cfSPeter Xu .finish_hook = test_migrate_tls_psk_finish,
1601767fa9cfSPeter Xu };
1602767fa9cfSPeter Xu
1603767fa9cfSPeter Xu test_postcopy_recovery_common(&args);
1604767fa9cfSPeter Xu }
1605767fa9cfSPeter Xu #endif
1606767fa9cfSPeter Xu
test_postcopy_preempt_recovery(void)16078f6fe915SPeter Xu static void test_postcopy_preempt_recovery(void)
16088f6fe915SPeter Xu {
16098f6fe915SPeter Xu MigrateCommon args = {
16108f6fe915SPeter Xu .postcopy_preempt = true,
16118f6fe915SPeter Xu };
16128f6fe915SPeter Xu
16138f6fe915SPeter Xu test_postcopy_recovery_common(&args);
16148f6fe915SPeter Xu }
16158f6fe915SPeter Xu
16168f6fe915SPeter Xu #ifdef CONFIG_GNUTLS
16178f6fe915SPeter Xu /* This contains preempt+recovery+tls test altogether */
test_postcopy_preempt_all(void)16188f6fe915SPeter Xu static void test_postcopy_preempt_all(void)
16198f6fe915SPeter Xu {
16208f6fe915SPeter Xu MigrateCommon args = {
16218f6fe915SPeter Xu .postcopy_preempt = true,
16228f6fe915SPeter Xu .start_hook = test_migrate_tls_psk_start_match,
16238f6fe915SPeter Xu .finish_hook = test_migrate_tls_psk_finish,
16248f6fe915SPeter Xu };
16258f6fe915SPeter Xu
16268f6fe915SPeter Xu test_postcopy_recovery_common(&args);
16278f6fe915SPeter Xu }
1628dc066da8SLukas Straub
16298f6fe915SPeter Xu #endif
16308f6fe915SPeter Xu
test_baddest(void)16311e8a1faeSThomas Huth static void test_baddest(void)
16321e8a1faeSThomas Huth {
163319da6edfSDaniel P. Berrangé MigrateStart args = {
163419da6edfSDaniel P. Berrangé .hide_stderr = true
163519da6edfSDaniel P. Berrangé };
16361e8a1faeSThomas Huth QTestState *from, *to;
16371e8a1faeSThomas Huth
16383ff57401SPeter Xu if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
16391e8a1faeSThomas Huth return;
16401e8a1faeSThomas Huth }
1641d5ee387dSHet Gala migrate_qmp(from, to, "tcp:127.0.0.1:0", NULL, "{}");
16421e8a1faeSThomas Huth wait_for_migration_fail(from, false);
16431e8a1faeSThomas Huth test_migrate_end(from, to, false);
16441e8a1faeSThomas Huth }
16451e8a1faeSThomas Huth
1646d864756eSFabiano Rosas #ifndef _WIN32
test_analyze_script(void)1647d864756eSFabiano Rosas static void test_analyze_script(void)
1648d864756eSFabiano Rosas {
1649d864756eSFabiano Rosas MigrateStart args = {
1650d864756eSFabiano Rosas .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
1651d864756eSFabiano Rosas };
1652d864756eSFabiano Rosas QTestState *from, *to;
1653d864756eSFabiano Rosas g_autofree char *uri = NULL;
1654d864756eSFabiano Rosas g_autofree char *file = NULL;
1655d864756eSFabiano Rosas int pid, wstatus;
1656d864756eSFabiano Rosas const char *python = g_getenv("PYTHON");
1657d864756eSFabiano Rosas
1658d864756eSFabiano Rosas if (!python) {
1659d864756eSFabiano Rosas g_test_skip("PYTHON variable not set");
1660d864756eSFabiano Rosas return;
1661d864756eSFabiano Rosas }
1662d864756eSFabiano Rosas
1663d864756eSFabiano Rosas /* dummy url */
1664d864756eSFabiano Rosas if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
1665d864756eSFabiano Rosas return;
1666d864756eSFabiano Rosas }
1667d864756eSFabiano Rosas
1668d864756eSFabiano Rosas /*
1669d864756eSFabiano Rosas * Setting these two capabilities causes the "configuration"
1670d864756eSFabiano Rosas * vmstate to include subsections for them. The script needs to
1671d864756eSFabiano Rosas * parse those subsections properly.
1672d864756eSFabiano Rosas */
1673d864756eSFabiano Rosas migrate_set_capability(from, "validate-uuid", true);
1674d864756eSFabiano Rosas migrate_set_capability(from, "x-ignore-shared", true);
1675d864756eSFabiano Rosas
1676d864756eSFabiano Rosas file = g_strdup_printf("%s/migfile", tmpfs);
1677d864756eSFabiano Rosas uri = g_strdup_printf("exec:cat > %s", file);
1678d864756eSFabiano Rosas
1679d864756eSFabiano Rosas migrate_ensure_converge(from);
1680d5ee387dSHet Gala migrate_qmp(from, to, uri, NULL, "{}");
1681d864756eSFabiano Rosas wait_for_migration_complete(from);
1682d864756eSFabiano Rosas
1683d864756eSFabiano Rosas pid = fork();
1684d864756eSFabiano Rosas if (!pid) {
1685d864756eSFabiano Rosas close(1);
1686d864756eSFabiano Rosas open("/dev/null", O_WRONLY);
1687d864756eSFabiano Rosas execl(python, python, ANALYZE_SCRIPT, "-f", file, NULL);
1688d864756eSFabiano Rosas g_assert_not_reached();
1689d864756eSFabiano Rosas }
1690d864756eSFabiano Rosas
1691d864756eSFabiano Rosas g_assert(waitpid(pid, &wstatus, 0) == pid);
16928f023a0bSThomas Huth if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
1693d864756eSFabiano Rosas g_test_message("Failed to analyze the migration stream");
1694d864756eSFabiano Rosas g_test_fail();
1695d864756eSFabiano Rosas }
1696d864756eSFabiano Rosas test_migrate_end(from, to, false);
1697d864756eSFabiano Rosas cleanup("migfile");
1698d864756eSFabiano Rosas }
1699d864756eSFabiano Rosas #endif
1700d864756eSFabiano Rosas
test_precopy_common(MigrateCommon * args)1701ffed54f6SDaniel P. Berrangé static void test_precopy_common(MigrateCommon *args)
17021e8a1faeSThomas Huth {
17031e8a1faeSThomas Huth QTestState *from, *to;
1704b3caa7b5SDaniel P. Berrangé void *data_hook = NULL;
17051e8a1faeSThomas Huth
1706ffed54f6SDaniel P. Berrangé if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
17071e8a1faeSThomas Huth return;
17081e8a1faeSThomas Huth }
17091e8a1faeSThomas Huth
1710b3caa7b5SDaniel P. Berrangé if (args->start_hook) {
1711b3caa7b5SDaniel P. Berrangé data_hook = args->start_hook(from, to);
1712b3caa7b5SDaniel P. Berrangé }
1713b3caa7b5SDaniel P. Berrangé
17141e8a1faeSThomas Huth /* Wait for the first serial output from the source */
1715e25636a1SThomas Huth if (args->result == MIG_TEST_SUCCEED) {
17161e8a1faeSThomas Huth wait_for_serial("src_serial");
1717b1fdd21eSSteve Sistare wait_for_suspend(from, &src_state);
1718e25636a1SThomas Huth }
17191e8a1faeSThomas Huth
17203c4fb177SDaniel P. Berrangé if (args->live) {
17213c4fb177SDaniel P. Berrangé migrate_ensure_non_converge(from);
1722e02f56e3SDaniel P. Berrangé migrate_prepare_for_dirty_mem(from);
17233c4fb177SDaniel P. Berrangé } else {
17243c4fb177SDaniel P. Berrangé /*
17253c4fb177SDaniel P. Berrangé * Testing non-live migration, we allow it to run at
17263c4fb177SDaniel P. Berrangé * full speed to ensure short test case duration.
17273c4fb177SDaniel P. Berrangé * For tests expected to fail, we don't need to
17283c4fb177SDaniel P. Berrangé * change anything.
17293c4fb177SDaniel P. Berrangé */
17303c4fb177SDaniel P. Berrangé if (args->result == MIG_TEST_SUCCEED) {
17313c4fb177SDaniel P. Berrangé qtest_qmp_assert_success(from, "{ 'execute' : 'stop'}");
1732f0649758SSteve Sistare wait_for_stop(from, &src_state);
17333c4fb177SDaniel P. Berrangé migrate_ensure_converge(from);
17343c4fb177SDaniel P. Berrangé }
17353c4fb177SDaniel P. Berrangé }
17363c4fb177SDaniel P. Berrangé
17375274274cSFabiano Rosas if (args->result == MIG_TEST_QMP_ERROR) {
1738bc6307a5SHet Gala migrate_qmp_fail(from, args->connect_uri, args->connect_channels, "{}");
17395274274cSFabiano Rosas goto finish;
17405274274cSFabiano Rosas }
17415274274cSFabiano Rosas
17429d36d62cSHet Gala migrate_qmp(from, to, args->connect_uri, args->connect_channels, "{}");
17431e8a1faeSThomas Huth
174400fbe7f6SDaniel P. Berrangé if (args->result != MIG_TEST_SUCCEED) {
174500fbe7f6SDaniel P. Berrangé bool allow_active = args->result == MIG_TEST_FAIL;
174600fbe7f6SDaniel P. Berrangé wait_for_migration_fail(from, allow_active);
174700fbe7f6SDaniel P. Berrangé
174800fbe7f6SDaniel P. Berrangé if (args->result == MIG_TEST_FAIL_DEST_QUIT_ERR) {
17491b0f1b14SBin Meng qtest_set_expected_status(to, EXIT_FAILURE);
175000fbe7f6SDaniel P. Berrangé }
175100fbe7f6SDaniel P. Berrangé } else {
17523c4fb177SDaniel P. Berrangé if (args->live) {
1753e02f56e3SDaniel P. Berrangé /*
1754e02f56e3SDaniel P. Berrangé * For initial iteration(s) we must do a full pass,
1755e02f56e3SDaniel P. Berrangé * but for the final iteration, we need only wait
1756e02f56e3SDaniel P. Berrangé * for some dirty mem before switching to converge
1757e02f56e3SDaniel P. Berrangé */
1758e02f56e3SDaniel P. Berrangé while (args->iterations > 1) {
17591e8a1faeSThomas Huth wait_for_migration_pass(from);
1760e02f56e3SDaniel P. Berrangé args->iterations--;
176183bcba1eSDaniel P. Berrangé }
1762e02f56e3SDaniel P. Berrangé migrate_wait_for_dirty_mem(from, to);
17631e8a1faeSThomas Huth
1764886dfe9dSDaniel P. Berrangé migrate_ensure_converge(from);
17651e8a1faeSThomas Huth
17663c4fb177SDaniel P. Berrangé /*
17673c4fb177SDaniel P. Berrangé * We do this first, as it has a timeout to stop us
17683c4fb177SDaniel P. Berrangé * hanging forever if migration didn't converge
17693c4fb177SDaniel P. Berrangé */
17708d4e897aSDaniel P. Berrangé wait_for_migration_complete(from);
17718d4e897aSDaniel P. Berrangé
1772f0649758SSteve Sistare wait_for_stop(from, &src_state);
1773f0649758SSteve Sistare
17743c4fb177SDaniel P. Berrangé } else {
17753c4fb177SDaniel P. Berrangé wait_for_migration_complete(from);
17763c4fb177SDaniel P. Berrangé /*
17773c4fb177SDaniel P. Berrangé * Must wait for dst to finish reading all incoming
17783c4fb177SDaniel P. Berrangé * data on the socket before issuing 'cont' otherwise
17793c4fb177SDaniel P. Berrangé * it'll be ignored
17803c4fb177SDaniel P. Berrangé */
17813c4fb177SDaniel P. Berrangé wait_for_migration_complete(to);
17821e8a1faeSThomas Huth
17833c4fb177SDaniel P. Berrangé qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
17843c4fb177SDaniel P. Berrangé }
17853c4fb177SDaniel P. Berrangé
1786f0649758SSteve Sistare wait_for_resume(to, &dst_state);
17871e8a1faeSThomas Huth
1788b1fdd21eSSteve Sistare if (args->start.suspend_me) {
1789b1fdd21eSSteve Sistare /* wakeup succeeds only if guest is suspended */
1790b1fdd21eSSteve Sistare qtest_qmp_assert_success(to, "{'execute': 'system_wakeup'}");
1791b1fdd21eSSteve Sistare }
1792b1fdd21eSSteve Sistare
17931e8a1faeSThomas Huth wait_for_serial("dest_serial");
179400fbe7f6SDaniel P. Berrangé }
17951e8a1faeSThomas Huth
17965274274cSFabiano Rosas finish:
1797b3caa7b5SDaniel P. Berrangé if (args->finish_hook) {
1798b3caa7b5SDaniel P. Berrangé args->finish_hook(from, to, data_hook);
1799b3caa7b5SDaniel P. Berrangé }
1800b3caa7b5SDaniel P. Berrangé
180100fbe7f6SDaniel P. Berrangé test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
18021e8a1faeSThomas Huth }
18031e8a1faeSThomas Huth
file_dirty_offset_region(void)180455fc0c2fSFabiano Rosas static void file_dirty_offset_region(void)
180555fc0c2fSFabiano Rosas {
180655fc0c2fSFabiano Rosas g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
180755fc0c2fSFabiano Rosas size_t size = FILE_TEST_OFFSET;
180855fc0c2fSFabiano Rosas g_autofree char *data = g_new0(char, size);
180955fc0c2fSFabiano Rosas
181055fc0c2fSFabiano Rosas memset(data, FILE_TEST_MARKER, size);
181155fc0c2fSFabiano Rosas g_assert(g_file_set_contents(path, data, size, NULL));
181255fc0c2fSFabiano Rosas }
181355fc0c2fSFabiano Rosas
file_check_offset_region(void)181455fc0c2fSFabiano Rosas static void file_check_offset_region(void)
181555fc0c2fSFabiano Rosas {
181655fc0c2fSFabiano Rosas g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
181755fc0c2fSFabiano Rosas size_t size = FILE_TEST_OFFSET;
181855fc0c2fSFabiano Rosas g_autofree char *expected = g_new0(char, size);
181955fc0c2fSFabiano Rosas g_autofree char *actual = NULL;
182055fc0c2fSFabiano Rosas uint64_t *stream_start;
182155fc0c2fSFabiano Rosas
182255fc0c2fSFabiano Rosas /*
182355fc0c2fSFabiano Rosas * Ensure the skipped offset region's data has not been touched
182455fc0c2fSFabiano Rosas * and the migration stream starts at the right place.
182555fc0c2fSFabiano Rosas */
182655fc0c2fSFabiano Rosas
182755fc0c2fSFabiano Rosas memset(expected, FILE_TEST_MARKER, size);
182855fc0c2fSFabiano Rosas
182955fc0c2fSFabiano Rosas g_assert(g_file_get_contents(path, &actual, NULL, NULL));
183055fc0c2fSFabiano Rosas g_assert(!memcmp(actual, expected, size));
183155fc0c2fSFabiano Rosas
183255fc0c2fSFabiano Rosas stream_start = (uint64_t *)(actual + size);
183355fc0c2fSFabiano Rosas g_assert_cmpint(cpu_to_be64(*stream_start) >> 32, ==, QEMU_VM_FILE_MAGIC);
183455fc0c2fSFabiano Rosas }
183555fc0c2fSFabiano Rosas
test_file_common(MigrateCommon * args,bool stop_src)18363dc35470SFabiano Rosas static void test_file_common(MigrateCommon *args, bool stop_src)
18373dc35470SFabiano Rosas {
18383dc35470SFabiano Rosas QTestState *from, *to;
18393dc35470SFabiano Rosas void *data_hook = NULL;
184055fc0c2fSFabiano Rosas bool check_offset = false;
18413dc35470SFabiano Rosas
18423dc35470SFabiano Rosas if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
18433dc35470SFabiano Rosas return;
18443dc35470SFabiano Rosas }
18453dc35470SFabiano Rosas
18463dc35470SFabiano Rosas /*
18473dc35470SFabiano Rosas * File migration is never live. We can keep the source VM running
18483dc35470SFabiano Rosas * during migration, but the destination will not be running
18493dc35470SFabiano Rosas * concurrently.
18503dc35470SFabiano Rosas */
18513dc35470SFabiano Rosas g_assert_false(args->live);
18523dc35470SFabiano Rosas
185355fc0c2fSFabiano Rosas if (g_strrstr(args->connect_uri, "offset=")) {
185455fc0c2fSFabiano Rosas check_offset = true;
185555fc0c2fSFabiano Rosas /*
185655fc0c2fSFabiano Rosas * This comes before the start_hook because it's equivalent to
185755fc0c2fSFabiano Rosas * a management application creating the file and writing to
185855fc0c2fSFabiano Rosas * it so hooks should expect the file to be already present.
185955fc0c2fSFabiano Rosas */
186055fc0c2fSFabiano Rosas file_dirty_offset_region();
186155fc0c2fSFabiano Rosas }
186255fc0c2fSFabiano Rosas
18633dc35470SFabiano Rosas if (args->start_hook) {
18643dc35470SFabiano Rosas data_hook = args->start_hook(from, to);
18653dc35470SFabiano Rosas }
18663dc35470SFabiano Rosas
18673dc35470SFabiano Rosas migrate_ensure_converge(from);
18683dc35470SFabiano Rosas wait_for_serial("src_serial");
18693dc35470SFabiano Rosas
18703dc35470SFabiano Rosas if (stop_src) {
18713dc35470SFabiano Rosas qtest_qmp_assert_success(from, "{ 'execute' : 'stop'}");
1872f0649758SSteve Sistare wait_for_stop(from, &src_state);
18733dc35470SFabiano Rosas }
18743dc35470SFabiano Rosas
18753dc35470SFabiano Rosas if (args->result == MIG_TEST_QMP_ERROR) {
1876387dc407SHet Gala migrate_qmp_fail(from, args->connect_uri, NULL, "{}");
18773dc35470SFabiano Rosas goto finish;
18783dc35470SFabiano Rosas }
18793dc35470SFabiano Rosas
1880d5ee387dSHet Gala migrate_qmp(from, to, args->connect_uri, NULL, "{}");
18813dc35470SFabiano Rosas wait_for_migration_complete(from);
18823dc35470SFabiano Rosas
18833dc35470SFabiano Rosas /*
18843dc35470SFabiano Rosas * We need to wait for the source to finish before starting the
18853dc35470SFabiano Rosas * destination.
18863dc35470SFabiano Rosas */
1887d1155fd4SHet Gala migrate_incoming_qmp(to, args->connect_uri, "{}");
18883dc35470SFabiano Rosas wait_for_migration_complete(to);
18893dc35470SFabiano Rosas
18903dc35470SFabiano Rosas if (stop_src) {
18913dc35470SFabiano Rosas qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
18923dc35470SFabiano Rosas }
1893f0649758SSteve Sistare wait_for_resume(to, &dst_state);
18943dc35470SFabiano Rosas
18953dc35470SFabiano Rosas wait_for_serial("dest_serial");
18963dc35470SFabiano Rosas
189755fc0c2fSFabiano Rosas if (check_offset) {
189855fc0c2fSFabiano Rosas file_check_offset_region();
189955fc0c2fSFabiano Rosas }
190055fc0c2fSFabiano Rosas
19013dc35470SFabiano Rosas finish:
19023dc35470SFabiano Rosas if (args->finish_hook) {
19033dc35470SFabiano Rosas args->finish_hook(from, to, data_hook);
19043dc35470SFabiano Rosas }
19053dc35470SFabiano Rosas
19063dc35470SFabiano Rosas test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
19073dc35470SFabiano Rosas }
19083dc35470SFabiano Rosas
test_precopy_unix_plain(void)190958d25e97SDaniel P. Berrangé static void test_precopy_unix_plain(void)
19101f546b70SPeter Xu {
1911ffed54f6SDaniel P. Berrangé g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1912ffed54f6SDaniel P. Berrangé MigrateCommon args = {
1913ffed54f6SDaniel P. Berrangé .listen_uri = uri,
1914ffed54f6SDaniel P. Berrangé .connect_uri = uri,
1915b861383cSPeter Xu /*
1916b861383cSPeter Xu * The simplest use case of precopy, covering smoke tests of
1917b861383cSPeter Xu * get-dirty-log dirty tracking.
1918b861383cSPeter Xu */
19193c4fb177SDaniel P. Berrangé .live = true,
1920ffed54f6SDaniel P. Berrangé };
1921ffed54f6SDaniel P. Berrangé
1922ffed54f6SDaniel P. Berrangé test_precopy_common(&args);
19231f546b70SPeter Xu }
19241f546b70SPeter Xu
test_precopy_unix_suspend_live(void)1925b1fdd21eSSteve Sistare static void test_precopy_unix_suspend_live(void)
1926b1fdd21eSSteve Sistare {
1927b1fdd21eSSteve Sistare g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1928b1fdd21eSSteve Sistare MigrateCommon args = {
1929b1fdd21eSSteve Sistare .listen_uri = uri,
1930b1fdd21eSSteve Sistare .connect_uri = uri,
1931b1fdd21eSSteve Sistare /*
1932b1fdd21eSSteve Sistare * despite being live, the test is fast because the src
1933b1fdd21eSSteve Sistare * suspends immediately.
1934b1fdd21eSSteve Sistare */
1935b1fdd21eSSteve Sistare .live = true,
1936b1fdd21eSSteve Sistare .start.suspend_me = true,
1937b1fdd21eSSteve Sistare };
1938b1fdd21eSSteve Sistare
1939b1fdd21eSSteve Sistare test_precopy_common(&args);
1940b1fdd21eSSteve Sistare }
1941b1fdd21eSSteve Sistare
test_precopy_unix_suspend_notlive(void)1942b1fdd21eSSteve Sistare static void test_precopy_unix_suspend_notlive(void)
1943b1fdd21eSSteve Sistare {
1944b1fdd21eSSteve Sistare g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1945b1fdd21eSSteve Sistare MigrateCommon args = {
1946b1fdd21eSSteve Sistare .listen_uri = uri,
1947b1fdd21eSSteve Sistare .connect_uri = uri,
1948b1fdd21eSSteve Sistare .start.suspend_me = true,
1949b1fdd21eSSteve Sistare };
1950b1fdd21eSSteve Sistare
1951b1fdd21eSSteve Sistare test_precopy_common(&args);
1952b1fdd21eSSteve Sistare }
195358d25e97SDaniel P. Berrangé
test_precopy_unix_dirty_ring(void)19541f546b70SPeter Xu static void test_precopy_unix_dirty_ring(void)
19551f546b70SPeter Xu {
1956ffed54f6SDaniel P. Berrangé g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1957ffed54f6SDaniel P. Berrangé MigrateCommon args = {
1958ffed54f6SDaniel P. Berrangé .start = {
1959ffed54f6SDaniel P. Berrangé .use_dirty_ring = true,
1960ffed54f6SDaniel P. Berrangé },
1961ffed54f6SDaniel P. Berrangé .listen_uri = uri,
1962ffed54f6SDaniel P. Berrangé .connect_uri = uri,
1963b861383cSPeter Xu /*
1964b861383cSPeter Xu * Besides the precopy/unix basic test, cover dirty ring interface
1965b861383cSPeter Xu * rather than get-dirty-log.
1966b861383cSPeter Xu */
19673c4fb177SDaniel P. Berrangé .live = true,
1968ffed54f6SDaniel P. Berrangé };
1969ffed54f6SDaniel P. Berrangé
1970ffed54f6SDaniel P. Berrangé test_precopy_common(&args);
19711f546b70SPeter Xu }
19721f546b70SPeter Xu
1973d47b83b1SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
test_precopy_unix_tls_psk(void)1974d47b83b1SDaniel P. Berrangé static void test_precopy_unix_tls_psk(void)
1975d47b83b1SDaniel P. Berrangé {
1976d47b83b1SDaniel P. Berrangé g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1977d47b83b1SDaniel P. Berrangé MigrateCommon args = {
1978d47b83b1SDaniel P. Berrangé .connect_uri = uri,
1979d47b83b1SDaniel P. Berrangé .listen_uri = uri,
1980d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_psk_start_match,
1981d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_psk_finish,
1982d47b83b1SDaniel P. Berrangé };
1983d47b83b1SDaniel P. Berrangé
1984d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
1985d47b83b1SDaniel P. Berrangé }
1986d47b83b1SDaniel P. Berrangé
1987d47b83b1SDaniel P. Berrangé #ifdef CONFIG_TASN1
test_precopy_unix_tls_x509_default_host(void)1988d47b83b1SDaniel P. Berrangé static void test_precopy_unix_tls_x509_default_host(void)
1989d47b83b1SDaniel P. Berrangé {
1990d47b83b1SDaniel P. Berrangé g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1991d47b83b1SDaniel P. Berrangé MigrateCommon args = {
1992d47b83b1SDaniel P. Berrangé .start = {
1993d47b83b1SDaniel P. Berrangé .hide_stderr = true,
1994d47b83b1SDaniel P. Berrangé },
1995d47b83b1SDaniel P. Berrangé .connect_uri = uri,
1996d47b83b1SDaniel P. Berrangé .listen_uri = uri,
1997d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_default_host,
1998d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
1999d47b83b1SDaniel P. Berrangé .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
2000d47b83b1SDaniel P. Berrangé };
2001d47b83b1SDaniel P. Berrangé
2002d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2003d47b83b1SDaniel P. Berrangé }
2004d47b83b1SDaniel P. Berrangé
test_precopy_unix_tls_x509_override_host(void)2005d47b83b1SDaniel P. Berrangé static void test_precopy_unix_tls_x509_override_host(void)
2006d47b83b1SDaniel P. Berrangé {
2007d47b83b1SDaniel P. Berrangé g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
2008d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2009d47b83b1SDaniel P. Berrangé .connect_uri = uri,
2010d47b83b1SDaniel P. Berrangé .listen_uri = uri,
2011d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_override_host,
2012d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2013d47b83b1SDaniel P. Berrangé };
2014d47b83b1SDaniel P. Berrangé
2015d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2016d47b83b1SDaniel P. Berrangé }
2017d47b83b1SDaniel P. Berrangé #endif /* CONFIG_TASN1 */
2018d47b83b1SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
2019d47b83b1SDaniel P. Berrangé
20201e8a1faeSThomas Huth #if 0
20211e8a1faeSThomas Huth /* Currently upset on aarch64 TCG */
20221e8a1faeSThomas Huth static void test_ignore_shared(void)
20231e8a1faeSThomas Huth {
2024ff7b9b56SPeter Maydell g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
20251e8a1faeSThomas Huth QTestState *from, *to;
20261e8a1faeSThomas Huth
20271e8a1faeSThomas Huth if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) {
20281e8a1faeSThomas Huth return;
20291e8a1faeSThomas Huth }
20301e8a1faeSThomas Huth
2031e02f56e3SDaniel P. Berrangé migrate_ensure_non_converge(from);
2032e02f56e3SDaniel P. Berrangé migrate_prepare_for_dirty_mem(from);
2033e02f56e3SDaniel P. Berrangé
20341e8a1faeSThomas Huth migrate_set_capability(from, "x-ignore-shared", true);
20351e8a1faeSThomas Huth migrate_set_capability(to, "x-ignore-shared", true);
20361e8a1faeSThomas Huth
20371e8a1faeSThomas Huth /* Wait for the first serial output from the source */
20381e8a1faeSThomas Huth wait_for_serial("src_serial");
20391e8a1faeSThomas Huth
2040d5ee387dSHet Gala migrate_qmp(from, to, uri, NULL, "{}");
20411e8a1faeSThomas Huth
2042e02f56e3SDaniel P. Berrangé migrate_wait_for_dirty_mem(from, to);
20431e8a1faeSThomas Huth
2044f0649758SSteve Sistare wait_for_stop(from, &src_state);
20451e8a1faeSThomas Huth
20461e8a1faeSThomas Huth qtest_qmp_eventwait(to, "RESUME");
20471e8a1faeSThomas Huth
20481e8a1faeSThomas Huth wait_for_serial("dest_serial");
20491e8a1faeSThomas Huth wait_for_migration_complete(from);
20501e8a1faeSThomas Huth
20511e8a1faeSThomas Huth /* Check whether shared RAM has been really skipped */
20521e8a1faeSThomas Huth g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 1024);
20531e8a1faeSThomas Huth
20541e8a1faeSThomas Huth test_migrate_end(from, to, true);
20551e8a1faeSThomas Huth }
20561e8a1faeSThomas Huth #endif
20571e8a1faeSThomas Huth
205883bcba1eSDaniel P. Berrangé static void *
test_migrate_xbzrle_start(QTestState * from,QTestState * to)205983bcba1eSDaniel P. Berrangé test_migrate_xbzrle_start(QTestState *from,
206083bcba1eSDaniel P. Berrangé QTestState *to)
20611e8a1faeSThomas Huth {
20621e8a1faeSThomas Huth migrate_set_parameter_int(from, "xbzrle-cache-size", 33554432);
20631e8a1faeSThomas Huth
2064a1209bb7SDr. David Alan Gilbert migrate_set_capability(from, "xbzrle", true);
2065a1209bb7SDr. David Alan Gilbert migrate_set_capability(to, "xbzrle", true);
20661e8a1faeSThomas Huth
206783bcba1eSDaniel P. Berrangé return NULL;
20681e8a1faeSThomas Huth }
20691e8a1faeSThomas Huth
test_precopy_unix_xbzrle(void)207083bcba1eSDaniel P. Berrangé static void test_precopy_unix_xbzrle(void)
20711e8a1faeSThomas Huth {
2072ff7b9b56SPeter Maydell g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
207383bcba1eSDaniel P. Berrangé MigrateCommon args = {
207483bcba1eSDaniel P. Berrangé .connect_uri = uri,
207583bcba1eSDaniel P. Berrangé .listen_uri = uri,
207683bcba1eSDaniel P. Berrangé .start_hook = test_migrate_xbzrle_start,
207783bcba1eSDaniel P. Berrangé .iterations = 2,
2078b861383cSPeter Xu /*
2079b861383cSPeter Xu * XBZRLE needs pages to be modified when doing the 2nd+ round
2080b861383cSPeter Xu * iteration to have real data pushed to the stream.
2081b861383cSPeter Xu */
20823c4fb177SDaniel P. Berrangé .live = true,
208383bcba1eSDaniel P. Berrangé };
208483bcba1eSDaniel P. Berrangé
208583bcba1eSDaniel P. Berrangé test_precopy_common(&args);
20861e8a1faeSThomas Huth }
20871e8a1faeSThomas Huth
test_precopy_file(void)20883dc35470SFabiano Rosas static void test_precopy_file(void)
20893dc35470SFabiano Rosas {
20903dc35470SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
20913dc35470SFabiano Rosas FILE_TEST_FILENAME);
20923dc35470SFabiano Rosas MigrateCommon args = {
20933dc35470SFabiano Rosas .connect_uri = uri,
20943dc35470SFabiano Rosas .listen_uri = "defer",
20953dc35470SFabiano Rosas };
20963dc35470SFabiano Rosas
20973dc35470SFabiano Rosas test_file_common(&args, true);
20983dc35470SFabiano Rosas }
20993dc35470SFabiano Rosas
2100926554c0SFabiano Rosas #ifndef _WIN32
fdset_add_fds(QTestState * qts,const char * file,int flags,int num_fds,bool direct_io)2101926554c0SFabiano Rosas static void fdset_add_fds(QTestState *qts, const char *file, int flags,
210231a5a303SFabiano Rosas int num_fds, bool direct_io)
2103926554c0SFabiano Rosas {
2104926554c0SFabiano Rosas for (int i = 0; i < num_fds; i++) {
2105926554c0SFabiano Rosas int fd;
2106926554c0SFabiano Rosas
210731a5a303SFabiano Rosas #ifdef O_DIRECT
210831a5a303SFabiano Rosas /* only secondary channels can use direct-io */
210931a5a303SFabiano Rosas if (direct_io && i != 0) {
211031a5a303SFabiano Rosas flags |= O_DIRECT;
211131a5a303SFabiano Rosas }
211231a5a303SFabiano Rosas #endif
211331a5a303SFabiano Rosas
2114926554c0SFabiano Rosas fd = open(file, flags, 0660);
2115926554c0SFabiano Rosas assert(fd != -1);
2116926554c0SFabiano Rosas
2117926554c0SFabiano Rosas qtest_qmp_fds_assert_success(qts, &fd, 1, "{'execute': 'add-fd', "
2118926554c0SFabiano Rosas "'arguments': {'fdset-id': 1}}");
2119926554c0SFabiano Rosas close(fd);
2120926554c0SFabiano Rosas }
2121926554c0SFabiano Rosas }
2122926554c0SFabiano Rosas
file_offset_fdset_start_hook(QTestState * from,QTestState * to)2123926554c0SFabiano Rosas static void *file_offset_fdset_start_hook(QTestState *from, QTestState *to)
2124926554c0SFabiano Rosas {
2125926554c0SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
2126926554c0SFabiano Rosas
212731a5a303SFabiano Rosas fdset_add_fds(from, file, O_WRONLY, 1, false);
212831a5a303SFabiano Rosas fdset_add_fds(to, file, O_RDONLY, 1, false);
2129926554c0SFabiano Rosas
2130926554c0SFabiano Rosas return NULL;
2131926554c0SFabiano Rosas }
2132926554c0SFabiano Rosas
test_precopy_file_offset_fdset(void)2133926554c0SFabiano Rosas static void test_precopy_file_offset_fdset(void)
2134926554c0SFabiano Rosas {
2135926554c0SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
2136926554c0SFabiano Rosas FILE_TEST_OFFSET);
2137926554c0SFabiano Rosas MigrateCommon args = {
2138926554c0SFabiano Rosas .connect_uri = uri,
2139926554c0SFabiano Rosas .listen_uri = "defer",
2140926554c0SFabiano Rosas .start_hook = file_offset_fdset_start_hook,
2141926554c0SFabiano Rosas };
2142926554c0SFabiano Rosas
2143926554c0SFabiano Rosas test_file_common(&args, false);
2144926554c0SFabiano Rosas }
2145926554c0SFabiano Rosas #endif
2146926554c0SFabiano Rosas
test_precopy_file_offset(void)21473dc35470SFabiano Rosas static void test_precopy_file_offset(void)
21483dc35470SFabiano Rosas {
21493dc35470SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=%d", tmpfs,
21503dc35470SFabiano Rosas FILE_TEST_FILENAME,
21513dc35470SFabiano Rosas FILE_TEST_OFFSET);
21523dc35470SFabiano Rosas MigrateCommon args = {
21533dc35470SFabiano Rosas .connect_uri = uri,
21543dc35470SFabiano Rosas .listen_uri = "defer",
21553dc35470SFabiano Rosas };
21563dc35470SFabiano Rosas
21573dc35470SFabiano Rosas test_file_common(&args, false);
21583dc35470SFabiano Rosas }
21593dc35470SFabiano Rosas
test_precopy_file_offset_bad(void)21603dc35470SFabiano Rosas static void test_precopy_file_offset_bad(void)
21613dc35470SFabiano Rosas {
21623dc35470SFabiano Rosas /* using a value not supported by qemu_strtosz() */
21633dc35470SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=0x20M",
21643dc35470SFabiano Rosas tmpfs, FILE_TEST_FILENAME);
21653dc35470SFabiano Rosas MigrateCommon args = {
21663dc35470SFabiano Rosas .connect_uri = uri,
21673dc35470SFabiano Rosas .listen_uri = "defer",
21683dc35470SFabiano Rosas .result = MIG_TEST_QMP_ERROR,
21693dc35470SFabiano Rosas };
21703dc35470SFabiano Rosas
21713dc35470SFabiano Rosas test_file_common(&args, false);
21723dc35470SFabiano Rosas }
21733dc35470SFabiano Rosas
test_mode_reboot_start(QTestState * from,QTestState * to)2174e7b428d6SSteve Sistare static void *test_mode_reboot_start(QTestState *from, QTestState *to)
2175e7b428d6SSteve Sistare {
2176e7b428d6SSteve Sistare migrate_set_parameter_str(from, "mode", "cpr-reboot");
2177e7b428d6SSteve Sistare migrate_set_parameter_str(to, "mode", "cpr-reboot");
2178e7b428d6SSteve Sistare
2179e7b428d6SSteve Sistare migrate_set_capability(from, "x-ignore-shared", true);
2180e7b428d6SSteve Sistare migrate_set_capability(to, "x-ignore-shared", true);
2181e7b428d6SSteve Sistare
2182e7b428d6SSteve Sistare return NULL;
2183e7b428d6SSteve Sistare }
2184e7b428d6SSteve Sistare
migrate_mapped_ram_start(QTestState * from,QTestState * to)2185c7076ec3SFabiano Rosas static void *migrate_mapped_ram_start(QTestState *from, QTestState *to)
2186c7076ec3SFabiano Rosas {
2187c7076ec3SFabiano Rosas migrate_set_capability(from, "mapped-ram", true);
2188c7076ec3SFabiano Rosas migrate_set_capability(to, "mapped-ram", true);
2189c7076ec3SFabiano Rosas
2190c7076ec3SFabiano Rosas return NULL;
2191c7076ec3SFabiano Rosas }
2192c7076ec3SFabiano Rosas
test_mode_reboot(void)2193e7b428d6SSteve Sistare static void test_mode_reboot(void)
2194e7b428d6SSteve Sistare {
2195e7b428d6SSteve Sistare g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
2196e7b428d6SSteve Sistare FILE_TEST_FILENAME);
2197e7b428d6SSteve Sistare MigrateCommon args = {
2198e7b428d6SSteve Sistare .start.use_shmem = true,
2199e7b428d6SSteve Sistare .connect_uri = uri,
2200e7b428d6SSteve Sistare .listen_uri = "defer",
2201e7b428d6SSteve Sistare .start_hook = test_mode_reboot_start
2202e7b428d6SSteve Sistare };
2203e7b428d6SSteve Sistare
2204e7b428d6SSteve Sistare test_file_common(&args, true);
2205e7b428d6SSteve Sistare }
2206e7b428d6SSteve Sistare
test_precopy_file_mapped_ram_live(void)2207c7076ec3SFabiano Rosas static void test_precopy_file_mapped_ram_live(void)
2208c7076ec3SFabiano Rosas {
2209c7076ec3SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
2210c7076ec3SFabiano Rosas FILE_TEST_FILENAME);
2211c7076ec3SFabiano Rosas MigrateCommon args = {
2212c7076ec3SFabiano Rosas .connect_uri = uri,
2213c7076ec3SFabiano Rosas .listen_uri = "defer",
2214c7076ec3SFabiano Rosas .start_hook = migrate_mapped_ram_start,
2215c7076ec3SFabiano Rosas };
2216c7076ec3SFabiano Rosas
2217c7076ec3SFabiano Rosas test_file_common(&args, false);
2218c7076ec3SFabiano Rosas }
2219c7076ec3SFabiano Rosas
test_precopy_file_mapped_ram(void)2220c7076ec3SFabiano Rosas static void test_precopy_file_mapped_ram(void)
2221c7076ec3SFabiano Rosas {
2222c7076ec3SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
2223c7076ec3SFabiano Rosas FILE_TEST_FILENAME);
2224c7076ec3SFabiano Rosas MigrateCommon args = {
2225c7076ec3SFabiano Rosas .connect_uri = uri,
2226c7076ec3SFabiano Rosas .listen_uri = "defer",
2227c7076ec3SFabiano Rosas .start_hook = migrate_mapped_ram_start,
2228c7076ec3SFabiano Rosas };
2229c7076ec3SFabiano Rosas
2230c7076ec3SFabiano Rosas test_file_common(&args, true);
2231c7076ec3SFabiano Rosas }
2232c7076ec3SFabiano Rosas
migrate_multifd_mapped_ram_start(QTestState * from,QTestState * to)22337a09f092SFabiano Rosas static void *migrate_multifd_mapped_ram_start(QTestState *from, QTestState *to)
22347a09f092SFabiano Rosas {
22357a09f092SFabiano Rosas migrate_mapped_ram_start(from, to);
22367a09f092SFabiano Rosas
22377a09f092SFabiano Rosas migrate_set_parameter_int(from, "multifd-channels", 4);
22387a09f092SFabiano Rosas migrate_set_parameter_int(to, "multifd-channels", 4);
22397a09f092SFabiano Rosas
22407a09f092SFabiano Rosas migrate_set_capability(from, "multifd", true);
22417a09f092SFabiano Rosas migrate_set_capability(to, "multifd", true);
22427a09f092SFabiano Rosas
22437a09f092SFabiano Rosas return NULL;
22447a09f092SFabiano Rosas }
22457a09f092SFabiano Rosas
test_multifd_file_mapped_ram_live(void)22467a09f092SFabiano Rosas static void test_multifd_file_mapped_ram_live(void)
22477a09f092SFabiano Rosas {
22487a09f092SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
22497a09f092SFabiano Rosas FILE_TEST_FILENAME);
22507a09f092SFabiano Rosas MigrateCommon args = {
22517a09f092SFabiano Rosas .connect_uri = uri,
22527a09f092SFabiano Rosas .listen_uri = "defer",
22537a09f092SFabiano Rosas .start_hook = migrate_multifd_mapped_ram_start,
22547a09f092SFabiano Rosas };
22557a09f092SFabiano Rosas
22567a09f092SFabiano Rosas test_file_common(&args, false);
22577a09f092SFabiano Rosas }
22587a09f092SFabiano Rosas
test_multifd_file_mapped_ram(void)22597a09f092SFabiano Rosas static void test_multifd_file_mapped_ram(void)
22607a09f092SFabiano Rosas {
22617a09f092SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
22627a09f092SFabiano Rosas FILE_TEST_FILENAME);
22637a09f092SFabiano Rosas MigrateCommon args = {
22647a09f092SFabiano Rosas .connect_uri = uri,
22657a09f092SFabiano Rosas .listen_uri = "defer",
22667a09f092SFabiano Rosas .start_hook = migrate_multifd_mapped_ram_start,
22677a09f092SFabiano Rosas };
22687a09f092SFabiano Rosas
22697a09f092SFabiano Rosas test_file_common(&args, true);
22707a09f092SFabiano Rosas }
22717a09f092SFabiano Rosas
multifd_mapped_ram_dio_start(QTestState * from,QTestState * to)2272408d295dSFabiano Rosas static void *multifd_mapped_ram_dio_start(QTestState *from, QTestState *to)
2273408d295dSFabiano Rosas {
2274408d295dSFabiano Rosas migrate_multifd_mapped_ram_start(from, to);
2275408d295dSFabiano Rosas
2276408d295dSFabiano Rosas migrate_set_parameter_bool(from, "direct-io", true);
2277408d295dSFabiano Rosas migrate_set_parameter_bool(to, "direct-io", true);
2278408d295dSFabiano Rosas
2279408d295dSFabiano Rosas return NULL;
2280408d295dSFabiano Rosas }
2281408d295dSFabiano Rosas
test_multifd_file_mapped_ram_dio(void)2282408d295dSFabiano Rosas static void test_multifd_file_mapped_ram_dio(void)
2283408d295dSFabiano Rosas {
2284408d295dSFabiano Rosas g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
2285408d295dSFabiano Rosas FILE_TEST_FILENAME);
2286408d295dSFabiano Rosas MigrateCommon args = {
2287408d295dSFabiano Rosas .connect_uri = uri,
2288408d295dSFabiano Rosas .listen_uri = "defer",
2289408d295dSFabiano Rosas .start_hook = multifd_mapped_ram_dio_start,
2290408d295dSFabiano Rosas };
2291408d295dSFabiano Rosas
2292408d295dSFabiano Rosas if (!probe_o_direct_support(tmpfs)) {
2293408d295dSFabiano Rosas g_test_skip("Filesystem does not support O_DIRECT");
2294408d295dSFabiano Rosas return;
2295408d295dSFabiano Rosas }
2296408d295dSFabiano Rosas
2297408d295dSFabiano Rosas test_file_common(&args, true);
2298408d295dSFabiano Rosas }
22997a09f092SFabiano Rosas
230031a5a303SFabiano Rosas #ifndef _WIN32
multifd_mapped_ram_fdset_end(QTestState * from,QTestState * to,void * opaque)230131a5a303SFabiano Rosas static void multifd_mapped_ram_fdset_end(QTestState *from, QTestState *to,
230231a5a303SFabiano Rosas void *opaque)
230331a5a303SFabiano Rosas {
230431a5a303SFabiano Rosas QDict *resp;
230531a5a303SFabiano Rosas QList *fdsets;
230631a5a303SFabiano Rosas
230731a5a303SFabiano Rosas /*
230831a5a303SFabiano Rosas * Remove the fdsets after migration, otherwise a second migration
230931a5a303SFabiano Rosas * would fail due fdset reuse.
231031a5a303SFabiano Rosas */
231131a5a303SFabiano Rosas qtest_qmp_assert_success(from, "{'execute': 'remove-fd', "
231231a5a303SFabiano Rosas "'arguments': { 'fdset-id': 1}}");
231331a5a303SFabiano Rosas
231431a5a303SFabiano Rosas /*
231531a5a303SFabiano Rosas * Make sure no fdsets are left after migration, otherwise a
231631a5a303SFabiano Rosas * second migration would fail due fdset reuse.
231731a5a303SFabiano Rosas */
231831a5a303SFabiano Rosas resp = qtest_qmp(from, "{'execute': 'query-fdsets', "
231931a5a303SFabiano Rosas "'arguments': {}}");
232031a5a303SFabiano Rosas g_assert(qdict_haskey(resp, "return"));
232131a5a303SFabiano Rosas fdsets = qdict_get_qlist(resp, "return");
232231a5a303SFabiano Rosas g_assert(fdsets && qlist_empty(fdsets));
23230fa2cf81SPeter Maydell qobject_unref(resp);
232431a5a303SFabiano Rosas }
232531a5a303SFabiano Rosas
multifd_mapped_ram_fdset_dio(QTestState * from,QTestState * to)232631a5a303SFabiano Rosas static void *multifd_mapped_ram_fdset_dio(QTestState *from, QTestState *to)
232731a5a303SFabiano Rosas {
232831a5a303SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
232931a5a303SFabiano Rosas
233031a5a303SFabiano Rosas fdset_add_fds(from, file, O_WRONLY, 2, true);
233131a5a303SFabiano Rosas fdset_add_fds(to, file, O_RDONLY, 2, true);
233231a5a303SFabiano Rosas
233331a5a303SFabiano Rosas migrate_multifd_mapped_ram_start(from, to);
233431a5a303SFabiano Rosas migrate_set_parameter_bool(from, "direct-io", true);
233531a5a303SFabiano Rosas migrate_set_parameter_bool(to, "direct-io", true);
233631a5a303SFabiano Rosas
233731a5a303SFabiano Rosas return NULL;
233831a5a303SFabiano Rosas }
233931a5a303SFabiano Rosas
multifd_mapped_ram_fdset(QTestState * from,QTestState * to)234031a5a303SFabiano Rosas static void *multifd_mapped_ram_fdset(QTestState *from, QTestState *to)
234131a5a303SFabiano Rosas {
234231a5a303SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
234331a5a303SFabiano Rosas
234431a5a303SFabiano Rosas fdset_add_fds(from, file, O_WRONLY, 2, false);
234531a5a303SFabiano Rosas fdset_add_fds(to, file, O_RDONLY, 2, false);
234631a5a303SFabiano Rosas
234731a5a303SFabiano Rosas migrate_multifd_mapped_ram_start(from, to);
234831a5a303SFabiano Rosas
234931a5a303SFabiano Rosas return NULL;
235031a5a303SFabiano Rosas }
235131a5a303SFabiano Rosas
test_multifd_file_mapped_ram_fdset(void)235231a5a303SFabiano Rosas static void test_multifd_file_mapped_ram_fdset(void)
235331a5a303SFabiano Rosas {
235431a5a303SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
235531a5a303SFabiano Rosas FILE_TEST_OFFSET);
235631a5a303SFabiano Rosas MigrateCommon args = {
235731a5a303SFabiano Rosas .connect_uri = uri,
235831a5a303SFabiano Rosas .listen_uri = "defer",
235931a5a303SFabiano Rosas .start_hook = multifd_mapped_ram_fdset,
236031a5a303SFabiano Rosas .finish_hook = multifd_mapped_ram_fdset_end,
236131a5a303SFabiano Rosas };
236231a5a303SFabiano Rosas
236331a5a303SFabiano Rosas test_file_common(&args, true);
236431a5a303SFabiano Rosas }
236531a5a303SFabiano Rosas
test_multifd_file_mapped_ram_fdset_dio(void)236631a5a303SFabiano Rosas static void test_multifd_file_mapped_ram_fdset_dio(void)
236731a5a303SFabiano Rosas {
236831a5a303SFabiano Rosas g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
236931a5a303SFabiano Rosas FILE_TEST_OFFSET);
237031a5a303SFabiano Rosas MigrateCommon args = {
237131a5a303SFabiano Rosas .connect_uri = uri,
237231a5a303SFabiano Rosas .listen_uri = "defer",
237331a5a303SFabiano Rosas .start_hook = multifd_mapped_ram_fdset_dio,
237431a5a303SFabiano Rosas .finish_hook = multifd_mapped_ram_fdset_end,
237531a5a303SFabiano Rosas };
237631a5a303SFabiano Rosas
237731a5a303SFabiano Rosas if (!probe_o_direct_support(tmpfs)) {
237831a5a303SFabiano Rosas g_test_skip("Filesystem does not support O_DIRECT");
237931a5a303SFabiano Rosas return;
238031a5a303SFabiano Rosas }
238131a5a303SFabiano Rosas
238231a5a303SFabiano Rosas test_file_common(&args, true);
238331a5a303SFabiano Rosas }
238431a5a303SFabiano Rosas #endif /* !_WIN32 */
238531a5a303SFabiano Rosas
test_precopy_tcp_plain(void)238658d25e97SDaniel P. Berrangé static void test_precopy_tcp_plain(void)
23871e8a1faeSThomas Huth {
2388ffed54f6SDaniel P. Berrangé MigrateCommon args = {
2389ffed54f6SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2390ffed54f6SDaniel P. Berrangé };
23911e8a1faeSThomas Huth
2392ffed54f6SDaniel P. Berrangé test_precopy_common(&args);
23931e8a1faeSThomas Huth }
23941e8a1faeSThomas Huth
test_migrate_switchover_ack_start(QTestState * from,QTestState * to)23957e6a5c73SAvihai Horon static void *test_migrate_switchover_ack_start(QTestState *from, QTestState *to)
23967e6a5c73SAvihai Horon {
23977e6a5c73SAvihai Horon
23987e6a5c73SAvihai Horon migrate_set_capability(from, "return-path", true);
23997e6a5c73SAvihai Horon migrate_set_capability(to, "return-path", true);
24007e6a5c73SAvihai Horon
24017e6a5c73SAvihai Horon migrate_set_capability(from, "switchover-ack", true);
24027e6a5c73SAvihai Horon migrate_set_capability(to, "switchover-ack", true);
24037e6a5c73SAvihai Horon
24047e6a5c73SAvihai Horon return NULL;
24057e6a5c73SAvihai Horon }
24067e6a5c73SAvihai Horon
test_precopy_tcp_switchover_ack(void)24077e6a5c73SAvihai Horon static void test_precopy_tcp_switchover_ack(void)
24087e6a5c73SAvihai Horon {
24097e6a5c73SAvihai Horon MigrateCommon args = {
24107e6a5c73SAvihai Horon .listen_uri = "tcp:127.0.0.1:0",
24117e6a5c73SAvihai Horon .start_hook = test_migrate_switchover_ack_start,
24127e6a5c73SAvihai Horon /*
24137e6a5c73SAvihai Horon * Source VM must be running in order to consider the switchover ACK
24147e6a5c73SAvihai Horon * when deciding to do switchover or not.
24157e6a5c73SAvihai Horon */
24167e6a5c73SAvihai Horon .live = true,
24177e6a5c73SAvihai Horon };
24187e6a5c73SAvihai Horon
24197e6a5c73SAvihai Horon test_precopy_common(&args);
24207e6a5c73SAvihai Horon }
24217e6a5c73SAvihai Horon
242258d25e97SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
test_precopy_tcp_tls_psk_match(void)242358d25e97SDaniel P. Berrangé static void test_precopy_tcp_tls_psk_match(void)
242458d25e97SDaniel P. Berrangé {
242558d25e97SDaniel P. Berrangé MigrateCommon args = {
242658d25e97SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
242758d25e97SDaniel P. Berrangé .start_hook = test_migrate_tls_psk_start_match,
242858d25e97SDaniel P. Berrangé .finish_hook = test_migrate_tls_psk_finish,
242958d25e97SDaniel P. Berrangé };
243058d25e97SDaniel P. Berrangé
243158d25e97SDaniel P. Berrangé test_precopy_common(&args);
243258d25e97SDaniel P. Berrangé }
243358d25e97SDaniel P. Berrangé
test_precopy_tcp_tls_psk_mismatch(void)243458d25e97SDaniel P. Berrangé static void test_precopy_tcp_tls_psk_mismatch(void)
243558d25e97SDaniel P. Berrangé {
243658d25e97SDaniel P. Berrangé MigrateCommon args = {
243758d25e97SDaniel P. Berrangé .start = {
243858d25e97SDaniel P. Berrangé .hide_stderr = true,
243958d25e97SDaniel P. Berrangé },
244058d25e97SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
244158d25e97SDaniel P. Berrangé .start_hook = test_migrate_tls_psk_start_mismatch,
244258d25e97SDaniel P. Berrangé .finish_hook = test_migrate_tls_psk_finish,
244358d25e97SDaniel P. Berrangé .result = MIG_TEST_FAIL,
244458d25e97SDaniel P. Berrangé };
244558d25e97SDaniel P. Berrangé
244658d25e97SDaniel P. Berrangé test_precopy_common(&args);
244758d25e97SDaniel P. Berrangé }
2448d47b83b1SDaniel P. Berrangé
2449d47b83b1SDaniel P. Berrangé #ifdef CONFIG_TASN1
test_precopy_tcp_tls_x509_default_host(void)2450d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_default_host(void)
2451d47b83b1SDaniel P. Berrangé {
2452d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2453d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2454d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_default_host,
2455d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2456d47b83b1SDaniel P. Berrangé };
2457d47b83b1SDaniel P. Berrangé
2458d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2459d47b83b1SDaniel P. Berrangé }
2460d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_override_host(void)2461d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_override_host(void)
2462d47b83b1SDaniel P. Berrangé {
2463d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2464d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2465d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_override_host,
2466d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2467d47b83b1SDaniel P. Berrangé };
2468d47b83b1SDaniel P. Berrangé
2469d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2470d47b83b1SDaniel P. Berrangé }
2471d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_mismatch_host(void)2472d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_mismatch_host(void)
2473d47b83b1SDaniel P. Berrangé {
2474d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2475d47b83b1SDaniel P. Berrangé .start = {
2476d47b83b1SDaniel P. Berrangé .hide_stderr = true,
2477d47b83b1SDaniel P. Berrangé },
2478d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2479d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_mismatch_host,
2480d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2481d47b83b1SDaniel P. Berrangé .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
2482d47b83b1SDaniel P. Berrangé };
2483d47b83b1SDaniel P. Berrangé
2484d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2485d47b83b1SDaniel P. Berrangé }
2486d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_friendly_client(void)2487d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_friendly_client(void)
2488d47b83b1SDaniel P. Berrangé {
2489d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2490d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2491d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_friendly_client,
2492d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2493d47b83b1SDaniel P. Berrangé };
2494d47b83b1SDaniel P. Berrangé
2495d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2496d47b83b1SDaniel P. Berrangé }
2497d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_hostile_client(void)2498d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_hostile_client(void)
2499d47b83b1SDaniel P. Berrangé {
2500d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2501d47b83b1SDaniel P. Berrangé .start = {
2502d47b83b1SDaniel P. Berrangé .hide_stderr = true,
2503d47b83b1SDaniel P. Berrangé },
2504d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2505d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_hostile_client,
2506d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2507d47b83b1SDaniel P. Berrangé .result = MIG_TEST_FAIL,
2508d47b83b1SDaniel P. Berrangé };
2509d47b83b1SDaniel P. Berrangé
2510d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2511d47b83b1SDaniel P. Berrangé }
2512d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_allow_anon_client(void)2513d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_allow_anon_client(void)
2514d47b83b1SDaniel P. Berrangé {
2515d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2516d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2517d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_allow_anon_client,
2518d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2519d47b83b1SDaniel P. Berrangé };
2520d47b83b1SDaniel P. Berrangé
2521d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2522d47b83b1SDaniel P. Berrangé }
2523d47b83b1SDaniel P. Berrangé
test_precopy_tcp_tls_x509_reject_anon_client(void)2524d47b83b1SDaniel P. Berrangé static void test_precopy_tcp_tls_x509_reject_anon_client(void)
2525d47b83b1SDaniel P. Berrangé {
2526d47b83b1SDaniel P. Berrangé MigrateCommon args = {
2527d47b83b1SDaniel P. Berrangé .start = {
2528d47b83b1SDaniel P. Berrangé .hide_stderr = true,
2529d47b83b1SDaniel P. Berrangé },
2530d47b83b1SDaniel P. Berrangé .listen_uri = "tcp:127.0.0.1:0",
2531d47b83b1SDaniel P. Berrangé .start_hook = test_migrate_tls_x509_start_reject_anon_client,
2532d47b83b1SDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
2533d47b83b1SDaniel P. Berrangé .result = MIG_TEST_FAIL,
2534d47b83b1SDaniel P. Berrangé };
2535d47b83b1SDaniel P. Berrangé
2536d47b83b1SDaniel P. Berrangé test_precopy_common(&args);
2537d47b83b1SDaniel P. Berrangé }
2538d47b83b1SDaniel P. Berrangé #endif /* CONFIG_TASN1 */
253958d25e97SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
254058d25e97SDaniel P. Berrangé
2541d7613ee2SBin Meng #ifndef _WIN32
test_migrate_fd_start_hook(QTestState * from,QTestState * to)2542243e0066SDaniel P. Berrangé static void *test_migrate_fd_start_hook(QTestState *from,
2543243e0066SDaniel P. Berrangé QTestState *to)
25441e8a1faeSThomas Huth {
25451e8a1faeSThomas Huth int ret;
25461e8a1faeSThomas Huth int pair[2];
25471e8a1faeSThomas Huth
25481e8a1faeSThomas Huth /* Create two connected sockets for migration */
25490038e9a2SGuoyi Tu ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair);
25501e8a1faeSThomas Huth g_assert_cmpint(ret, ==, 0);
25511e8a1faeSThomas Huth
25521e8a1faeSThomas Huth /* Send the 1st socket to the target */
2553aca04069SDaniel P. Berrangé qtest_qmp_fds_assert_success(to, &pair[0], 1,
25541e8a1faeSThomas Huth "{ 'execute': 'getfd',"
25551e8a1faeSThomas Huth " 'arguments': { 'fdname': 'fd-mig' }}");
25561e8a1faeSThomas Huth close(pair[0]);
25571e8a1faeSThomas Huth
25581e8a1faeSThomas Huth /* Start incoming migration from the 1st socket */
25596830e53bSFabiano Rosas migrate_incoming_qmp(to, "fd:fd-mig", "{}");
25601e8a1faeSThomas Huth
25611e8a1faeSThomas Huth /* Send the 2nd socket to the target */
2562aca04069SDaniel P. Berrangé qtest_qmp_fds_assert_success(from, &pair[1], 1,
25631e8a1faeSThomas Huth "{ 'execute': 'getfd',"
25641e8a1faeSThomas Huth " 'arguments': { 'fdname': 'fd-mig' }}");
25651e8a1faeSThomas Huth close(pair[1]);
25661e8a1faeSThomas Huth
2567243e0066SDaniel P. Berrangé return NULL;
25681e8a1faeSThomas Huth }
2569243e0066SDaniel P. Berrangé
test_migrate_fd_finish_hook(QTestState * from,QTestState * to,void * opaque)2570243e0066SDaniel P. Berrangé static void test_migrate_fd_finish_hook(QTestState *from,
2571243e0066SDaniel P. Berrangé QTestState *to,
2572243e0066SDaniel P. Berrangé void *opaque)
2573243e0066SDaniel P. Berrangé {
2574243e0066SDaniel P. Berrangé QDict *rsp;
2575243e0066SDaniel P. Berrangé const char *error_desc;
25761e8a1faeSThomas Huth
25771e8a1faeSThomas Huth /* Test closing fds */
25781e8a1faeSThomas Huth /* We assume, that QEMU removes named fd from its list,
25791e8a1faeSThomas Huth * so this should fail */
2580*19e56616SFabiano Rosas rsp = qtest_qmp(from,
2581*19e56616SFabiano Rosas "{ 'execute': 'closefd',"
25821e8a1faeSThomas Huth " 'arguments': { 'fdname': 'fd-mig' }}");
25831e8a1faeSThomas Huth g_assert_true(qdict_haskey(rsp, "error"));
25841e8a1faeSThomas Huth error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
25851e8a1faeSThomas Huth g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
25861e8a1faeSThomas Huth qobject_unref(rsp);
25871e8a1faeSThomas Huth
2588*19e56616SFabiano Rosas rsp = qtest_qmp(to,
2589*19e56616SFabiano Rosas "{ 'execute': 'closefd',"
25901e8a1faeSThomas Huth " 'arguments': { 'fdname': 'fd-mig' }}");
25911e8a1faeSThomas Huth g_assert_true(qdict_haskey(rsp, "error"));
25921e8a1faeSThomas Huth error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
25931e8a1faeSThomas Huth g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
25941e8a1faeSThomas Huth qobject_unref(rsp);
2595243e0066SDaniel P. Berrangé }
25961e8a1faeSThomas Huth
test_migrate_precopy_fd_socket(void)259785cf9abdSFabiano Rosas static void test_migrate_precopy_fd_socket(void)
2598243e0066SDaniel P. Berrangé {
2599243e0066SDaniel P. Berrangé MigrateCommon args = {
2600243e0066SDaniel P. Berrangé .listen_uri = "defer",
2601243e0066SDaniel P. Berrangé .connect_uri = "fd:fd-mig",
2602243e0066SDaniel P. Berrangé .start_hook = test_migrate_fd_start_hook,
2603243e0066SDaniel P. Berrangé .finish_hook = test_migrate_fd_finish_hook
2604243e0066SDaniel P. Berrangé };
2605243e0066SDaniel P. Berrangé test_precopy_common(&args);
26061e8a1faeSThomas Huth }
26076d79bd68SFabiano Rosas
migrate_precopy_fd_file_start(QTestState * from,QTestState * to)26086d79bd68SFabiano Rosas static void *migrate_precopy_fd_file_start(QTestState *from, QTestState *to)
26096d79bd68SFabiano Rosas {
26106d79bd68SFabiano Rosas g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
26116d79bd68SFabiano Rosas int src_flags = O_CREAT | O_RDWR;
26126d79bd68SFabiano Rosas int dst_flags = O_CREAT | O_RDWR;
26136d79bd68SFabiano Rosas int fds[2];
26146d79bd68SFabiano Rosas
26156d79bd68SFabiano Rosas fds[0] = open(file, src_flags, 0660);
26166d79bd68SFabiano Rosas assert(fds[0] != -1);
26176d79bd68SFabiano Rosas
26186d79bd68SFabiano Rosas fds[1] = open(file, dst_flags, 0660);
26196d79bd68SFabiano Rosas assert(fds[1] != -1);
26206d79bd68SFabiano Rosas
26216d79bd68SFabiano Rosas
26226d79bd68SFabiano Rosas qtest_qmp_fds_assert_success(to, &fds[0], 1,
26236d79bd68SFabiano Rosas "{ 'execute': 'getfd',"
26246d79bd68SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
26256d79bd68SFabiano Rosas
26266d79bd68SFabiano Rosas qtest_qmp_fds_assert_success(from, &fds[1], 1,
26276d79bd68SFabiano Rosas "{ 'execute': 'getfd',"
26286d79bd68SFabiano Rosas " 'arguments': { 'fdname': 'fd-mig' }}");
26296d79bd68SFabiano Rosas
26306d79bd68SFabiano Rosas close(fds[0]);
26316d79bd68SFabiano Rosas close(fds[1]);
26326d79bd68SFabiano Rosas
26336d79bd68SFabiano Rosas return NULL;
26346d79bd68SFabiano Rosas }
26356d79bd68SFabiano Rosas
test_migrate_precopy_fd_file(void)26366d79bd68SFabiano Rosas static void test_migrate_precopy_fd_file(void)
26376d79bd68SFabiano Rosas {
26386d79bd68SFabiano Rosas MigrateCommon args = {
26396d79bd68SFabiano Rosas .listen_uri = "defer",
26406d79bd68SFabiano Rosas .connect_uri = "fd:fd-mig",
26416d79bd68SFabiano Rosas .start_hook = migrate_precopy_fd_file_start,
26426d79bd68SFabiano Rosas .finish_hook = test_migrate_fd_finish_hook
26436d79bd68SFabiano Rosas };
26446d79bd68SFabiano Rosas test_file_common(&args, true);
26456d79bd68SFabiano Rosas }
2646d7613ee2SBin Meng #endif /* _WIN32 */
26471e8a1faeSThomas Huth
do_test_validate_uuid(MigrateStart * args,bool should_fail)26481e8a1faeSThomas Huth static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
26491e8a1faeSThomas Huth {
2650ff7b9b56SPeter Maydell g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
26511e8a1faeSThomas Huth QTestState *from, *to;
26521e8a1faeSThomas Huth
265319da6edfSDaniel P. Berrangé if (test_migrate_start(&from, &to, uri, args)) {
26541e8a1faeSThomas Huth return;
26551e8a1faeSThomas Huth }
26561e8a1faeSThomas Huth
26571e8a1faeSThomas Huth /*
26581e8a1faeSThomas Huth * UUID validation is at the begin of migration. So, the main process of
26591e8a1faeSThomas Huth * migration is not interesting for us here. Thus, set huge downtime for
26601e8a1faeSThomas Huth * very fast migration.
26611e8a1faeSThomas Huth */
26621e8a1faeSThomas Huth migrate_set_parameter_int(from, "downtime-limit", 1000000);
26631e8a1faeSThomas Huth migrate_set_capability(from, "validate-uuid", true);
26641e8a1faeSThomas Huth
26651e8a1faeSThomas Huth /* Wait for the first serial output from the source */
26661e8a1faeSThomas Huth wait_for_serial("src_serial");
26671e8a1faeSThomas Huth
2668d5ee387dSHet Gala migrate_qmp(from, to, uri, NULL, "{}");
26691e8a1faeSThomas Huth
26701e8a1faeSThomas Huth if (should_fail) {
26711b0f1b14SBin Meng qtest_set_expected_status(to, EXIT_FAILURE);
26721e8a1faeSThomas Huth wait_for_migration_fail(from, true);
26731e8a1faeSThomas Huth } else {
26741e8a1faeSThomas Huth wait_for_migration_complete(from);
26751e8a1faeSThomas Huth }
26761e8a1faeSThomas Huth
26771e8a1faeSThomas Huth test_migrate_end(from, to, false);
26781e8a1faeSThomas Huth }
26791e8a1faeSThomas Huth
test_validate_uuid(void)26801e8a1faeSThomas Huth static void test_validate_uuid(void)
26811e8a1faeSThomas Huth {
268219da6edfSDaniel P. Berrangé MigrateStart args = {
268319da6edfSDaniel P. Berrangé .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
268419da6edfSDaniel P. Berrangé .opts_target = "-uuid 11111111-1111-1111-1111-111111111111",
268519da6edfSDaniel P. Berrangé };
26861e8a1faeSThomas Huth
268719da6edfSDaniel P. Berrangé do_test_validate_uuid(&args, false);
26881e8a1faeSThomas Huth }
26891e8a1faeSThomas Huth
test_validate_uuid_error(void)26901e8a1faeSThomas Huth static void test_validate_uuid_error(void)
26911e8a1faeSThomas Huth {
269219da6edfSDaniel P. Berrangé MigrateStart args = {
269319da6edfSDaniel P. Berrangé .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
269419da6edfSDaniel P. Berrangé .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
269519da6edfSDaniel P. Berrangé .hide_stderr = true,
269619da6edfSDaniel P. Berrangé };
26971e8a1faeSThomas Huth
269819da6edfSDaniel P. Berrangé do_test_validate_uuid(&args, true);
26991e8a1faeSThomas Huth }
27001e8a1faeSThomas Huth
test_validate_uuid_src_not_set(void)27011e8a1faeSThomas Huth static void test_validate_uuid_src_not_set(void)
27021e8a1faeSThomas Huth {
270319da6edfSDaniel P. Berrangé MigrateStart args = {
270419da6edfSDaniel P. Berrangé .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
270519da6edfSDaniel P. Berrangé .hide_stderr = true,
270619da6edfSDaniel P. Berrangé };
27071e8a1faeSThomas Huth
270819da6edfSDaniel P. Berrangé do_test_validate_uuid(&args, false);
27091e8a1faeSThomas Huth }
27101e8a1faeSThomas Huth
test_validate_uuid_dst_not_set(void)27111e8a1faeSThomas Huth static void test_validate_uuid_dst_not_set(void)
27121e8a1faeSThomas Huth {
271319da6edfSDaniel P. Berrangé MigrateStart args = {
271419da6edfSDaniel P. Berrangé .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
271519da6edfSDaniel P. Berrangé .hide_stderr = true,
271619da6edfSDaniel P. Berrangé };
27171e8a1faeSThomas Huth
271819da6edfSDaniel P. Berrangé do_test_validate_uuid(&args, false);
27191e8a1faeSThomas Huth }
27201e8a1faeSThomas Huth
do_test_validate_uri_channel(MigrateCommon * args)2721bc6307a5SHet Gala static void do_test_validate_uri_channel(MigrateCommon *args)
2722bc6307a5SHet Gala {
2723bc6307a5SHet Gala QTestState *from, *to;
2724bc6307a5SHet Gala
2725bc6307a5SHet Gala if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
2726bc6307a5SHet Gala return;
2727bc6307a5SHet Gala }
2728bc6307a5SHet Gala
2729bc6307a5SHet Gala /* Wait for the first serial output from the source */
2730bc6307a5SHet Gala wait_for_serial("src_serial");
2731bc6307a5SHet Gala
2732bc6307a5SHet Gala /*
2733bc6307a5SHet Gala * 'uri' and 'channels' validation is checked even before the migration
2734bc6307a5SHet Gala * starts.
2735bc6307a5SHet Gala */
2736bc6307a5SHet Gala migrate_qmp_fail(from, args->connect_uri, args->connect_channels, "{}");
2737bc6307a5SHet Gala test_migrate_end(from, to, false);
2738bc6307a5SHet Gala }
2739bc6307a5SHet Gala
test_validate_uri_channels_both_set(void)2740bc6307a5SHet Gala static void test_validate_uri_channels_both_set(void)
2741bc6307a5SHet Gala {
2742bc6307a5SHet Gala MigrateCommon args = {
2743bc6307a5SHet Gala .start = {
2744bc6307a5SHet Gala .hide_stderr = true,
2745bc6307a5SHet Gala },
2746bc6307a5SHet Gala .listen_uri = "defer",
2747bc6307a5SHet Gala .connect_uri = "tcp:127.0.0.1:0",
2748*19e56616SFabiano Rosas .connect_channels = ("[ { ""'channel-type': 'main',"
2749bc6307a5SHet Gala " 'addr': { 'transport': 'socket',"
2750bc6307a5SHet Gala " 'type': 'inet',"
2751bc6307a5SHet Gala " 'host': '127.0.0.1',"
2752*19e56616SFabiano Rosas " 'port': '0' } } ]"),
2753bc6307a5SHet Gala };
2754bc6307a5SHet Gala
2755bc6307a5SHet Gala do_test_validate_uri_channel(&args);
2756bc6307a5SHet Gala }
2757bc6307a5SHet Gala
test_validate_uri_channels_none_set(void)2758bc6307a5SHet Gala static void test_validate_uri_channels_none_set(void)
2759bc6307a5SHet Gala {
2760bc6307a5SHet Gala MigrateCommon args = {
2761bc6307a5SHet Gala .start = {
2762bc6307a5SHet Gala .hide_stderr = true,
2763bc6307a5SHet Gala },
2764bc6307a5SHet Gala .listen_uri = "defer",
2765bc6307a5SHet Gala };
2766bc6307a5SHet Gala
2767bc6307a5SHet Gala do_test_validate_uri_channel(&args);
2768bc6307a5SHet Gala }
2769bc6307a5SHet Gala
277074902af7SJuan Quintela /*
277174902af7SJuan Quintela * The way auto_converge works, we need to do too many passes to
277274902af7SJuan Quintela * run this test. Auto_converge logic is only run once every
277374902af7SJuan Quintela * three iterations, so:
277474902af7SJuan Quintela *
277574902af7SJuan Quintela * - 3 iterations without auto_converge enabled
277674902af7SJuan Quintela * - 3 iterations with pct = 5
277774902af7SJuan Quintela * - 3 iterations with pct = 30
277874902af7SJuan Quintela * - 3 iterations with pct = 55
277974902af7SJuan Quintela * - 3 iterations with pct = 80
278074902af7SJuan Quintela * - 3 iterations with pct = 95 (max(95, 80 + 25))
278174902af7SJuan Quintela *
278274902af7SJuan Quintela * To make things even worse, we need to run the initial stage at
278374902af7SJuan Quintela * 3MB/s so we enter autoconverge even when host is (over)loaded.
278474902af7SJuan Quintela */
test_migrate_auto_converge(void)27851e8a1faeSThomas Huth static void test_migrate_auto_converge(void)
27861e8a1faeSThomas Huth {
2787ff7b9b56SPeter Maydell g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
278819da6edfSDaniel P. Berrangé MigrateStart args = {};
27891e8a1faeSThomas Huth QTestState *from, *to;
2790219044b8SPeter Xu int64_t percentage;
27911e8a1faeSThomas Huth
27921e8a1faeSThomas Huth /*
27931e8a1faeSThomas Huth * We want the test to be stable and as fast as possible.
279496420a30SMichael Tokarev * E.g., with 1Gb/s bandwidth migration may pass without throttling,
27951e8a1faeSThomas Huth * so we need to decrease a bandwidth.
27961e8a1faeSThomas Huth */
27971bfc8ddeSDr. David Alan Gilbert const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
2798bfd66ccbSHyman Huang uint64_t prev_dirty_sync_cnt, dirty_sync_cnt;
2799bfd66ccbSHyman Huang int max_try_count, hit = 0;
28001e8a1faeSThomas Huth
28013ff57401SPeter Xu if (test_migrate_start(&from, &to, uri, &args)) {
28021e8a1faeSThomas Huth return;
28031e8a1faeSThomas Huth }
28041e8a1faeSThomas Huth
28051e8a1faeSThomas Huth migrate_set_capability(from, "auto-converge", true);
28061e8a1faeSThomas Huth migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct);
28071e8a1faeSThomas Huth migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct);
28081e8a1faeSThomas Huth migrate_set_parameter_int(from, "max-cpu-throttle", max_pct);
28091e8a1faeSThomas Huth
28101e8a1faeSThomas Huth /*
28111e8a1faeSThomas Huth * Set the initial parameters so that the migration could not converge
28121e8a1faeSThomas Huth * without throttling.
28131e8a1faeSThomas Huth */
2814886dfe9dSDaniel P. Berrangé migrate_ensure_non_converge(from);
28151e8a1faeSThomas Huth
28161e8a1faeSThomas Huth /* To check remaining size after precopy */
28171e8a1faeSThomas Huth migrate_set_capability(from, "pause-before-switchover", true);
28181e8a1faeSThomas Huth
28191e8a1faeSThomas Huth /* Wait for the first serial output from the source */
28201e8a1faeSThomas Huth wait_for_serial("src_serial");
28211e8a1faeSThomas Huth
2822d5ee387dSHet Gala migrate_qmp(from, to, uri, NULL, "{}");
28231e8a1faeSThomas Huth
28241e8a1faeSThomas Huth /* Wait for throttling begins */
28251e8a1faeSThomas Huth percentage = 0;
28261bfc8ddeSDr. David Alan Gilbert do {
28271e8a1faeSThomas Huth percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
28281bfc8ddeSDr. David Alan Gilbert if (percentage != 0) {
28291bfc8ddeSDr. David Alan Gilbert break;
28301e8a1faeSThomas Huth }
28311bfc8ddeSDr. David Alan Gilbert usleep(20);
2832f0649758SSteve Sistare g_assert_false(src_state.stop_seen);
28331bfc8ddeSDr. David Alan Gilbert } while (true);
28341bfc8ddeSDr. David Alan Gilbert /* The first percentage of throttling should be at least init_pct */
28351bfc8ddeSDr. David Alan Gilbert g_assert_cmpint(percentage, >=, init_pct);
2836bfd66ccbSHyman Huang
2837bfd66ccbSHyman Huang /*
2838bfd66ccbSHyman Huang * End the loop when the dirty sync count greater than 1.
2839bfd66ccbSHyman Huang */
2840bfd66ccbSHyman Huang while ((dirty_sync_cnt = get_migration_pass(from)) < 2) {
2841bfd66ccbSHyman Huang usleep(1000 * 1000);
2842bfd66ccbSHyman Huang }
2843bfd66ccbSHyman Huang
2844bfd66ccbSHyman Huang prev_dirty_sync_cnt = dirty_sync_cnt;
2845bfd66ccbSHyman Huang
2846bfd66ccbSHyman Huang /*
2847bfd66ccbSHyman Huang * The RAMBlock dirty sync count must changes in 5 seconds, here we set
2848bfd66ccbSHyman Huang * the timeout to 10 seconds to ensure it changes.
2849bfd66ccbSHyman Huang *
2850bfd66ccbSHyman Huang * Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s,
2851bfd66ccbSHyman Huang * while the qtest mem is >= 100MB, one iteration takes at least 33s (100/3)
2852bfd66ccbSHyman Huang * to complete; this ensures that the RAMBlock dirty sync occurs.
2853bfd66ccbSHyman Huang */
2854bfd66ccbSHyman Huang max_try_count = 10;
2855bfd66ccbSHyman Huang while (--max_try_count) {
2856bfd66ccbSHyman Huang dirty_sync_cnt = get_migration_pass(from);
2857bfd66ccbSHyman Huang if (dirty_sync_cnt != prev_dirty_sync_cnt) {
2858bfd66ccbSHyman Huang hit = 1;
2859bfd66ccbSHyman Huang break;
2860bfd66ccbSHyman Huang }
2861bfd66ccbSHyman Huang prev_dirty_sync_cnt = dirty_sync_cnt;
2862bfd66ccbSHyman Huang sleep(1);
2863bfd66ccbSHyman Huang }
2864bfd66ccbSHyman Huang g_assert_cmpint(hit, ==, 1);
2865bfd66ccbSHyman Huang
28661e8a1faeSThomas Huth /* Now, when we tested that throttling works, let it converge */
2867219044b8SPeter Xu migrate_ensure_converge(from);
28681e8a1faeSThomas Huth
28691e8a1faeSThomas Huth /*
28701e8a1faeSThomas Huth * Wait for pre-switchover status to check last throttle percentage
28711e8a1faeSThomas Huth * and remaining. These values will be zeroed later
28721e8a1faeSThomas Huth */
28731e8a1faeSThomas Huth wait_for_migration_status(from, "pre-switchover", NULL);
28741e8a1faeSThomas Huth
28751e8a1faeSThomas Huth /* The final percentage of throttling shouldn't be greater than max_pct */
28761e8a1faeSThomas Huth percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
28771e8a1faeSThomas Huth g_assert_cmpint(percentage, <=, max_pct);
28781e8a1faeSThomas Huth migrate_continue(from, "pre-switchover");
28791e8a1faeSThomas Huth
28801e8a1faeSThomas Huth qtest_qmp_eventwait(to, "RESUME");
28811e8a1faeSThomas Huth
28821e8a1faeSThomas Huth wait_for_serial("dest_serial");
28831e8a1faeSThomas Huth wait_for_migration_complete(from);
28841e8a1faeSThomas Huth
28851e8a1faeSThomas Huth test_migrate_end(from, to, true);
28861e8a1faeSThomas Huth }
28871e8a1faeSThomas Huth
2888490facffSDaniel P. Berrangé static void *
test_migrate_precopy_tcp_multifd_start_common(QTestState * from,QTestState * to,const char * method)2889490facffSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(QTestState *from,
2890490facffSDaniel P. Berrangé QTestState *to,
2891490facffSDaniel P. Berrangé const char *method)
2892b99784efSJuan Quintela {
2893b99784efSJuan Quintela migrate_set_parameter_int(from, "multifd-channels", 16);
2894b99784efSJuan Quintela migrate_set_parameter_int(to, "multifd-channels", 16);
2895b99784efSJuan Quintela
289696eef042SJuan Quintela migrate_set_parameter_str(from, "multifd-compression", method);
289796eef042SJuan Quintela migrate_set_parameter_str(to, "multifd-compression", method);
289896eef042SJuan Quintela
2899a1209bb7SDr. David Alan Gilbert migrate_set_capability(from, "multifd", true);
2900a1209bb7SDr. David Alan Gilbert migrate_set_capability(to, "multifd", true);
2901b99784efSJuan Quintela
2902b99784efSJuan Quintela /* Start incoming migration from the 1st socket */
29036830e53bSFabiano Rosas migrate_incoming_qmp(to, "tcp:127.0.0.1:0", "{}");
2904b99784efSJuan Quintela
2905490facffSDaniel P. Berrangé return NULL;
2906b99784efSJuan Quintela }
2907b99784efSJuan Quintela
2908490facffSDaniel P. Berrangé static void *
test_migrate_precopy_tcp_multifd_start(QTestState * from,QTestState * to)2909490facffSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start(QTestState *from,
2910490facffSDaniel P. Berrangé QTestState *to)
2911490facffSDaniel P. Berrangé {
2912490facffSDaniel P. Berrangé return test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2913b99784efSJuan Quintela }
2914b99784efSJuan Quintela
2915490facffSDaniel P. Berrangé static void *
test_migrate_precopy_tcp_multifd_start_zero_page_legacy(QTestState * from,QTestState * to)29161815338dSHao Xiang test_migrate_precopy_tcp_multifd_start_zero_page_legacy(QTestState *from,
29171815338dSHao Xiang QTestState *to)
29181815338dSHao Xiang {
29191815338dSHao Xiang test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
29201815338dSHao Xiang migrate_set_parameter_str(from, "zero-page-detection", "legacy");
29211815338dSHao Xiang return NULL;
29221815338dSHao Xiang }
29231815338dSHao Xiang
29241815338dSHao Xiang static void *
test_migration_precopy_tcp_multifd_start_no_zero_page(QTestState * from,QTestState * to)29251815338dSHao Xiang test_migration_precopy_tcp_multifd_start_no_zero_page(QTestState *from,
29261815338dSHao Xiang QTestState *to)
29271815338dSHao Xiang {
29281815338dSHao Xiang test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
29291815338dSHao Xiang migrate_set_parameter_str(from, "zero-page-detection", "none");
29301815338dSHao Xiang return NULL;
29311815338dSHao Xiang }
29321815338dSHao Xiang
29331815338dSHao Xiang static void *
test_migrate_precopy_tcp_multifd_zlib_start(QTestState * from,QTestState * to)2934490facffSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_zlib_start(QTestState *from,
2935490facffSDaniel P. Berrangé QTestState *to)
2936490facffSDaniel P. Berrangé {
29372b571432SBryan Zhang /*
29382b571432SBryan Zhang * Overloading this test to also check that set_parameter does not error.
29392b571432SBryan Zhang * This is also done in the tests for the other compression methods.
29402b571432SBryan Zhang */
29412b571432SBryan Zhang migrate_set_parameter_int(from, "multifd-zlib-level", 2);
29422b571432SBryan Zhang migrate_set_parameter_int(to, "multifd-zlib-level", 2);
29432b571432SBryan Zhang
2944490facffSDaniel P. Berrangé return test_migrate_precopy_tcp_multifd_start_common(from, to, "zlib");
2945490facffSDaniel P. Berrangé }
2946490facffSDaniel P. Berrangé
2947490facffSDaniel P. Berrangé #ifdef CONFIG_ZSTD
2948490facffSDaniel P. Berrangé static void *
test_migrate_precopy_tcp_multifd_zstd_start(QTestState * from,QTestState * to)2949490facffSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_zstd_start(QTestState *from,
2950490facffSDaniel P. Berrangé QTestState *to)
2951490facffSDaniel P. Berrangé {
29522b571432SBryan Zhang migrate_set_parameter_int(from, "multifd-zstd-level", 2);
29532b571432SBryan Zhang migrate_set_parameter_int(to, "multifd-zstd-level", 2);
29542b571432SBryan Zhang
2955490facffSDaniel P. Berrangé return test_migrate_precopy_tcp_multifd_start_common(from, to, "zstd");
2956490facffSDaniel P. Berrangé }
2957490facffSDaniel P. Berrangé #endif /* CONFIG_ZSTD */
2958490facffSDaniel P. Berrangé
2959afe166d4SBryan Zhang #ifdef CONFIG_QATZIP
2960afe166d4SBryan Zhang static void *
test_migrate_precopy_tcp_multifd_qatzip_start(QTestState * from,QTestState * to)2961afe166d4SBryan Zhang test_migrate_precopy_tcp_multifd_qatzip_start(QTestState *from,
2962afe166d4SBryan Zhang QTestState *to)
2963afe166d4SBryan Zhang {
2964afe166d4SBryan Zhang migrate_set_parameter_int(from, "multifd-qatzip-level", 2);
2965afe166d4SBryan Zhang migrate_set_parameter_int(to, "multifd-qatzip-level", 2);
2966afe166d4SBryan Zhang
2967afe166d4SBryan Zhang return test_migrate_precopy_tcp_multifd_start_common(from, to, "qatzip");
2968afe166d4SBryan Zhang }
2969afe166d4SBryan Zhang #endif
2970afe166d4SBryan Zhang
297108b82d20SYuan Liu #ifdef CONFIG_QPL
297208b82d20SYuan Liu static void *
test_migrate_precopy_tcp_multifd_qpl_start(QTestState * from,QTestState * to)297308b82d20SYuan Liu test_migrate_precopy_tcp_multifd_qpl_start(QTestState *from,
297408b82d20SYuan Liu QTestState *to)
297508b82d20SYuan Liu {
297608b82d20SYuan Liu return test_migrate_precopy_tcp_multifd_start_common(from, to, "qpl");
297708b82d20SYuan Liu }
297808b82d20SYuan Liu #endif /* CONFIG_QPL */
2979c519caa8SShameer Kolothum #ifdef CONFIG_UADK
2980c519caa8SShameer Kolothum static void *
test_migrate_precopy_tcp_multifd_uadk_start(QTestState * from,QTestState * to)2981c519caa8SShameer Kolothum test_migrate_precopy_tcp_multifd_uadk_start(QTestState *from,
2982c519caa8SShameer Kolothum QTestState *to)
2983c519caa8SShameer Kolothum {
2984c519caa8SShameer Kolothum return test_migrate_precopy_tcp_multifd_start_common(from, to, "uadk");
2985c519caa8SShameer Kolothum }
2986c519caa8SShameer Kolothum #endif /* CONFIG_UADK */
298708b82d20SYuan Liu
test_multifd_tcp_uri_none(void)29889d36d62cSHet Gala static void test_multifd_tcp_uri_none(void)
298996eef042SJuan Quintela {
2990490facffSDaniel P. Berrangé MigrateCommon args = {
2991490facffSDaniel P. Berrangé .listen_uri = "defer",
2992490facffSDaniel P. Berrangé .start_hook = test_migrate_precopy_tcp_multifd_start,
2993b861383cSPeter Xu /*
2994b861383cSPeter Xu * Multifd is more complicated than most of the features, it
2995b861383cSPeter Xu * directly takes guest page buffers when sending, make sure
2996b861383cSPeter Xu * everything will work alright even if guest page is changing.
2997b861383cSPeter Xu */
29983c4fb177SDaniel P. Berrangé .live = true,
2999490facffSDaniel P. Berrangé };
3000490facffSDaniel P. Berrangé test_precopy_common(&args);
300196eef042SJuan Quintela }
300296eef042SJuan Quintela
test_multifd_tcp_zero_page_legacy(void)30031815338dSHao Xiang static void test_multifd_tcp_zero_page_legacy(void)
30041815338dSHao Xiang {
30051815338dSHao Xiang MigrateCommon args = {
30061815338dSHao Xiang .listen_uri = "defer",
30071815338dSHao Xiang .start_hook = test_migrate_precopy_tcp_multifd_start_zero_page_legacy,
30081815338dSHao Xiang /*
30091815338dSHao Xiang * Multifd is more complicated than most of the features, it
30101815338dSHao Xiang * directly takes guest page buffers when sending, make sure
30111815338dSHao Xiang * everything will work alright even if guest page is changing.
30121815338dSHao Xiang */
30131815338dSHao Xiang .live = true,
30141815338dSHao Xiang };
30151815338dSHao Xiang test_precopy_common(&args);
30161815338dSHao Xiang }
30171815338dSHao Xiang
test_multifd_tcp_no_zero_page(void)30181815338dSHao Xiang static void test_multifd_tcp_no_zero_page(void)
30191815338dSHao Xiang {
30201815338dSHao Xiang MigrateCommon args = {
30211815338dSHao Xiang .listen_uri = "defer",
30221815338dSHao Xiang .start_hook = test_migration_precopy_tcp_multifd_start_no_zero_page,
30231815338dSHao Xiang /*
30241815338dSHao Xiang * Multifd is more complicated than most of the features, it
30251815338dSHao Xiang * directly takes guest page buffers when sending, make sure
30261815338dSHao Xiang * everything will work alright even if guest page is changing.
30271815338dSHao Xiang */
30281815338dSHao Xiang .live = true,
30291815338dSHao Xiang };
30301815338dSHao Xiang test_precopy_common(&args);
30311815338dSHao Xiang }
30321815338dSHao Xiang
test_multifd_tcp_channels_none(void)30339d36d62cSHet Gala static void test_multifd_tcp_channels_none(void)
30349d36d62cSHet Gala {
30359d36d62cSHet Gala MigrateCommon args = {
30369d36d62cSHet Gala .listen_uri = "defer",
30379d36d62cSHet Gala .start_hook = test_migrate_precopy_tcp_multifd_start,
30389d36d62cSHet Gala .live = true,
3039*19e56616SFabiano Rosas .connect_channels = ("[ { 'channel-type': 'main',"
30409d36d62cSHet Gala " 'addr': { 'transport': 'socket',"
30419d36d62cSHet Gala " 'type': 'inet',"
30429d36d62cSHet Gala " 'host': '127.0.0.1',"
3043*19e56616SFabiano Rosas " 'port': '0' } } ]"),
30449d36d62cSHet Gala };
30459d36d62cSHet Gala test_precopy_common(&args);
30469d36d62cSHet Gala }
30479d36d62cSHet Gala
test_multifd_tcp_zlib(void)30487ec2c2b3SJuan Quintela static void test_multifd_tcp_zlib(void)
30497ec2c2b3SJuan Quintela {
3050490facffSDaniel P. Berrangé MigrateCommon args = {
3051490facffSDaniel P. Berrangé .listen_uri = "defer",
3052490facffSDaniel P. Berrangé .start_hook = test_migrate_precopy_tcp_multifd_zlib_start,
3053490facffSDaniel P. Berrangé };
3054490facffSDaniel P. Berrangé test_precopy_common(&args);
30557ec2c2b3SJuan Quintela }
30567ec2c2b3SJuan Quintela
305787dc6f5fSJuan Quintela #ifdef CONFIG_ZSTD
test_multifd_tcp_zstd(void)305887dc6f5fSJuan Quintela static void test_multifd_tcp_zstd(void)
305987dc6f5fSJuan Quintela {
3060490facffSDaniel P. Berrangé MigrateCommon args = {
3061490facffSDaniel P. Berrangé .listen_uri = "defer",
3062490facffSDaniel P. Berrangé .start_hook = test_migrate_precopy_tcp_multifd_zstd_start,
3063490facffSDaniel P. Berrangé };
3064490facffSDaniel P. Berrangé test_precopy_common(&args);
306587dc6f5fSJuan Quintela }
306687dc6f5fSJuan Quintela #endif
306787dc6f5fSJuan Quintela
3068afe166d4SBryan Zhang #ifdef CONFIG_QATZIP
test_multifd_tcp_qatzip(void)3069afe166d4SBryan Zhang static void test_multifd_tcp_qatzip(void)
3070afe166d4SBryan Zhang {
3071afe166d4SBryan Zhang MigrateCommon args = {
3072afe166d4SBryan Zhang .listen_uri = "defer",
3073afe166d4SBryan Zhang .start_hook = test_migrate_precopy_tcp_multifd_qatzip_start,
3074afe166d4SBryan Zhang };
3075afe166d4SBryan Zhang test_precopy_common(&args);
3076afe166d4SBryan Zhang }
3077afe166d4SBryan Zhang #endif
3078afe166d4SBryan Zhang
307908b82d20SYuan Liu #ifdef CONFIG_QPL
test_multifd_tcp_qpl(void)308008b82d20SYuan Liu static void test_multifd_tcp_qpl(void)
308108b82d20SYuan Liu {
308208b82d20SYuan Liu MigrateCommon args = {
308308b82d20SYuan Liu .listen_uri = "defer",
308408b82d20SYuan Liu .start_hook = test_migrate_precopy_tcp_multifd_qpl_start,
308508b82d20SYuan Liu };
308608b82d20SYuan Liu test_precopy_common(&args);
308708b82d20SYuan Liu }
308808b82d20SYuan Liu #endif
308908b82d20SYuan Liu
3090c519caa8SShameer Kolothum #ifdef CONFIG_UADK
test_multifd_tcp_uadk(void)3091c519caa8SShameer Kolothum static void test_multifd_tcp_uadk(void)
3092c519caa8SShameer Kolothum {
3093c519caa8SShameer Kolothum MigrateCommon args = {
3094c519caa8SShameer Kolothum .listen_uri = "defer",
3095c519caa8SShameer Kolothum .start_hook = test_migrate_precopy_tcp_multifd_uadk_start,
3096c519caa8SShameer Kolothum };
3097c519caa8SShameer Kolothum test_precopy_common(&args);
3098c519caa8SShameer Kolothum }
3099c519caa8SShameer Kolothum #endif
3100c519caa8SShameer Kolothum
31014d6d2e87SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
31024d6d2e87SDaniel P. Berrangé static void *
test_migrate_multifd_tcp_tls_psk_start_match(QTestState * from,QTestState * to)31034d6d2e87SDaniel P. Berrangé test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from,
31044d6d2e87SDaniel P. Berrangé QTestState *to)
31054d6d2e87SDaniel P. Berrangé {
31064d6d2e87SDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
31074d6d2e87SDaniel P. Berrangé return test_migrate_tls_psk_start_match(from, to);
31084d6d2e87SDaniel P. Berrangé }
31094d6d2e87SDaniel P. Berrangé
31104d6d2e87SDaniel P. Berrangé static void *
test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState * from,QTestState * to)31114d6d2e87SDaniel P. Berrangé test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState *from,
31124d6d2e87SDaniel P. Berrangé QTestState *to)
31134d6d2e87SDaniel P. Berrangé {
31144d6d2e87SDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
31154d6d2e87SDaniel P. Berrangé return test_migrate_tls_psk_start_mismatch(from, to);
31164d6d2e87SDaniel P. Berrangé }
31174d6d2e87SDaniel P. Berrangé
3118ff32f1ddSDaniel P. Berrangé #ifdef CONFIG_TASN1
3119ff32f1ddSDaniel P. Berrangé static void *
test_migrate_multifd_tls_x509_start_default_host(QTestState * from,QTestState * to)3120ff32f1ddSDaniel P. Berrangé test_migrate_multifd_tls_x509_start_default_host(QTestState *from,
3121ff32f1ddSDaniel P. Berrangé QTestState *to)
3122ff32f1ddSDaniel P. Berrangé {
3123ff32f1ddSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
3124ff32f1ddSDaniel P. Berrangé return test_migrate_tls_x509_start_default_host(from, to);
3125ff32f1ddSDaniel P. Berrangé }
3126ff32f1ddSDaniel P. Berrangé
3127ff32f1ddSDaniel P. Berrangé static void *
test_migrate_multifd_tls_x509_start_override_host(QTestState * from,QTestState * to)3128ff32f1ddSDaniel P. Berrangé test_migrate_multifd_tls_x509_start_override_host(QTestState *from,
3129ff32f1ddSDaniel P. Berrangé QTestState *to)
3130ff32f1ddSDaniel P. Berrangé {
3131ff32f1ddSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
3132ff32f1ddSDaniel P. Berrangé return test_migrate_tls_x509_start_override_host(from, to);
3133ff32f1ddSDaniel P. Berrangé }
3134ff32f1ddSDaniel P. Berrangé
3135ff32f1ddSDaniel P. Berrangé static void *
test_migrate_multifd_tls_x509_start_mismatch_host(QTestState * from,QTestState * to)3136ff32f1ddSDaniel P. Berrangé test_migrate_multifd_tls_x509_start_mismatch_host(QTestState *from,
3137ff32f1ddSDaniel P. Berrangé QTestState *to)
3138ff32f1ddSDaniel P. Berrangé {
3139ff32f1ddSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
3140ff32f1ddSDaniel P. Berrangé return test_migrate_tls_x509_start_mismatch_host(from, to);
3141ff32f1ddSDaniel P. Berrangé }
3142ff32f1ddSDaniel P. Berrangé
3143ff32f1ddSDaniel P. Berrangé static void *
test_migrate_multifd_tls_x509_start_allow_anon_client(QTestState * from,QTestState * to)3144ff32f1ddSDaniel P. Berrangé test_migrate_multifd_tls_x509_start_allow_anon_client(QTestState *from,
3145ff32f1ddSDaniel P. Berrangé QTestState *to)
3146ff32f1ddSDaniel P. Berrangé {
3147ff32f1ddSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
3148ff32f1ddSDaniel P. Berrangé return test_migrate_tls_x509_start_allow_anon_client(from, to);
3149ff32f1ddSDaniel P. Berrangé }
3150ff32f1ddSDaniel P. Berrangé
3151ff32f1ddSDaniel P. Berrangé static void *
test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState * from,QTestState * to)3152ff32f1ddSDaniel P. Berrangé test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState *from,
3153ff32f1ddSDaniel P. Berrangé QTestState *to)
3154ff32f1ddSDaniel P. Berrangé {
3155ff32f1ddSDaniel P. Berrangé test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
3156ff32f1ddSDaniel P. Berrangé return test_migrate_tls_x509_start_reject_anon_client(from, to);
3157ff32f1ddSDaniel P. Berrangé }
3158ff32f1ddSDaniel P. Berrangé #endif /* CONFIG_TASN1 */
3159ff32f1ddSDaniel P. Berrangé
test_multifd_tcp_tls_psk_match(void)31604d6d2e87SDaniel P. Berrangé static void test_multifd_tcp_tls_psk_match(void)
31614d6d2e87SDaniel P. Berrangé {
31624d6d2e87SDaniel P. Berrangé MigrateCommon args = {
31634d6d2e87SDaniel P. Berrangé .listen_uri = "defer",
31644d6d2e87SDaniel P. Berrangé .start_hook = test_migrate_multifd_tcp_tls_psk_start_match,
31654d6d2e87SDaniel P. Berrangé .finish_hook = test_migrate_tls_psk_finish,
31664d6d2e87SDaniel P. Berrangé };
31674d6d2e87SDaniel P. Berrangé test_precopy_common(&args);
31684d6d2e87SDaniel P. Berrangé }
31694d6d2e87SDaniel P. Berrangé
test_multifd_tcp_tls_psk_mismatch(void)31704d6d2e87SDaniel P. Berrangé static void test_multifd_tcp_tls_psk_mismatch(void)
31714d6d2e87SDaniel P. Berrangé {
31724d6d2e87SDaniel P. Berrangé MigrateCommon args = {
31734d6d2e87SDaniel P. Berrangé .start = {
31744d6d2e87SDaniel P. Berrangé .hide_stderr = true,
31754d6d2e87SDaniel P. Berrangé },
31764d6d2e87SDaniel P. Berrangé .listen_uri = "defer",
31774d6d2e87SDaniel P. Berrangé .start_hook = test_migrate_multifd_tcp_tls_psk_start_mismatch,
31784d6d2e87SDaniel P. Berrangé .finish_hook = test_migrate_tls_psk_finish,
31794d6d2e87SDaniel P. Berrangé .result = MIG_TEST_FAIL,
31804d6d2e87SDaniel P. Berrangé };
31814d6d2e87SDaniel P. Berrangé test_precopy_common(&args);
31824d6d2e87SDaniel P. Berrangé }
3183ff32f1ddSDaniel P. Berrangé
3184ff32f1ddSDaniel P. Berrangé #ifdef CONFIG_TASN1
test_multifd_tcp_tls_x509_default_host(void)3185ff32f1ddSDaniel P. Berrangé static void test_multifd_tcp_tls_x509_default_host(void)
3186ff32f1ddSDaniel P. Berrangé {
3187ff32f1ddSDaniel P. Berrangé MigrateCommon args = {
3188ff32f1ddSDaniel P. Berrangé .listen_uri = "defer",
3189ff32f1ddSDaniel P. Berrangé .start_hook = test_migrate_multifd_tls_x509_start_default_host,
3190ff32f1ddSDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
3191ff32f1ddSDaniel P. Berrangé };
3192ff32f1ddSDaniel P. Berrangé test_precopy_common(&args);
3193ff32f1ddSDaniel P. Berrangé }
3194ff32f1ddSDaniel P. Berrangé
test_multifd_tcp_tls_x509_override_host(void)3195ff32f1ddSDaniel P. Berrangé static void test_multifd_tcp_tls_x509_override_host(void)
3196ff32f1ddSDaniel P. Berrangé {
3197ff32f1ddSDaniel P. Berrangé MigrateCommon args = {
3198ff32f1ddSDaniel P. Berrangé .listen_uri = "defer",
3199ff32f1ddSDaniel P. Berrangé .start_hook = test_migrate_multifd_tls_x509_start_override_host,
3200ff32f1ddSDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
3201ff32f1ddSDaniel P. Berrangé };
3202ff32f1ddSDaniel P. Berrangé test_precopy_common(&args);
3203ff32f1ddSDaniel P. Berrangé }
3204ff32f1ddSDaniel P. Berrangé
test_multifd_tcp_tls_x509_mismatch_host(void)3205ff32f1ddSDaniel P. Berrangé static void test_multifd_tcp_tls_x509_mismatch_host(void)
3206ff32f1ddSDaniel P. Berrangé {
3207ff32f1ddSDaniel P. Berrangé /*
3208ff32f1ddSDaniel P. Berrangé * This has different behaviour to the non-multifd case.
3209ff32f1ddSDaniel P. Berrangé *
3210ff32f1ddSDaniel P. Berrangé * In non-multifd case when client aborts due to mismatched
3211ff32f1ddSDaniel P. Berrangé * cert host, the server has already started trying to load
3212ff32f1ddSDaniel P. Berrangé * migration state, and so it exits with I/O failure.
3213ff32f1ddSDaniel P. Berrangé *
3214ff32f1ddSDaniel P. Berrangé * In multifd case when client aborts due to mismatched
3215ff32f1ddSDaniel P. Berrangé * cert host, the server is still waiting for the other
3216ff32f1ddSDaniel P. Berrangé * multifd connections to arrive so hasn't started trying
3217ff32f1ddSDaniel P. Berrangé * to load migration state, and thus just aborts the migration
3218ff32f1ddSDaniel P. Berrangé * without exiting.
3219ff32f1ddSDaniel P. Berrangé */
3220ff32f1ddSDaniel P. Berrangé MigrateCommon args = {
3221ff32f1ddSDaniel P. Berrangé .start = {
3222ff32f1ddSDaniel P. Berrangé .hide_stderr = true,
3223ff32f1ddSDaniel P. Berrangé },
3224ff32f1ddSDaniel P. Berrangé .listen_uri = "defer",
3225ff32f1ddSDaniel P. Berrangé .start_hook = test_migrate_multifd_tls_x509_start_mismatch_host,
3226ff32f1ddSDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
3227ff32f1ddSDaniel P. Berrangé .result = MIG_TEST_FAIL,
3228ff32f1ddSDaniel P. Berrangé };
3229ff32f1ddSDaniel P. Berrangé test_precopy_common(&args);
3230ff32f1ddSDaniel P. Berrangé }
3231ff32f1ddSDaniel P. Berrangé
test_multifd_tcp_tls_x509_allow_anon_client(void)3232ff32f1ddSDaniel P. Berrangé static void test_multifd_tcp_tls_x509_allow_anon_client(void)
3233ff32f1ddSDaniel P. Berrangé {
3234ff32f1ddSDaniel P. Berrangé MigrateCommon args = {
3235ff32f1ddSDaniel P. Berrangé .listen_uri = "defer",
3236ff32f1ddSDaniel P. Berrangé .start_hook = test_migrate_multifd_tls_x509_start_allow_anon_client,
3237ff32f1ddSDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
3238ff32f1ddSDaniel P. Berrangé };
3239ff32f1ddSDaniel P. Berrangé test_precopy_common(&args);
3240ff32f1ddSDaniel P. Berrangé }
3241ff32f1ddSDaniel P. Berrangé
test_multifd_tcp_tls_x509_reject_anon_client(void)3242ff32f1ddSDaniel P. Berrangé static void test_multifd_tcp_tls_x509_reject_anon_client(void)
3243ff32f1ddSDaniel P. Berrangé {
3244ff32f1ddSDaniel P. Berrangé MigrateCommon args = {
3245ff32f1ddSDaniel P. Berrangé .start = {
3246ff32f1ddSDaniel P. Berrangé .hide_stderr = true,
3247ff32f1ddSDaniel P. Berrangé },
3248ff32f1ddSDaniel P. Berrangé .listen_uri = "defer",
3249ff32f1ddSDaniel P. Berrangé .start_hook = test_migrate_multifd_tls_x509_start_reject_anon_client,
3250ff32f1ddSDaniel P. Berrangé .finish_hook = test_migrate_tls_x509_finish,
3251ff32f1ddSDaniel P. Berrangé .result = MIG_TEST_FAIL,
3252ff32f1ddSDaniel P. Berrangé };
3253ff32f1ddSDaniel P. Berrangé test_precopy_common(&args);
3254ff32f1ddSDaniel P. Berrangé }
3255ff32f1ddSDaniel P. Berrangé #endif /* CONFIG_TASN1 */
32564d6d2e87SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
32574d6d2e87SDaniel P. Berrangé
3258d795f474SJuan Quintela /*
3259d795f474SJuan Quintela * This test does:
3260d795f474SJuan Quintela * source target
3261d795f474SJuan Quintela * migrate_incoming
3262d795f474SJuan Quintela * migrate
3263d795f474SJuan Quintela * migrate_cancel
3264d795f474SJuan Quintela * launch another target
3265d795f474SJuan Quintela * migrate
3266d795f474SJuan Quintela *
3267d795f474SJuan Quintela * And see that it works
3268d795f474SJuan Quintela */
test_multifd_tcp_cancel(void)3269d795f474SJuan Quintela static void test_multifd_tcp_cancel(void)
3270d795f474SJuan Quintela {
327119da6edfSDaniel P. Berrangé MigrateStart args = {
327219da6edfSDaniel P. Berrangé .hide_stderr = true,
327319da6edfSDaniel P. Berrangé };
3274d795f474SJuan Quintela QTestState *from, *to, *to2;
3275d795f474SJuan Quintela
32763ff57401SPeter Xu if (test_migrate_start(&from, &to, "defer", &args)) {
3277d795f474SJuan Quintela return;
3278d795f474SJuan Quintela }
3279d795f474SJuan Quintela
3280886dfe9dSDaniel P. Berrangé migrate_ensure_non_converge(from);
3281e02f56e3SDaniel P. Berrangé migrate_prepare_for_dirty_mem(from);
3282d795f474SJuan Quintela
3283d795f474SJuan Quintela migrate_set_parameter_int(from, "multifd-channels", 16);
3284d795f474SJuan Quintela migrate_set_parameter_int(to, "multifd-channels", 16);
3285d795f474SJuan Quintela
3286a1209bb7SDr. David Alan Gilbert migrate_set_capability(from, "multifd", true);
3287a1209bb7SDr. David Alan Gilbert migrate_set_capability(to, "multifd", true);
3288d795f474SJuan Quintela
3289d795f474SJuan Quintela /* Start incoming migration from the 1st socket */
32906830e53bSFabiano Rosas migrate_incoming_qmp(to, "tcp:127.0.0.1:0", "{}");
3291d795f474SJuan Quintela
3292d795f474SJuan Quintela /* Wait for the first serial output from the source */
3293d795f474SJuan Quintela wait_for_serial("src_serial");
3294d795f474SJuan Quintela
3295d5ee387dSHet Gala migrate_qmp(from, to, NULL, NULL, "{}");
3296d795f474SJuan Quintela
3297e02f56e3SDaniel P. Berrangé migrate_wait_for_dirty_mem(from, to);
3298d795f474SJuan Quintela
3299d795f474SJuan Quintela migrate_cancel(from);
3300d795f474SJuan Quintela
3301f2d063e6SXuzhou Cheng /* Make sure QEMU process "to" exited */
3302f2d063e6SXuzhou Cheng qtest_set_expected_status(to, EXIT_FAILURE);
3303f2d063e6SXuzhou Cheng qtest_wait_qemu(to);
3304854f67faSPeter Maydell qtest_quit(to);
3305f2d063e6SXuzhou Cheng
33069adcdd49SJuraj Marcin /*
33079adcdd49SJuraj Marcin * Ensure the source QEMU finishes its cancellation process before we
33089adcdd49SJuraj Marcin * proceed with the setup of the next migration. The test_migrate_start()
33099adcdd49SJuraj Marcin * function and others might want to interact with the source in a way that
33109adcdd49SJuraj Marcin * is not possible while the migration is not canceled properly. For
33119adcdd49SJuraj Marcin * example, setting migration capabilities when the migration is still
33129adcdd49SJuraj Marcin * running leads to an error.
33139adcdd49SJuraj Marcin */
33149adcdd49SJuraj Marcin wait_for_migration_status(from, "cancelled", NULL);
33159adcdd49SJuraj Marcin
331619da6edfSDaniel P. Berrangé args = (MigrateStart){
331719da6edfSDaniel P. Berrangé .only_target = true,
331819da6edfSDaniel P. Berrangé };
3319d795f474SJuan Quintela
33203ff57401SPeter Xu if (test_migrate_start(&from, &to2, "defer", &args)) {
3321d795f474SJuan Quintela return;
3322d795f474SJuan Quintela }
3323d795f474SJuan Quintela
3324d795f474SJuan Quintela migrate_set_parameter_int(to2, "multifd-channels", 16);
3325d795f474SJuan Quintela
3326a1209bb7SDr. David Alan Gilbert migrate_set_capability(to2, "multifd", true);
3327d795f474SJuan Quintela
3328d795f474SJuan Quintela /* Start incoming migration from the 1st socket */
33296830e53bSFabiano Rosas migrate_incoming_qmp(to2, "tcp:127.0.0.1:0", "{}");
3330d795f474SJuan Quintela
3331e02f56e3SDaniel P. Berrangé migrate_ensure_non_converge(from);
3332d795f474SJuan Quintela
3333d5ee387dSHet Gala migrate_qmp(from, to2, NULL, NULL, "{}");
3334d795f474SJuan Quintela
333594aaf6d8SFabiano Rosas migrate_wait_for_dirty_mem(from, to2);
3336e02f56e3SDaniel P. Berrangé
3337e02f56e3SDaniel P. Berrangé migrate_ensure_converge(from);
3338d795f474SJuan Quintela
3339f0649758SSteve Sistare wait_for_stop(from, &src_state);
3340d795f474SJuan Quintela qtest_qmp_eventwait(to2, "RESUME");
3341d795f474SJuan Quintela
3342d795f474SJuan Quintela wait_for_serial("dest_serial");
3343d795f474SJuan Quintela wait_for_migration_complete(from);
3344d795f474SJuan Quintela test_migrate_end(from, to2, true);
3345d795f474SJuan Quintela }
3346d795f474SJuan Quintela
calc_dirty_rate(QTestState * who,uint64_t calc_time)33478aff6f50SHyman Huang(黄勇) static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
33488aff6f50SHyman Huang(黄勇) {
3349ffd47275SDaniel P. Berrangé qtest_qmp_assert_success(who,
33508aff6f50SHyman Huang(黄勇) "{ 'execute': 'calc-dirty-rate',"
33518aff6f50SHyman Huang(黄勇) "'arguments': { "
3352d46e6bbaSStefan Weil "'calc-time': %" PRIu64 ","
33538aff6f50SHyman Huang(黄勇) "'mode': 'dirty-ring' }}",
3354ffd47275SDaniel P. Berrangé calc_time);
33558aff6f50SHyman Huang(黄勇) }
33568aff6f50SHyman Huang(黄勇)
query_dirty_rate(QTestState * who)33578aff6f50SHyman Huang(黄勇) static QDict *query_dirty_rate(QTestState *who)
33588aff6f50SHyman Huang(黄勇) {
3359ffd47275SDaniel P. Berrangé return qtest_qmp_assert_success_ref(who,
3360ffd47275SDaniel P. Berrangé "{ 'execute': 'query-dirty-rate' }");
33618aff6f50SHyman Huang(黄勇) }
33628aff6f50SHyman Huang(黄勇)
dirtylimit_set_all(QTestState * who,uint64_t dirtyrate)33638aff6f50SHyman Huang(黄勇) static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate)
33648aff6f50SHyman Huang(黄勇) {
3365ffd47275SDaniel P. Berrangé qtest_qmp_assert_success(who,
33668aff6f50SHyman Huang(黄勇) "{ 'execute': 'set-vcpu-dirty-limit',"
33678aff6f50SHyman Huang(黄勇) "'arguments': { "
3368d46e6bbaSStefan Weil "'dirty-rate': %" PRIu64 " } }",
3369ffd47275SDaniel P. Berrangé dirtyrate);
33708aff6f50SHyman Huang(黄勇) }
33718aff6f50SHyman Huang(黄勇)
cancel_vcpu_dirty_limit(QTestState * who)33728aff6f50SHyman Huang(黄勇) static void cancel_vcpu_dirty_limit(QTestState *who)
33738aff6f50SHyman Huang(黄勇) {
3374ffd47275SDaniel P. Berrangé qtest_qmp_assert_success(who,
3375ffd47275SDaniel P. Berrangé "{ 'execute': 'cancel-vcpu-dirty-limit' }");
33768aff6f50SHyman Huang(黄勇) }
33778aff6f50SHyman Huang(黄勇)
query_vcpu_dirty_limit(QTestState * who)33788aff6f50SHyman Huang(黄勇) static QDict *query_vcpu_dirty_limit(QTestState *who)
33798aff6f50SHyman Huang(黄勇) {
33808aff6f50SHyman Huang(黄勇) QDict *rsp;
33818aff6f50SHyman Huang(黄勇)
33828aff6f50SHyman Huang(黄勇) rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }");
33838aff6f50SHyman Huang(黄勇) g_assert(!qdict_haskey(rsp, "error"));
33848aff6f50SHyman Huang(黄勇) g_assert(qdict_haskey(rsp, "return"));
33858aff6f50SHyman Huang(黄勇)
33868aff6f50SHyman Huang(黄勇) return rsp;
33878aff6f50SHyman Huang(黄勇) }
33888aff6f50SHyman Huang(黄勇)
calc_dirtyrate_ready(QTestState * who)33898aff6f50SHyman Huang(黄勇) static bool calc_dirtyrate_ready(QTestState *who)
33908aff6f50SHyman Huang(黄勇) {
33918aff6f50SHyman Huang(黄勇) QDict *rsp_return;
3392f0d74774SPeter Maydell const char *status;
3393f0d74774SPeter Maydell bool ready;
33948aff6f50SHyman Huang(黄勇)
33958aff6f50SHyman Huang(黄勇) rsp_return = query_dirty_rate(who);
33968aff6f50SHyman Huang(黄勇) g_assert(rsp_return);
33978aff6f50SHyman Huang(黄勇)
3398f0d74774SPeter Maydell status = qdict_get_str(rsp_return, "status");
33998aff6f50SHyman Huang(黄勇) g_assert(status);
3400f0d74774SPeter Maydell ready = g_strcmp0(status, "measuring");
3401f0d74774SPeter Maydell qobject_unref(rsp_return);
34028aff6f50SHyman Huang(黄勇)
3403f0d74774SPeter Maydell return ready;
34048aff6f50SHyman Huang(黄勇) }
34058aff6f50SHyman Huang(黄勇)
wait_for_calc_dirtyrate_complete(QTestState * who,int64_t time_s)34068aff6f50SHyman Huang(黄勇) static void wait_for_calc_dirtyrate_complete(QTestState *who,
34078aff6f50SHyman Huang(黄勇) int64_t time_s)
34088aff6f50SHyman Huang(黄勇) {
34098aff6f50SHyman Huang(黄勇) int max_try_count = 10000;
34108aff6f50SHyman Huang(黄勇) usleep(time_s * 1000000);
34118aff6f50SHyman Huang(黄勇)
34128aff6f50SHyman Huang(黄勇) while (!calc_dirtyrate_ready(who) && max_try_count--) {
34138aff6f50SHyman Huang(黄勇) usleep(1000);
34148aff6f50SHyman Huang(黄勇) }
34158aff6f50SHyman Huang(黄勇)
34168aff6f50SHyman Huang(黄勇) /*
34178aff6f50SHyman Huang(黄勇) * Set the timeout with 10 s(max_try_count * 1000us),
34188aff6f50SHyman Huang(黄勇) * if dirtyrate measurement not complete, fail test.
34198aff6f50SHyman Huang(黄勇) */
34208aff6f50SHyman Huang(黄勇) g_assert_cmpint(max_try_count, !=, 0);
34218aff6f50SHyman Huang(黄勇) }
34228aff6f50SHyman Huang(黄勇)
get_dirty_rate(QTestState * who)34238aff6f50SHyman Huang(黄勇) static int64_t get_dirty_rate(QTestState *who)
34248aff6f50SHyman Huang(黄勇) {
34258aff6f50SHyman Huang(黄勇) QDict *rsp_return;
342678a053bcSPeter Maydell const char *status;
34278aff6f50SHyman Huang(黄勇) QList *rates;
34288aff6f50SHyman Huang(黄勇) const QListEntry *entry;
34298aff6f50SHyman Huang(黄勇) QDict *rate;
34308aff6f50SHyman Huang(黄勇) int64_t dirtyrate;
34318aff6f50SHyman Huang(黄勇)
34328aff6f50SHyman Huang(黄勇) rsp_return = query_dirty_rate(who);
34338aff6f50SHyman Huang(黄勇) g_assert(rsp_return);
34348aff6f50SHyman Huang(黄勇)
343578a053bcSPeter Maydell status = qdict_get_str(rsp_return, "status");
34368aff6f50SHyman Huang(黄勇) g_assert(status);
34378aff6f50SHyman Huang(黄勇) g_assert_cmpstr(status, ==, "measured");
34388aff6f50SHyman Huang(黄勇)
34398aff6f50SHyman Huang(黄勇) rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate");
34408aff6f50SHyman Huang(黄勇) g_assert(rates && !qlist_empty(rates));
34418aff6f50SHyman Huang(黄勇)
34428aff6f50SHyman Huang(黄勇) entry = qlist_first(rates);
34438aff6f50SHyman Huang(黄勇) g_assert(entry);
34448aff6f50SHyman Huang(黄勇)
34458aff6f50SHyman Huang(黄勇) rate = qobject_to(QDict, qlist_entry_obj(entry));
34468aff6f50SHyman Huang(黄勇) g_assert(rate);
34478aff6f50SHyman Huang(黄勇)
34488aff6f50SHyman Huang(黄勇) dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1);
34498aff6f50SHyman Huang(黄勇)
34508aff6f50SHyman Huang(黄勇) qobject_unref(rsp_return);
34518aff6f50SHyman Huang(黄勇) return dirtyrate;
34528aff6f50SHyman Huang(黄勇) }
34538aff6f50SHyman Huang(黄勇)
get_limit_rate(QTestState * who)34548aff6f50SHyman Huang(黄勇) static int64_t get_limit_rate(QTestState *who)
34558aff6f50SHyman Huang(黄勇) {
34568aff6f50SHyman Huang(黄勇) QDict *rsp_return;
34578aff6f50SHyman Huang(黄勇) QList *rates;
34588aff6f50SHyman Huang(黄勇) const QListEntry *entry;
34598aff6f50SHyman Huang(黄勇) QDict *rate;
34608aff6f50SHyman Huang(黄勇) int64_t dirtyrate;
34618aff6f50SHyman Huang(黄勇)
34628aff6f50SHyman Huang(黄勇) rsp_return = query_vcpu_dirty_limit(who);
34638aff6f50SHyman Huang(黄勇) g_assert(rsp_return);
34648aff6f50SHyman Huang(黄勇)
34658aff6f50SHyman Huang(黄勇) rates = qdict_get_qlist(rsp_return, "return");
34668aff6f50SHyman Huang(黄勇) g_assert(rates && !qlist_empty(rates));
34678aff6f50SHyman Huang(黄勇)
34688aff6f50SHyman Huang(黄勇) entry = qlist_first(rates);
34698aff6f50SHyman Huang(黄勇) g_assert(entry);
34708aff6f50SHyman Huang(黄勇)
34718aff6f50SHyman Huang(黄勇) rate = qobject_to(QDict, qlist_entry_obj(entry));
34728aff6f50SHyman Huang(黄勇) g_assert(rate);
34738aff6f50SHyman Huang(黄勇)
34748aff6f50SHyman Huang(黄勇) dirtyrate = qdict_get_try_int(rate, "limit-rate", -1);
34758aff6f50SHyman Huang(黄勇)
34768aff6f50SHyman Huang(黄勇) qobject_unref(rsp_return);
34778aff6f50SHyman Huang(黄勇) return dirtyrate;
34788aff6f50SHyman Huang(黄勇) }
34798aff6f50SHyman Huang(黄勇)
dirtylimit_start_vm(void)34808aff6f50SHyman Huang(黄勇) static QTestState *dirtylimit_start_vm(void)
34818aff6f50SHyman Huang(黄勇) {
34828aff6f50SHyman Huang(黄勇) QTestState *vm = NULL;
34835014478eSSteve Sistare g_autofree gchar *cmd = NULL;
34845014478eSSteve Sistare
34855014478eSSteve Sistare bootfile_create(tmpfs, false);
34868aff6f50SHyman Huang(黄勇) cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
34878aff6f50SHyman Huang(黄勇) "-name dirtylimit-test,debug-threads=on "
34888aff6f50SHyman Huang(黄勇) "-m 150M -smp 1 "
34898aff6f50SHyman Huang(黄勇) "-serial file:%s/vm_serial "
34908aff6f50SHyman Huang(黄勇) "-drive file=%s,format=raw ",
34918aff6f50SHyman Huang(黄勇) tmpfs, bootpath);
34928aff6f50SHyman Huang(黄勇)
34938aff6f50SHyman Huang(黄勇) vm = qtest_init(cmd);
34948aff6f50SHyman Huang(黄勇) return vm;
34958aff6f50SHyman Huang(黄勇) }
34968aff6f50SHyman Huang(黄勇)
dirtylimit_stop_vm(QTestState * vm)34978aff6f50SHyman Huang(黄勇) static void dirtylimit_stop_vm(QTestState *vm)
34988aff6f50SHyman Huang(黄勇) {
34998aff6f50SHyman Huang(黄勇) qtest_quit(vm);
35008aff6f50SHyman Huang(黄勇) cleanup("vm_serial");
35018aff6f50SHyman Huang(黄勇) }
35028aff6f50SHyman Huang(黄勇)
test_vcpu_dirty_limit(void)35038aff6f50SHyman Huang(黄勇) static void test_vcpu_dirty_limit(void)
35048aff6f50SHyman Huang(黄勇) {
35058aff6f50SHyman Huang(黄勇) QTestState *vm;
35068aff6f50SHyman Huang(黄勇) int64_t origin_rate;
35078aff6f50SHyman Huang(黄勇) int64_t quota_rate;
35088aff6f50SHyman Huang(黄勇) int64_t rate ;
35098aff6f50SHyman Huang(黄勇) int max_try_count = 20;
35108aff6f50SHyman Huang(黄勇) int hit = 0;
35118aff6f50SHyman Huang(黄勇)
35128aff6f50SHyman Huang(黄勇) /* Start vm for vcpu dirtylimit test */
35138aff6f50SHyman Huang(黄勇) vm = dirtylimit_start_vm();
35148aff6f50SHyman Huang(黄勇)
35158aff6f50SHyman Huang(黄勇) /* Wait for the first serial output from the vm*/
35168aff6f50SHyman Huang(黄勇) wait_for_serial("vm_serial");
35178aff6f50SHyman Huang(黄勇)
35188aff6f50SHyman Huang(黄勇) /* Do dirtyrate measurement with calc time equals 1s */
35198aff6f50SHyman Huang(黄勇) calc_dirty_rate(vm, 1);
35208aff6f50SHyman Huang(黄勇)
35218aff6f50SHyman Huang(黄勇) /* Sleep calc time and wait for calc dirtyrate complete */
35228aff6f50SHyman Huang(黄勇) wait_for_calc_dirtyrate_complete(vm, 1);
35238aff6f50SHyman Huang(黄勇)
35248aff6f50SHyman Huang(黄勇) /* Query original dirty page rate */
35258aff6f50SHyman Huang(黄勇) origin_rate = get_dirty_rate(vm);
35268aff6f50SHyman Huang(黄勇)
35278aff6f50SHyman Huang(黄勇) /* VM booted from bootsect should dirty memory steadily */
35288aff6f50SHyman Huang(黄勇) assert(origin_rate != 0);
35298aff6f50SHyman Huang(黄勇)
35308aff6f50SHyman Huang(黄勇) /* Setup quota dirty page rate at half of origin */
35318aff6f50SHyman Huang(黄勇) quota_rate = origin_rate / 2;
35328aff6f50SHyman Huang(黄勇)
35338aff6f50SHyman Huang(黄勇) /* Set dirtylimit */
35348aff6f50SHyman Huang(黄勇) dirtylimit_set_all(vm, quota_rate);
35358aff6f50SHyman Huang(黄勇)
35368aff6f50SHyman Huang(黄勇) /*
35378aff6f50SHyman Huang(黄勇) * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit
35388aff6f50SHyman Huang(黄勇) * works literally
35398aff6f50SHyman Huang(黄勇) */
35408aff6f50SHyman Huang(黄勇) g_assert_cmpint(quota_rate, ==, get_limit_rate(vm));
35418aff6f50SHyman Huang(黄勇)
35428aff6f50SHyman Huang(黄勇) /* Sleep a bit to check if it take effect */
35438aff6f50SHyman Huang(黄勇) usleep(2000000);
35448aff6f50SHyman Huang(黄勇)
35458aff6f50SHyman Huang(黄勇) /*
35468aff6f50SHyman Huang(黄勇) * Check if dirtylimit take effect realistically, set the
35478aff6f50SHyman Huang(黄勇) * timeout with 20 s(max_try_count * 1s), if dirtylimit
35488aff6f50SHyman Huang(黄勇) * doesn't take effect, fail test.
35498aff6f50SHyman Huang(黄勇) */
35508aff6f50SHyman Huang(黄勇) while (--max_try_count) {
35518aff6f50SHyman Huang(黄勇) calc_dirty_rate(vm, 1);
35528aff6f50SHyman Huang(黄勇) wait_for_calc_dirtyrate_complete(vm, 1);
35538aff6f50SHyman Huang(黄勇) rate = get_dirty_rate(vm);
35548aff6f50SHyman Huang(黄勇)
35558aff6f50SHyman Huang(黄勇) /*
35568aff6f50SHyman Huang(黄勇) * Assume hitting if current rate is less
35578aff6f50SHyman Huang(黄勇) * than quota rate (within accepting error)
35588aff6f50SHyman Huang(黄勇) */
35598aff6f50SHyman Huang(黄勇) if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
35608aff6f50SHyman Huang(黄勇) hit = 1;
35618aff6f50SHyman Huang(黄勇) break;
35628aff6f50SHyman Huang(黄勇) }
35638aff6f50SHyman Huang(黄勇) }
35648aff6f50SHyman Huang(黄勇)
35658aff6f50SHyman Huang(黄勇) g_assert_cmpint(hit, ==, 1);
35668aff6f50SHyman Huang(黄勇)
35678aff6f50SHyman Huang(黄勇) hit = 0;
35688aff6f50SHyman Huang(黄勇) max_try_count = 20;
35698aff6f50SHyman Huang(黄勇)
35708aff6f50SHyman Huang(黄勇) /* Check if dirtylimit cancellation take effect */
35718aff6f50SHyman Huang(黄勇) cancel_vcpu_dirty_limit(vm);
35728aff6f50SHyman Huang(黄勇) while (--max_try_count) {
35738aff6f50SHyman Huang(黄勇) calc_dirty_rate(vm, 1);
35748aff6f50SHyman Huang(黄勇) wait_for_calc_dirtyrate_complete(vm, 1);
35758aff6f50SHyman Huang(黄勇) rate = get_dirty_rate(vm);
35768aff6f50SHyman Huang(黄勇)
35778aff6f50SHyman Huang(黄勇) /*
35788aff6f50SHyman Huang(黄勇) * Assume dirtylimit be canceled if current rate is
35798aff6f50SHyman Huang(黄勇) * greater than quota rate (within accepting error)
35808aff6f50SHyman Huang(黄勇) */
35818aff6f50SHyman Huang(黄勇) if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
35828aff6f50SHyman Huang(黄勇) hit = 1;
35838aff6f50SHyman Huang(黄勇) break;
35848aff6f50SHyman Huang(黄勇) }
35858aff6f50SHyman Huang(黄勇) }
35868aff6f50SHyman Huang(黄勇)
35878aff6f50SHyman Huang(黄勇) g_assert_cmpint(hit, ==, 1);
35888aff6f50SHyman Huang(黄勇) dirtylimit_stop_vm(vm);
35898aff6f50SHyman Huang(黄勇) }
35908aff6f50SHyman Huang(黄勇)
migrate_dirty_limit_wait_showup(QTestState * from,const int64_t period,const int64_t value)359117257b90SHyman Huang static void migrate_dirty_limit_wait_showup(QTestState *from,
359217257b90SHyman Huang const int64_t period,
359317257b90SHyman Huang const int64_t value)
359417257b90SHyman Huang {
359517257b90SHyman Huang /* Enable dirty limit capability */
359617257b90SHyman Huang migrate_set_capability(from, "dirty-limit", true);
359717257b90SHyman Huang
359817257b90SHyman Huang /* Set dirty limit parameters */
359917257b90SHyman Huang migrate_set_parameter_int(from, "x-vcpu-dirty-limit-period", period);
360017257b90SHyman Huang migrate_set_parameter_int(from, "vcpu-dirty-limit", value);
360117257b90SHyman Huang
360217257b90SHyman Huang /* Make sure migrate can't converge */
360317257b90SHyman Huang migrate_ensure_non_converge(from);
360417257b90SHyman Huang
360517257b90SHyman Huang /* To check limit rate after precopy */
360617257b90SHyman Huang migrate_set_capability(from, "pause-before-switchover", true);
360717257b90SHyman Huang
360817257b90SHyman Huang /* Wait for the serial output from the source */
360917257b90SHyman Huang wait_for_serial("src_serial");
361017257b90SHyman Huang }
361117257b90SHyman Huang
361217257b90SHyman Huang /*
361317257b90SHyman Huang * This test does:
361417257b90SHyman Huang * source destination
361517257b90SHyman Huang * start vm
361617257b90SHyman Huang * start incoming vm
361717257b90SHyman Huang * migrate
361817257b90SHyman Huang * wait dirty limit to begin
361917257b90SHyman Huang * cancel migrate
362017257b90SHyman Huang * cancellation check
362117257b90SHyman Huang * restart incoming vm
362217257b90SHyman Huang * migrate
362317257b90SHyman Huang * wait dirty limit to begin
362417257b90SHyman Huang * wait pre-switchover event
362517257b90SHyman Huang * convergence condition check
362617257b90SHyman Huang *
362717257b90SHyman Huang * And see if dirty limit migration works correctly.
362817257b90SHyman Huang * This test case involves many passes, so it runs in slow mode only.
362917257b90SHyman Huang */
test_migrate_dirty_limit(void)363017257b90SHyman Huang static void test_migrate_dirty_limit(void)
363117257b90SHyman Huang {
363217257b90SHyman Huang g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
363317257b90SHyman Huang QTestState *from, *to;
363417257b90SHyman Huang int64_t remaining;
363517257b90SHyman Huang uint64_t throttle_us_per_full;
363617257b90SHyman Huang /*
363717257b90SHyman Huang * We want the test to be stable and as fast as possible.
36388053feaaSMichael Tokarev * E.g., with 1Gb/s bandwidth migration may pass without dirty limit,
363917257b90SHyman Huang * so we need to decrease a bandwidth.
364017257b90SHyman Huang */
364117257b90SHyman Huang const int64_t dirtylimit_period = 1000, dirtylimit_value = 50;
364217257b90SHyman Huang const int64_t max_bandwidth = 400000000; /* ~400Mb/s */
364317257b90SHyman Huang const int64_t downtime_limit = 250; /* 250ms */
364417257b90SHyman Huang /*
364517257b90SHyman Huang * We migrate through unix-socket (> 500Mb/s).
364617257b90SHyman Huang * Thus, expected migration speed ~= bandwidth limit (< 500Mb/s).
364717257b90SHyman Huang * So, we can predict expected_threshold
364817257b90SHyman Huang */
364917257b90SHyman Huang const int64_t expected_threshold = max_bandwidth * downtime_limit / 1000;
365017257b90SHyman Huang int max_try_count = 10;
365117257b90SHyman Huang MigrateCommon args = {
365217257b90SHyman Huang .start = {
365317257b90SHyman Huang .hide_stderr = true,
365417257b90SHyman Huang .use_dirty_ring = true,
365517257b90SHyman Huang },
365617257b90SHyman Huang .listen_uri = uri,
365717257b90SHyman Huang .connect_uri = uri,
365817257b90SHyman Huang };
365917257b90SHyman Huang
366017257b90SHyman Huang /* Start src, dst vm */
366117257b90SHyman Huang if (test_migrate_start(&from, &to, args.listen_uri, &args.start)) {
366217257b90SHyman Huang return;
366317257b90SHyman Huang }
366417257b90SHyman Huang
366517257b90SHyman Huang /* Prepare for dirty limit migration and wait src vm show up */
366617257b90SHyman Huang migrate_dirty_limit_wait_showup(from, dirtylimit_period, dirtylimit_value);
366717257b90SHyman Huang
366817257b90SHyman Huang /* Start migrate */
3669d5ee387dSHet Gala migrate_qmp(from, to, args.connect_uri, NULL, "{}");
367017257b90SHyman Huang
367117257b90SHyman Huang /* Wait for dirty limit throttle begin */
367217257b90SHyman Huang throttle_us_per_full = 0;
367317257b90SHyman Huang while (throttle_us_per_full == 0) {
367417257b90SHyman Huang throttle_us_per_full =
3675*19e56616SFabiano Rosas read_migrate_property_int(from,
3676*19e56616SFabiano Rosas "dirty-limit-throttle-time-per-round");
367717257b90SHyman Huang usleep(100);
3678f0649758SSteve Sistare g_assert_false(src_state.stop_seen);
367917257b90SHyman Huang }
368017257b90SHyman Huang
368117257b90SHyman Huang /* Now cancel migrate and wait for dirty limit throttle switch off */
368217257b90SHyman Huang migrate_cancel(from);
368317257b90SHyman Huang wait_for_migration_status(from, "cancelled", NULL);
368417257b90SHyman Huang
368517257b90SHyman Huang /* Check if dirty limit throttle switched off, set timeout 1ms */
368617257b90SHyman Huang do {
368717257b90SHyman Huang throttle_us_per_full =
3688*19e56616SFabiano Rosas read_migrate_property_int(from,
3689*19e56616SFabiano Rosas "dirty-limit-throttle-time-per-round");
369017257b90SHyman Huang usleep(100);
3691f0649758SSteve Sistare g_assert_false(src_state.stop_seen);
369217257b90SHyman Huang } while (throttle_us_per_full != 0 && --max_try_count);
369317257b90SHyman Huang
369417257b90SHyman Huang /* Assert dirty limit is not in service */
369517257b90SHyman Huang g_assert_cmpint(throttle_us_per_full, ==, 0);
369617257b90SHyman Huang
369717257b90SHyman Huang args = (MigrateCommon) {
369817257b90SHyman Huang .start = {
369917257b90SHyman Huang .only_target = true,
370017257b90SHyman Huang .use_dirty_ring = true,
370117257b90SHyman Huang },
370217257b90SHyman Huang .listen_uri = uri,
370317257b90SHyman Huang .connect_uri = uri,
370417257b90SHyman Huang };
370517257b90SHyman Huang
370617257b90SHyman Huang /* Restart dst vm, src vm already show up so we needn't wait anymore */
370717257b90SHyman Huang if (test_migrate_start(&from, &to, args.listen_uri, &args.start)) {
370817257b90SHyman Huang return;
370917257b90SHyman Huang }
371017257b90SHyman Huang
371117257b90SHyman Huang /* Start migrate */
3712d5ee387dSHet Gala migrate_qmp(from, to, args.connect_uri, NULL, "{}");
371317257b90SHyman Huang
371417257b90SHyman Huang /* Wait for dirty limit throttle begin */
371517257b90SHyman Huang throttle_us_per_full = 0;
371617257b90SHyman Huang while (throttle_us_per_full == 0) {
371717257b90SHyman Huang throttle_us_per_full =
3718*19e56616SFabiano Rosas read_migrate_property_int(from,
3719*19e56616SFabiano Rosas "dirty-limit-throttle-time-per-round");
372017257b90SHyman Huang usleep(100);
3721f0649758SSteve Sistare g_assert_false(src_state.stop_seen);
372217257b90SHyman Huang }
372317257b90SHyman Huang
372417257b90SHyman Huang /*
372517257b90SHyman Huang * The dirty limit rate should equals the return value of
372617257b90SHyman Huang * query-vcpu-dirty-limit if dirty limit cap set
372717257b90SHyman Huang */
372817257b90SHyman Huang g_assert_cmpint(dirtylimit_value, ==, get_limit_rate(from));
372917257b90SHyman Huang
373017257b90SHyman Huang /* Now, we have tested if dirty limit works, let it converge */
373117257b90SHyman Huang migrate_set_parameter_int(from, "downtime-limit", downtime_limit);
373217257b90SHyman Huang migrate_set_parameter_int(from, "max-bandwidth", max_bandwidth);
373317257b90SHyman Huang
373417257b90SHyman Huang /*
373517257b90SHyman Huang * Wait for pre-switchover status to check if migration
373617257b90SHyman Huang * satisfy the convergence condition
373717257b90SHyman Huang */
373817257b90SHyman Huang wait_for_migration_status(from, "pre-switchover", NULL);
373917257b90SHyman Huang
374017257b90SHyman Huang remaining = read_ram_property_int(from, "remaining");
374117257b90SHyman Huang g_assert_cmpint(remaining, <,
374217257b90SHyman Huang (expected_threshold + expected_threshold / 100));
374317257b90SHyman Huang
374417257b90SHyman Huang migrate_continue(from, "pre-switchover");
374517257b90SHyman Huang
374617257b90SHyman Huang qtest_qmp_eventwait(to, "RESUME");
374717257b90SHyman Huang
374817257b90SHyman Huang wait_for_serial("dest_serial");
374917257b90SHyman Huang wait_for_migration_complete(from);
375017257b90SHyman Huang
375117257b90SHyman Huang test_migrate_end(from, to, true);
375217257b90SHyman Huang }
375317257b90SHyman Huang
kvm_dirty_ring_supported(void)37541f546b70SPeter Xu static bool kvm_dirty_ring_supported(void)
37551f546b70SPeter Xu {
375661c32485SPeter Xu #if defined(__linux__) && defined(HOST_X86_64)
37571f546b70SPeter Xu int ret, kvm_fd = open("/dev/kvm", O_RDONLY);
37581f546b70SPeter Xu
37591f546b70SPeter Xu if (kvm_fd < 0) {
37601f546b70SPeter Xu return false;
37611f546b70SPeter Xu }
37621f546b70SPeter Xu
37631f546b70SPeter Xu ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
37641f546b70SPeter Xu close(kvm_fd);
37651f546b70SPeter Xu
37661f546b70SPeter Xu /* We test with 4096 slots */
37671f546b70SPeter Xu if (ret < 4096) {
37681f546b70SPeter Xu return false;
37691f546b70SPeter Xu }
37701f546b70SPeter Xu
37711f546b70SPeter Xu return true;
37721f546b70SPeter Xu #else
37731f546b70SPeter Xu return false;
37741f546b70SPeter Xu #endif
37751f546b70SPeter Xu }
37761f546b70SPeter Xu
main(int argc,char ** argv)37771e8a1faeSThomas Huth int main(int argc, char **argv)
37781e8a1faeSThomas Huth {
37790c1ae3ffSFabiano Rosas bool has_kvm, has_tcg;
3780b1fdd21eSSteve Sistare bool has_uffd, is_x86;
3781e35b9a2eSDaniel P. Berrangé const char *arch;
3782e5553c1bSBin Meng g_autoptr(GError) err = NULL;
37835050ad2aSFabiano Rosas const char *qemu_src = getenv(QEMU_ENV_SRC);
37845050ad2aSFabiano Rosas const char *qemu_dst = getenv(QEMU_ENV_DST);
37851e8a1faeSThomas Huth int ret;
37861e8a1faeSThomas Huth
37871e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL);
37881e8a1faeSThomas Huth
37895050ad2aSFabiano Rosas /*
37905050ad2aSFabiano Rosas * The default QTEST_QEMU_BINARY must always be provided because
37915050ad2aSFabiano Rosas * that is what helpers use to query the accel type and
37925050ad2aSFabiano Rosas * architecture.
37935050ad2aSFabiano Rosas */
37945050ad2aSFabiano Rosas if (qemu_src && qemu_dst) {
37955050ad2aSFabiano Rosas g_test_message("Only one of %s, %s is allowed",
37965050ad2aSFabiano Rosas QEMU_ENV_SRC, QEMU_ENV_DST);
37975050ad2aSFabiano Rosas exit(1);
37985050ad2aSFabiano Rosas }
37995050ad2aSFabiano Rosas
3800e35b9a2eSDaniel P. Berrangé has_kvm = qtest_has_accel("kvm");
38010c1ae3ffSFabiano Rosas has_tcg = qtest_has_accel("tcg");
38020c1ae3ffSFabiano Rosas
38030c1ae3ffSFabiano Rosas if (!has_tcg && !has_kvm) {
38040c1ae3ffSFabiano Rosas g_test_skip("No KVM or TCG accelerator available");
38050c1ae3ffSFabiano Rosas return 0;
38060c1ae3ffSFabiano Rosas }
38070c1ae3ffSFabiano Rosas
3808e35b9a2eSDaniel P. Berrangé has_uffd = ufd_version_check();
3809e35b9a2eSDaniel P. Berrangé arch = qtest_get_arch();
3810b1fdd21eSSteve Sistare is_x86 = !strcmp(arch, "i386") || !strcmp(arch, "x86_64");
3811e35b9a2eSDaniel P. Berrangé
3812e5553c1bSBin Meng tmpfs = g_dir_make_tmp("migration-test-XXXXXX", &err);
38131e8a1faeSThomas Huth if (!tmpfs) {
3814b1f6208cSBin Meng g_test_message("Can't create temporary directory in %s: %s",
3815b1f6208cSBin Meng g_get_tmp_dir(), err->message);
38161e8a1faeSThomas Huth }
38171e8a1faeSThomas Huth g_assert(tmpfs);
38181e8a1faeSThomas Huth
38191e8a1faeSThomas Huth module_call_init(MODULE_INIT_QOM);
38201e8a1faeSThomas Huth
382164853655SThomas Huth migration_test_add("/migration/bad_dest", test_baddest);
382264853655SThomas Huth #ifndef _WIN32
382364853655SThomas Huth migration_test_add("/migration/analyze-script", test_analyze_script);
382464853655SThomas Huth #endif
382564853655SThomas Huth
3826b1fdd21eSSteve Sistare if (is_x86) {
38276f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/live",
3828b1fdd21eSSteve Sistare test_precopy_unix_suspend_live);
38296f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/suspend/notlive",
3830b1fdd21eSSteve Sistare test_precopy_unix_suspend_notlive);
3831b1fdd21eSSteve Sistare }
3832b1fdd21eSSteve Sistare
38332649a725SPeter Xu if (has_uffd) {
38346f0771deSFabiano Rosas migration_test_add("/migration/postcopy/plain", test_postcopy);
38356f0771deSFabiano Rosas migration_test_add("/migration/postcopy/recovery/plain",
3836767fa9cfSPeter Xu test_postcopy_recovery);
38376f0771deSFabiano Rosas migration_test_add("/migration/postcopy/preempt/plain",
38386f0771deSFabiano Rosas test_postcopy_preempt);
38396f0771deSFabiano Rosas migration_test_add("/migration/postcopy/preempt/recovery/plain",
38408f6fe915SPeter Xu test_postcopy_preempt_recovery);
38416cf56a87SPeter Xu migration_test_add("/migration/postcopy/recovery/double-failures/handshake",
38426cf56a87SPeter Xu test_postcopy_recovery_fail_handshake);
38436cf56a87SPeter Xu migration_test_add("/migration/postcopy/recovery/double-failures/reconnect",
38446cf56a87SPeter Xu test_postcopy_recovery_fail_reconnect);
38452b58a8b9SSteve Sistare if (is_x86) {
38466f0771deSFabiano Rosas migration_test_add("/migration/postcopy/suspend",
38472b58a8b9SSteve Sistare test_postcopy_suspend);
38482b58a8b9SSteve Sistare }
38492649a725SPeter Xu }
3850d1a27b16SPeter Xu
38516f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/plain",
38526f0771deSFabiano Rosas test_precopy_unix_plain);
38536abc8f12SFabiano Rosas if (g_test_slow()) {
38546f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/xbzrle",
38556f0771deSFabiano Rosas test_precopy_unix_xbzrle);
38566abc8f12SFabiano Rosas }
38576f0771deSFabiano Rosas migration_test_add("/migration/precopy/file",
38583dc35470SFabiano Rosas test_precopy_file);
38596f0771deSFabiano Rosas migration_test_add("/migration/precopy/file/offset",
38603dc35470SFabiano Rosas test_precopy_file_offset);
3861926554c0SFabiano Rosas #ifndef _WIN32
3862926554c0SFabiano Rosas migration_test_add("/migration/precopy/file/offset/fdset",
3863926554c0SFabiano Rosas test_precopy_file_offset_fdset);
3864926554c0SFabiano Rosas #endif
38656f0771deSFabiano Rosas migration_test_add("/migration/precopy/file/offset/bad",
38663dc35470SFabiano Rosas test_precopy_file_offset_bad);
38673dc35470SFabiano Rosas
3868e7b428d6SSteve Sistare /*
3869e7b428d6SSteve Sistare * Our CI system has problems with shared memory.
3870e7b428d6SSteve Sistare * Don't run this test until we find a workaround.
3871e7b428d6SSteve Sistare */
3872e7b428d6SSteve Sistare if (getenv("QEMU_TEST_FLAKY_TESTS")) {
38736f0771deSFabiano Rosas migration_test_add("/migration/mode/reboot", test_mode_reboot);
3874e7b428d6SSteve Sistare }
3875e7b428d6SSteve Sistare
3876c7076ec3SFabiano Rosas migration_test_add("/migration/precopy/file/mapped-ram",
3877c7076ec3SFabiano Rosas test_precopy_file_mapped_ram);
3878c7076ec3SFabiano Rosas migration_test_add("/migration/precopy/file/mapped-ram/live",
3879c7076ec3SFabiano Rosas test_precopy_file_mapped_ram_live);
3880c7076ec3SFabiano Rosas
38817a09f092SFabiano Rosas migration_test_add("/migration/multifd/file/mapped-ram",
38827a09f092SFabiano Rosas test_multifd_file_mapped_ram);
38837a09f092SFabiano Rosas migration_test_add("/migration/multifd/file/mapped-ram/live",
38847a09f092SFabiano Rosas test_multifd_file_mapped_ram_live);
38857a09f092SFabiano Rosas
3886408d295dSFabiano Rosas migration_test_add("/migration/multifd/file/mapped-ram/dio",
3887408d295dSFabiano Rosas test_multifd_file_mapped_ram_dio);
3888408d295dSFabiano Rosas
388931a5a303SFabiano Rosas #ifndef _WIN32
389031a5a303SFabiano Rosas migration_test_add("/migration/multifd/file/mapped-ram/fdset",
389131a5a303SFabiano Rosas test_multifd_file_mapped_ram_fdset);
389231a5a303SFabiano Rosas migration_test_add("/migration/multifd/file/mapped-ram/fdset/dio",
389331a5a303SFabiano Rosas test_multifd_file_mapped_ram_fdset_dio);
389431a5a303SFabiano Rosas #endif
389531a5a303SFabiano Rosas
389658d25e97SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
38976f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/tls/psk",
389858d25e97SDaniel P. Berrangé test_precopy_unix_tls_psk);
38992649a725SPeter Xu
39002649a725SPeter Xu if (has_uffd) {
3901d1a27b16SPeter Xu /*
3902d1a27b16SPeter Xu * NOTE: psk test is enough for postcopy, as other types of TLS
3903d1a27b16SPeter Xu * channels are tested under precopy. Here what we want to test is the
3904d1a27b16SPeter Xu * general postcopy path that has TLS channel enabled.
3905d1a27b16SPeter Xu */
39066f0771deSFabiano Rosas migration_test_add("/migration/postcopy/tls/psk",
39076f0771deSFabiano Rosas test_postcopy_tls_psk);
39086f0771deSFabiano Rosas migration_test_add("/migration/postcopy/recovery/tls/psk",
3909767fa9cfSPeter Xu test_postcopy_recovery_tls_psk);
39106f0771deSFabiano Rosas migration_test_add("/migration/postcopy/preempt/tls/psk",
39118f6fe915SPeter Xu test_postcopy_preempt_tls_psk);
39126f0771deSFabiano Rosas migration_test_add("/migration/postcopy/preempt/recovery/tls/psk",
39138f6fe915SPeter Xu test_postcopy_preempt_all);
39142649a725SPeter Xu }
3915d47b83b1SDaniel P. Berrangé #ifdef CONFIG_TASN1
39166f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/tls/x509/default-host",
3917d47b83b1SDaniel P. Berrangé test_precopy_unix_tls_x509_default_host);
39186f0771deSFabiano Rosas migration_test_add("/migration/precopy/unix/tls/x509/override-host",
3919d47b83b1SDaniel P. Berrangé test_precopy_unix_tls_x509_override_host);
3920d47b83b1SDaniel P. Berrangé #endif /* CONFIG_TASN1 */
392158d25e97SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
392258d25e97SDaniel P. Berrangé
39236f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/plain", test_precopy_tcp_plain);
39247e6a5c73SAvihai Horon
39256f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/plain/switchover-ack",
39267e6a5c73SAvihai Horon test_precopy_tcp_switchover_ack);
39277e6a5c73SAvihai Horon
392858d25e97SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
39296f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/psk/match",
393058d25e97SDaniel P. Berrangé test_precopy_tcp_tls_psk_match);
39316f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/psk/mismatch",
393258d25e97SDaniel P. Berrangé test_precopy_tcp_tls_psk_mismatch);
3933d47b83b1SDaniel P. Berrangé #ifdef CONFIG_TASN1
39346f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/default-host",
3935d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_default_host);
39366f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/override-host",
3937d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_override_host);
39386f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/mismatch-host",
3939d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_mismatch_host);
39406f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/friendly-client",
3941d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_friendly_client);
39426f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/hostile-client",
3943d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_hostile_client);
39446f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/allow-anon-client",
3945d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_allow_anon_client);
39466f0771deSFabiano Rosas migration_test_add("/migration/precopy/tcp/tls/x509/reject-anon-client",
3947d47b83b1SDaniel P. Berrangé test_precopy_tcp_tls_x509_reject_anon_client);
3948d47b83b1SDaniel P. Berrangé #endif /* CONFIG_TASN1 */
394958d25e97SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
395058d25e97SDaniel P. Berrangé
39516f0771deSFabiano Rosas /* migration_test_add("/migration/ignore_shared", test_ignore_shared); */
3952d7613ee2SBin Meng #ifndef _WIN32
395385cf9abdSFabiano Rosas migration_test_add("/migration/precopy/fd/tcp",
395485cf9abdSFabiano Rosas test_migrate_precopy_fd_socket);
39556d79bd68SFabiano Rosas migration_test_add("/migration/precopy/fd/file",
39566d79bd68SFabiano Rosas test_migrate_precopy_fd_file);
3957d7613ee2SBin Meng #endif
39586f0771deSFabiano Rosas migration_test_add("/migration/validate_uuid", test_validate_uuid);
39596f0771deSFabiano Rosas migration_test_add("/migration/validate_uuid_error",
39606f0771deSFabiano Rosas test_validate_uuid_error);
39616f0771deSFabiano Rosas migration_test_add("/migration/validate_uuid_src_not_set",
39621e8a1faeSThomas Huth test_validate_uuid_src_not_set);
39636f0771deSFabiano Rosas migration_test_add("/migration/validate_uuid_dst_not_set",
39641e8a1faeSThomas Huth test_validate_uuid_dst_not_set);
3965bc6307a5SHet Gala migration_test_add("/migration/validate_uri/channels/both_set",
3966bc6307a5SHet Gala test_validate_uri_channels_both_set);
3967bc6307a5SHet Gala migration_test_add("/migration/validate_uri/channels/none_set",
3968bc6307a5SHet Gala test_validate_uri_channels_none_set);
396974902af7SJuan Quintela /*
397074902af7SJuan Quintela * See explanation why this test is slow on function definition
397174902af7SJuan Quintela */
397274902af7SJuan Quintela if (g_test_slow()) {
39736f0771deSFabiano Rosas migration_test_add("/migration/auto_converge",
39746f0771deSFabiano Rosas test_migrate_auto_converge);
397517257b90SHyman Huang if (g_str_equal(arch, "x86_64") &&
397617257b90SHyman Huang has_kvm && kvm_dirty_ring_supported()) {
39776f0771deSFabiano Rosas migration_test_add("/migration/dirty_limit",
39786f0771deSFabiano Rosas test_migrate_dirty_limit);
397917257b90SHyman Huang }
398074902af7SJuan Quintela }
39819d36d62cSHet Gala migration_test_add("/migration/multifd/tcp/uri/plain/none",
39829d36d62cSHet Gala test_multifd_tcp_uri_none);
39839d36d62cSHet Gala migration_test_add("/migration/multifd/tcp/channels/plain/none",
39849d36d62cSHet Gala test_multifd_tcp_channels_none);
39851815338dSHao Xiang migration_test_add("/migration/multifd/tcp/plain/zero-page/legacy",
39861815338dSHao Xiang test_multifd_tcp_zero_page_legacy);
39871815338dSHao Xiang migration_test_add("/migration/multifd/tcp/plain/zero-page/none",
39881815338dSHao Xiang test_multifd_tcp_no_zero_page);
39896f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/cancel",
39904d6d2e87SDaniel P. Berrangé test_multifd_tcp_cancel);
39916f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zlib",
39924d6d2e87SDaniel P. Berrangé test_multifd_tcp_zlib);
399387dc6f5fSJuan Quintela #ifdef CONFIG_ZSTD
39946f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/plain/zstd",
39954d6d2e87SDaniel P. Berrangé test_multifd_tcp_zstd);
399687dc6f5fSJuan Quintela #endif
3997afe166d4SBryan Zhang #ifdef CONFIG_QATZIP
3998afe166d4SBryan Zhang migration_test_add("/migration/multifd/tcp/plain/qatzip",
3999afe166d4SBryan Zhang test_multifd_tcp_qatzip);
4000afe166d4SBryan Zhang #endif
400108b82d20SYuan Liu #ifdef CONFIG_QPL
400208b82d20SYuan Liu migration_test_add("/migration/multifd/tcp/plain/qpl",
400308b82d20SYuan Liu test_multifd_tcp_qpl);
400408b82d20SYuan Liu #endif
4005c519caa8SShameer Kolothum #ifdef CONFIG_UADK
4006c519caa8SShameer Kolothum migration_test_add("/migration/multifd/tcp/plain/uadk",
4007c519caa8SShameer Kolothum test_multifd_tcp_uadk);
4008c519caa8SShameer Kolothum #endif
40094d6d2e87SDaniel P. Berrangé #ifdef CONFIG_GNUTLS
40106f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/psk/match",
40114d6d2e87SDaniel P. Berrangé test_multifd_tcp_tls_psk_match);
40126f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/psk/mismatch",
40134d6d2e87SDaniel P. Berrangé test_multifd_tcp_tls_psk_mismatch);
4014ff32f1ddSDaniel P. Berrangé #ifdef CONFIG_TASN1
40156f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/x509/default-host",
4016ff32f1ddSDaniel P. Berrangé test_multifd_tcp_tls_x509_default_host);
40176f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/x509/override-host",
4018ff32f1ddSDaniel P. Berrangé test_multifd_tcp_tls_x509_override_host);
40196f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/x509/mismatch-host",
4020ff32f1ddSDaniel P. Berrangé test_multifd_tcp_tls_x509_mismatch_host);
40216f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/x509/allow-anon-client",
4022ff32f1ddSDaniel P. Berrangé test_multifd_tcp_tls_x509_allow_anon_client);
40236f0771deSFabiano Rosas migration_test_add("/migration/multifd/tcp/tls/x509/reject-anon-client",
4024ff32f1ddSDaniel P. Berrangé test_multifd_tcp_tls_x509_reject_anon_client);
4025ff32f1ddSDaniel P. Berrangé #endif /* CONFIG_TASN1 */
40264d6d2e87SDaniel P. Berrangé #endif /* CONFIG_GNUTLS */
40271e8a1faeSThomas Huth
40281bca64a3SThomas Huth if (g_str_equal(arch, "x86_64") && has_kvm && kvm_dirty_ring_supported()) {
40296f0771deSFabiano Rosas migration_test_add("/migration/dirty_ring",
40301f546b70SPeter Xu test_precopy_unix_dirty_ring);
40316abc8f12SFabiano Rosas if (qtest_has_machine("pc") && g_test_slow()) {
40326f0771deSFabiano Rosas migration_test_add("/migration/vcpu_dirty_limit",
40338aff6f50SHyman Huang(黄勇) test_vcpu_dirty_limit);
40341f546b70SPeter Xu }
4035d41c9896SThomas Huth }
40361f546b70SPeter Xu
40371e8a1faeSThomas Huth ret = g_test_run();
40381e8a1faeSThomas Huth
40391e8a1faeSThomas Huth g_assert_cmpint(ret, ==, 0);
40401e8a1faeSThomas Huth
40410c690d3eSJuan Quintela bootfile_delete();
40421e8a1faeSThomas Huth ret = rmdir(tmpfs);
40431e8a1faeSThomas Huth if (ret != 0) {
40441e8a1faeSThomas Huth g_test_message("unable to rmdir: path (%s): %s",
40451e8a1faeSThomas Huth tmpfs, strerror(errno));
40461e8a1faeSThomas Huth }
4047e5553c1bSBin Meng g_free(tmpfs);
40481e8a1faeSThomas Huth
40491e8a1faeSThomas Huth return ret;
40501e8a1faeSThomas Huth }
4051