]> git.proxmox.com Git - mirror_qemu.git/blob - tests/qtest/migration-test.c
tests/qtest: distinguish src/dst migration VM stop/resume events
[mirror_qemu.git] / tests / qtest / migration-test.c
1 /*
2 * QTest testcase for migration
3 *
4 * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
5 * based on the vhost-user-test.c that is:
6 * Copyright (c) 2014 Virtual Open Systems Sarl.
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
10 *
11 */
12
13 #include "qemu/osdep.h"
14
15 #include "libqtest.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/qdict.h"
18 #include "qemu/module.h"
19 #include "qemu/option.h"
20 #include "qemu/range.h"
21 #include "qemu/sockets.h"
22 #include "chardev/char.h"
23 #include "qapi/qapi-visit-sockets.h"
24 #include "qapi/qobject-input-visitor.h"
25 #include "qapi/qobject-output-visitor.h"
26 #include "crypto/tlscredspsk.h"
27 #include "qapi/qmp/qlist.h"
28
29 #include "migration-helpers.h"
30 #include "tests/migration/migration-test.h"
31 #ifdef CONFIG_GNUTLS
32 # include "tests/unit/crypto-tls-psk-helpers.h"
33 # ifdef CONFIG_TASN1
34 # include "tests/unit/crypto-tls-x509-helpers.h"
35 # endif /* CONFIG_TASN1 */
36 #endif /* CONFIG_GNUTLS */
37
38 /* For dirty ring test; so far only x86_64 is supported */
39 #if defined(__linux__) && defined(HOST_X86_64)
40 #include "linux/kvm.h"
41 #endif
42
43 unsigned start_address;
44 unsigned end_address;
45 static bool uffd_feature_thread_id;
46 static bool got_src_stop;
47 static bool got_dst_resume;
48
49 /*
50 * Dirtylimit stop working if dirty page rate error
51 * value less than DIRTYLIMIT_TOLERANCE_RANGE
52 */
53 #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */
54
55 #if defined(__linux__)
56 #include <sys/syscall.h>
57 #include <sys/vfs.h>
58 #endif
59
60 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
61 #include <sys/eventfd.h>
62 #include <sys/ioctl.h>
63 #include "qemu/userfaultfd.h"
64
65 static bool ufd_version_check(void)
66 {
67 struct uffdio_api api_struct;
68 uint64_t ioctl_mask;
69
70 int ufd = uffd_open(O_CLOEXEC);
71
72 if (ufd == -1) {
73 g_test_message("Skipping test: userfaultfd not available");
74 return false;
75 }
76
77 api_struct.api = UFFD_API;
78 api_struct.features = 0;
79 if (ioctl(ufd, UFFDIO_API, &api_struct)) {
80 g_test_message("Skipping test: UFFDIO_API failed");
81 return false;
82 }
83 uffd_feature_thread_id = api_struct.features & UFFD_FEATURE_THREAD_ID;
84
85 ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
86 (__u64)1 << _UFFDIO_UNREGISTER;
87 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
88 g_test_message("Skipping test: Missing userfault feature");
89 return false;
90 }
91
92 return true;
93 }
94
95 #else
96 static bool ufd_version_check(void)
97 {
98 g_test_message("Skipping test: Userfault not available (builtdtime)");
99 return false;
100 }
101
102 #endif
103
104 static char *tmpfs;
105
106 /* The boot file modifies memory area in [start_address, end_address)
107 * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
108 */
109 #include "tests/migration/i386/a-b-bootblock.h"
110 #include "tests/migration/aarch64/a-b-kernel.h"
111 #include "tests/migration/s390x/a-b-bios.h"
112
113 static void init_bootfile(const char *bootpath, void *content, size_t len)
114 {
115 FILE *bootfile = fopen(bootpath, "wb");
116
117 g_assert_cmpint(fwrite(content, len, 1, bootfile), ==, 1);
118 fclose(bootfile);
119 }
120
121 /*
122 * Wait for some output in the serial output file,
123 * we get an 'A' followed by an endless string of 'B's
124 * but on the destination we won't have the A.
125 */
126 static void wait_for_serial(const char *side)
127 {
128 g_autofree char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
129 FILE *serialfile = fopen(serialpath, "r");
130 const char *arch = qtest_get_arch();
131 int started = (strcmp(side, "src_serial") == 0 &&
132 strcmp(arch, "ppc64") == 0) ? 0 : 1;
133
134 do {
135 int readvalue = fgetc(serialfile);
136
137 if (!started) {
138 /* SLOF prints its banner before starting test,
139 * to ignore it, mark the start of the test with '_',
140 * ignore all characters until this marker
141 */
142 switch (readvalue) {
143 case '_':
144 started = 1;
145 break;
146 case EOF:
147 fseek(serialfile, 0, SEEK_SET);
148 usleep(1000);
149 break;
150 }
151 continue;
152 }
153 switch (readvalue) {
154 case 'A':
155 /* Fine */
156 break;
157
158 case 'B':
159 /* It's alive! */
160 fclose(serialfile);
161 return;
162
163 case EOF:
164 started = (strcmp(side, "src_serial") == 0 &&
165 strcmp(arch, "ppc64") == 0) ? 0 : 1;
166 fseek(serialfile, 0, SEEK_SET);
167 usleep(1000);
168 break;
169
170 default:
171 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
172 g_assert_not_reached();
173 }
174 } while (true);
175 }
176
177 /*
178 * It's tricky to use qemu's migration event capability with qtest,
179 * events suddenly appearing confuse the qmp()/hmp() responses.
180 */
181
182 static int64_t read_ram_property_int(QTestState *who, const char *property)
183 {
184 QDict *rsp_return, *rsp_ram;
185 int64_t result;
186
187 rsp_return = migrate_query_not_failed(who);
188 if (!qdict_haskey(rsp_return, "ram")) {
189 /* Still in setup */
190 result = 0;
191 } else {
192 rsp_ram = qdict_get_qdict(rsp_return, "ram");
193 result = qdict_get_try_int(rsp_ram, property, 0);
194 }
195 qobject_unref(rsp_return);
196 return result;
197 }
198
199 static int64_t read_migrate_property_int(QTestState *who, const char *property)
200 {
201 QDict *rsp_return;
202 int64_t result;
203
204 rsp_return = migrate_query_not_failed(who);
205 result = qdict_get_try_int(rsp_return, property, 0);
206 qobject_unref(rsp_return);
207 return result;
208 }
209
210 static uint64_t get_migration_pass(QTestState *who)
211 {
212 return read_ram_property_int(who, "dirty-sync-count");
213 }
214
215 static void read_blocktime(QTestState *who)
216 {
217 QDict *rsp_return;
218
219 rsp_return = migrate_query_not_failed(who);
220 g_assert(qdict_haskey(rsp_return, "postcopy-blocktime"));
221 qobject_unref(rsp_return);
222 }
223
224 static void wait_for_migration_pass(QTestState *who)
225 {
226 uint64_t initial_pass = get_migration_pass(who);
227 uint64_t pass;
228
229 /* Wait for the 1st sync */
230 while (!got_src_stop && !initial_pass) {
231 usleep(1000);
232 initial_pass = get_migration_pass(who);
233 }
234
235 do {
236 usleep(1000);
237 pass = get_migration_pass(who);
238 } while (pass == initial_pass && !got_src_stop);
239 }
240
241 static void check_guests_ram(QTestState *who)
242 {
243 /* Our ASM test will have been incrementing one byte from each page from
244 * start_address to < end_address in order. This gives us a constraint
245 * that any page's byte should be equal or less than the previous pages
246 * byte (mod 256); and they should all be equal except for one transition
247 * at the point where we meet the incrementer. (We're running this with
248 * the guest stopped).
249 */
250 unsigned address;
251 uint8_t first_byte;
252 uint8_t last_byte;
253 bool hit_edge = false;
254 int bad = 0;
255
256 qtest_memread(who, start_address, &first_byte, 1);
257 last_byte = first_byte;
258
259 for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
260 address += TEST_MEM_PAGE_SIZE)
261 {
262 uint8_t b;
263 qtest_memread(who, address, &b, 1);
264 if (b != last_byte) {
265 if (((b + 1) % 256) == last_byte && !hit_edge) {
266 /* This is OK, the guest stopped at the point of
267 * incrementing the previous page but didn't get
268 * to us yet.
269 */
270 hit_edge = true;
271 last_byte = b;
272 } else {
273 bad++;
274 if (bad <= 10) {
275 fprintf(stderr, "Memory content inconsistency at %x"
276 " first_byte = %x last_byte = %x current = %x"
277 " hit_edge = %x\n",
278 address, first_byte, last_byte, b, hit_edge);
279 }
280 }
281 }
282 }
283 if (bad >= 10) {
284 fprintf(stderr, "and in another %d pages", bad - 10);
285 }
286 g_assert(bad == 0);
287 }
288
289 static void cleanup(const char *filename)
290 {
291 g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, filename);
292
293 unlink(path);
294 }
295
296 static char *SocketAddress_to_str(SocketAddress *addr)
297 {
298 switch (addr->type) {
299 case SOCKET_ADDRESS_TYPE_INET:
300 return g_strdup_printf("tcp:%s:%s",
301 addr->u.inet.host,
302 addr->u.inet.port);
303 case SOCKET_ADDRESS_TYPE_UNIX:
304 return g_strdup_printf("unix:%s",
305 addr->u.q_unix.path);
306 case SOCKET_ADDRESS_TYPE_FD:
307 return g_strdup_printf("fd:%s", addr->u.fd.str);
308 case SOCKET_ADDRESS_TYPE_VSOCK:
309 return g_strdup_printf("tcp:%s:%s",
310 addr->u.vsock.cid,
311 addr->u.vsock.port);
312 default:
313 return g_strdup("unknown address type");
314 }
315 }
316
317 static char *migrate_get_socket_address(QTestState *who, const char *parameter)
318 {
319 QDict *rsp;
320 char *result;
321 SocketAddressList *addrs;
322 Visitor *iv = NULL;
323 QObject *object;
324
325 rsp = migrate_query(who);
326 object = qdict_get(rsp, parameter);
327
328 iv = qobject_input_visitor_new(object);
329 visit_type_SocketAddressList(iv, NULL, &addrs, &error_abort);
330 visit_free(iv);
331
332 /* we are only using a single address */
333 result = SocketAddress_to_str(addrs->value);
334
335 qapi_free_SocketAddressList(addrs);
336 qobject_unref(rsp);
337 return result;
338 }
339
340 static long long migrate_get_parameter_int(QTestState *who,
341 const char *parameter)
342 {
343 QDict *rsp;
344 long long result;
345
346 rsp = qtest_qmp_assert_success_ref(
347 who, "{ 'execute': 'query-migrate-parameters' }");
348 result = qdict_get_int(rsp, parameter);
349 qobject_unref(rsp);
350 return result;
351 }
352
353 static void migrate_check_parameter_int(QTestState *who, const char *parameter,
354 long long value)
355 {
356 long long result;
357
358 result = migrate_get_parameter_int(who, parameter);
359 g_assert_cmpint(result, ==, value);
360 }
361
362 static void migrate_set_parameter_int(QTestState *who, const char *parameter,
363 long long value)
364 {
365 qtest_qmp_assert_success(who,
366 "{ 'execute': 'migrate-set-parameters',"
367 "'arguments': { %s: %lld } }",
368 parameter, value);
369 migrate_check_parameter_int(who, parameter, value);
370 }
371
372 static char *migrate_get_parameter_str(QTestState *who,
373 const char *parameter)
374 {
375 QDict *rsp;
376 char *result;
377
378 rsp = qtest_qmp_assert_success_ref(
379 who, "{ 'execute': 'query-migrate-parameters' }");
380 result = g_strdup(qdict_get_str(rsp, parameter));
381 qobject_unref(rsp);
382 return result;
383 }
384
385 static void migrate_check_parameter_str(QTestState *who, const char *parameter,
386 const char *value)
387 {
388 g_autofree char *result = migrate_get_parameter_str(who, parameter);
389 g_assert_cmpstr(result, ==, value);
390 }
391
392 static void migrate_set_parameter_str(QTestState *who, const char *parameter,
393 const char *value)
394 {
395 qtest_qmp_assert_success(who,
396 "{ 'execute': 'migrate-set-parameters',"
397 "'arguments': { %s: %s } }",
398 parameter, value);
399 migrate_check_parameter_str(who, parameter, value);
400 }
401
402 static long long migrate_get_parameter_bool(QTestState *who,
403 const char *parameter)
404 {
405 QDict *rsp;
406 int result;
407
408 rsp = qtest_qmp_assert_success_ref(
409 who, "{ 'execute': 'query-migrate-parameters' }");
410 result = qdict_get_bool(rsp, parameter);
411 qobject_unref(rsp);
412 return !!result;
413 }
414
415 static void migrate_check_parameter_bool(QTestState *who, const char *parameter,
416 int value)
417 {
418 int result;
419
420 result = migrate_get_parameter_bool(who, parameter);
421 g_assert_cmpint(result, ==, value);
422 }
423
424 static void migrate_set_parameter_bool(QTestState *who, const char *parameter,
425 int value)
426 {
427 qtest_qmp_assert_success(who,
428 "{ 'execute': 'migrate-set-parameters',"
429 "'arguments': { %s: %i } }",
430 parameter, value);
431 migrate_check_parameter_bool(who, parameter, value);
432 }
433
434 static void migrate_ensure_non_converge(QTestState *who)
435 {
436 /* Can't converge with 1ms downtime + 3 mbs bandwidth limit */
437 migrate_set_parameter_int(who, "max-bandwidth", 3 * 1000 * 1000);
438 migrate_set_parameter_int(who, "downtime-limit", 1);
439 }
440
441 static void migrate_ensure_converge(QTestState *who)
442 {
443 /* Should converge with 30s downtime + 1 gbs bandwidth limit */
444 migrate_set_parameter_int(who, "max-bandwidth", 1 * 1000 * 1000 * 1000);
445 migrate_set_parameter_int(who, "downtime-limit", 30 * 1000);
446 }
447
448 static void migrate_pause(QTestState *who)
449 {
450 qtest_qmp_assert_success(who, "{ 'execute': 'migrate-pause' }");
451 }
452
453 static void migrate_continue(QTestState *who, const char *state)
454 {
455 qtest_qmp_assert_success(who,
456 "{ 'execute': 'migrate-continue',"
457 " 'arguments': { 'state': %s } }",
458 state);
459 }
460
461 static void migrate_recover(QTestState *who, const char *uri)
462 {
463 qtest_qmp_assert_success(who,
464 "{ 'execute': 'migrate-recover', "
465 " 'id': 'recover-cmd', "
466 " 'arguments': { 'uri': %s } }",
467 uri);
468 }
469
470 static void migrate_cancel(QTestState *who)
471 {
472 qtest_qmp_assert_success(who, "{ 'execute': 'migrate_cancel' }");
473 }
474
475 static void migrate_set_capability(QTestState *who, const char *capability,
476 bool value)
477 {
478 qtest_qmp_assert_success(who,
479 "{ 'execute': 'migrate-set-capabilities',"
480 "'arguments': { "
481 "'capabilities': [ { "
482 "'capability': %s, 'state': %i } ] } }",
483 capability, value);
484 }
485
486 static void migrate_postcopy_start(QTestState *from, QTestState *to)
487 {
488 qtest_qmp_assert_success(from, "{ 'execute': 'migrate-start-postcopy' }");
489
490 if (!got_src_stop) {
491 qtest_qmp_eventwait(from, "STOP");
492 }
493
494 qtest_qmp_eventwait(to, "RESUME");
495 }
496
497 typedef struct {
498 /*
499 * QTEST_LOG=1 may override this. When QTEST_LOG=1, we always dump errors
500 * unconditionally, because it means the user would like to be verbose.
501 */
502 bool hide_stderr;
503 bool use_shmem;
504 /* only launch the target process */
505 bool only_target;
506 /* Use dirty ring if true; dirty logging otherwise */
507 bool use_dirty_ring;
508 const char *opts_source;
509 const char *opts_target;
510 } MigrateStart;
511
512 /*
513 * A hook that runs after the src and dst QEMUs have been
514 * created, but before the migration is started. This can
515 * be used to set migration parameters and capabilities.
516 *
517 * Returns: NULL, or a pointer to opaque state to be
518 * later passed to the TestMigrateFinishHook
519 */
520 typedef void * (*TestMigrateStartHook)(QTestState *from,
521 QTestState *to);
522
523 /*
524 * A hook that runs after the migration has finished,
525 * regardless of whether it succeeded or failed, but
526 * before QEMU has terminated (unless it self-terminated
527 * due to migration error)
528 *
529 * @opaque is a pointer to state previously returned
530 * by the TestMigrateStartHook if any, or NULL.
531 */
532 typedef void (*TestMigrateFinishHook)(QTestState *from,
533 QTestState *to,
534 void *opaque);
535
536 typedef struct {
537 /* Optional: fine tune start parameters */
538 MigrateStart start;
539
540 /* Required: the URI for the dst QEMU to listen on */
541 const char *listen_uri;
542
543 /*
544 * Optional: the URI for the src QEMU to connect to
545 * If NULL, then it will query the dst QEMU for its actual
546 * listening address and use that as the connect address.
547 * This allows for dynamically picking a free TCP port.
548 */
549 const char *connect_uri;
550
551 /* Optional: callback to run at start to set migration parameters */
552 TestMigrateStartHook start_hook;
553 /* Optional: callback to run at finish to cleanup */
554 TestMigrateFinishHook finish_hook;
555
556 /*
557 * Optional: normally we expect the migration process to complete.
558 *
559 * There can be a variety of reasons and stages in which failure
560 * can happen during tests.
561 *
562 * If a failure is expected to happen at time of establishing
563 * the connection, then MIG_TEST_FAIL will indicate that the dst
564 * QEMU is expected to stay running and accept future migration
565 * connections.
566 *
567 * If a failure is expected to happen while processing the
568 * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
569 * that the dst QEMU is expected to quit with non-zero exit status
570 */
571 enum {
572 /* This test should succeed, the default */
573 MIG_TEST_SUCCEED = 0,
574 /* This test should fail, dest qemu should keep alive */
575 MIG_TEST_FAIL,
576 /* This test should fail, dest qemu should fail with abnormal status */
577 MIG_TEST_FAIL_DEST_QUIT_ERR,
578 } result;
579
580 /* Optional: set number of migration passes to wait for */
581 unsigned int iterations;
582
583 /* Postcopy specific fields */
584 void *postcopy_data;
585 bool postcopy_preempt;
586 } MigrateCommon;
587
588 static int test_migrate_start(QTestState **from, QTestState **to,
589 const char *uri, MigrateStart *args)
590 {
591 g_autofree gchar *arch_source = NULL;
592 g_autofree gchar *arch_target = NULL;
593 g_autofree gchar *cmd_source = NULL;
594 g_autofree gchar *cmd_target = NULL;
595 const gchar *ignore_stderr;
596 g_autofree char *bootpath = NULL;
597 g_autofree char *shmem_opts = NULL;
598 g_autofree char *shmem_path = NULL;
599 const char *arch = qtest_get_arch();
600 const char *machine_opts = NULL;
601 const char *memory_size;
602
603 if (args->use_shmem) {
604 if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
605 g_test_skip("/dev/shm is not supported");
606 return -1;
607 }
608 }
609
610 got_src_stop = false;
611 got_dst_resume = false;
612 bootpath = g_strdup_printf("%s/bootsect", tmpfs);
613 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
614 /* the assembled x86 boot sector should be exactly one sector large */
615 assert(sizeof(x86_bootsect) == 512);
616 init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
617 memory_size = "150M";
618 arch_source = g_strdup_printf("-drive file=%s,format=raw", bootpath);
619 arch_target = g_strdup(arch_source);
620 start_address = X86_TEST_MEM_START;
621 end_address = X86_TEST_MEM_END;
622 } else if (g_str_equal(arch, "s390x")) {
623 init_bootfile(bootpath, s390x_elf, sizeof(s390x_elf));
624 memory_size = "128M";
625 arch_source = g_strdup_printf("-bios %s", bootpath);
626 arch_target = g_strdup(arch_source);
627 start_address = S390_TEST_MEM_START;
628 end_address = S390_TEST_MEM_END;
629 } else if (strcmp(arch, "ppc64") == 0) {
630 machine_opts = "vsmt=8";
631 memory_size = "256M";
632 start_address = PPC_TEST_MEM_START;
633 end_address = PPC_TEST_MEM_END;
634 arch_source = g_strdup_printf("-nodefaults "
635 "-prom-env 'use-nvramrc?=true' -prom-env "
636 "'nvramrc=hex .\" _\" begin %x %x "
637 "do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
638 "until'", end_address, start_address);
639 arch_target = g_strdup("");
640 } else if (strcmp(arch, "aarch64") == 0) {
641 init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel));
642 machine_opts = "virt,gic-version=max";
643 memory_size = "150M";
644 arch_source = g_strdup_printf("-cpu max "
645 "-kernel %s",
646 bootpath);
647 arch_target = g_strdup(arch_source);
648 start_address = ARM_TEST_MEM_START;
649 end_address = ARM_TEST_MEM_END;
650
651 g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
652 } else {
653 g_assert_not_reached();
654 }
655
656 if (!getenv("QTEST_LOG") && args->hide_stderr) {
657 #ifndef _WIN32
658 ignore_stderr = "2>/dev/null";
659 #else
660 /*
661 * On Windows the QEMU executable is created via CreateProcess() and
662 * IO redirection does not work, so don't bother adding IO redirection
663 * to the command line.
664 */
665 ignore_stderr = "";
666 #endif
667 } else {
668 ignore_stderr = "";
669 }
670
671 if (args->use_shmem) {
672 shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
673 shmem_opts = g_strdup_printf(
674 "-object memory-backend-file,id=mem0,size=%s"
675 ",mem-path=%s,share=on -numa node,memdev=mem0",
676 memory_size, shmem_path);
677 } else {
678 shmem_path = NULL;
679 shmem_opts = g_strdup("");
680 }
681
682 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
683 "-name source,debug-threads=on "
684 "-m %s "
685 "-serial file:%s/src_serial "
686 "%s %s %s %s",
687 args->use_dirty_ring ?
688 ",dirty-ring-size=4096" : "",
689 machine_opts ? " -machine " : "",
690 machine_opts ? machine_opts : "",
691 memory_size, tmpfs,
692 arch_source, shmem_opts,
693 args->opts_source ? args->opts_source : "",
694 ignore_stderr);
695 if (!args->only_target) {
696 *from = qtest_init(cmd_source);
697 qtest_qmp_set_event_callback(*from,
698 migrate_watch_for_stop,
699 &got_src_stop);
700 }
701
702 cmd_target = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
703 "-name target,debug-threads=on "
704 "-m %s "
705 "-serial file:%s/dest_serial "
706 "-incoming %s "
707 "%s %s %s %s",
708 args->use_dirty_ring ?
709 ",dirty-ring-size=4096" : "",
710 machine_opts ? " -machine " : "",
711 machine_opts ? machine_opts : "",
712 memory_size, tmpfs, uri,
713 arch_target, shmem_opts,
714 args->opts_target ? args->opts_target : "",
715 ignore_stderr);
716 *to = qtest_init(cmd_target);
717 qtest_qmp_set_event_callback(*to,
718 migrate_watch_for_resume,
719 &got_dst_resume);
720
721 /*
722 * Remove shmem file immediately to avoid memory leak in test failed case.
723 * It's valid becase QEMU has already opened this file
724 */
725 if (args->use_shmem) {
726 unlink(shmem_path);
727 }
728
729 return 0;
730 }
731
732 static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
733 {
734 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
735
736 qtest_quit(from);
737
738 if (test_dest) {
739 qtest_memread(to, start_address, &dest_byte_a, 1);
740
741 /* Destination still running, wait for a byte to change */
742 do {
743 qtest_memread(to, start_address, &dest_byte_b, 1);
744 usleep(1000 * 10);
745 } while (dest_byte_a == dest_byte_b);
746
747 qtest_qmp_assert_success(to, "{ 'execute' : 'stop'}");
748
749 /* With it stopped, check nothing changes */
750 qtest_memread(to, start_address, &dest_byte_c, 1);
751 usleep(1000 * 200);
752 qtest_memread(to, start_address, &dest_byte_d, 1);
753 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
754
755 check_guests_ram(to);
756 }
757
758 qtest_quit(to);
759
760 cleanup("bootsect");
761 cleanup("migsocket");
762 cleanup("src_serial");
763 cleanup("dest_serial");
764 }
765
766 #ifdef CONFIG_GNUTLS
767 struct TestMigrateTLSPSKData {
768 char *workdir;
769 char *workdiralt;
770 char *pskfile;
771 char *pskfilealt;
772 };
773
774 static void *
775 test_migrate_tls_psk_start_common(QTestState *from,
776 QTestState *to,
777 bool mismatch)
778 {
779 struct TestMigrateTLSPSKData *data =
780 g_new0(struct TestMigrateTLSPSKData, 1);
781
782 data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs);
783 data->pskfile = g_strdup_printf("%s/%s", data->workdir,
784 QCRYPTO_TLS_CREDS_PSKFILE);
785 g_mkdir_with_parents(data->workdir, 0700);
786 test_tls_psk_init(data->pskfile);
787
788 if (mismatch) {
789 data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs);
790 data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt,
791 QCRYPTO_TLS_CREDS_PSKFILE);
792 g_mkdir_with_parents(data->workdiralt, 0700);
793 test_tls_psk_init_alt(data->pskfilealt);
794 }
795
796 qtest_qmp_assert_success(from,
797 "{ 'execute': 'object-add',"
798 " 'arguments': { 'qom-type': 'tls-creds-psk',"
799 " 'id': 'tlscredspsk0',"
800 " 'endpoint': 'client',"
801 " 'dir': %s,"
802 " 'username': 'qemu'} }",
803 data->workdir);
804
805 qtest_qmp_assert_success(to,
806 "{ 'execute': 'object-add',"
807 " 'arguments': { 'qom-type': 'tls-creds-psk',"
808 " 'id': 'tlscredspsk0',"
809 " 'endpoint': 'server',"
810 " 'dir': %s } }",
811 mismatch ? data->workdiralt : data->workdir);
812
813 migrate_set_parameter_str(from, "tls-creds", "tlscredspsk0");
814 migrate_set_parameter_str(to, "tls-creds", "tlscredspsk0");
815
816 return data;
817 }
818
819 static void *
820 test_migrate_tls_psk_start_match(QTestState *from,
821 QTestState *to)
822 {
823 return test_migrate_tls_psk_start_common(from, to, false);
824 }
825
826 static void *
827 test_migrate_tls_psk_start_mismatch(QTestState *from,
828 QTestState *to)
829 {
830 return test_migrate_tls_psk_start_common(from, to, true);
831 }
832
833 static void
834 test_migrate_tls_psk_finish(QTestState *from,
835 QTestState *to,
836 void *opaque)
837 {
838 struct TestMigrateTLSPSKData *data = opaque;
839
840 test_tls_psk_cleanup(data->pskfile);
841 if (data->pskfilealt) {
842 test_tls_psk_cleanup(data->pskfilealt);
843 }
844 rmdir(data->workdir);
845 if (data->workdiralt) {
846 rmdir(data->workdiralt);
847 }
848
849 g_free(data->workdiralt);
850 g_free(data->pskfilealt);
851 g_free(data->workdir);
852 g_free(data->pskfile);
853 g_free(data);
854 }
855
856 #ifdef CONFIG_TASN1
857 typedef struct {
858 char *workdir;
859 char *keyfile;
860 char *cacert;
861 char *servercert;
862 char *serverkey;
863 char *clientcert;
864 char *clientkey;
865 } TestMigrateTLSX509Data;
866
867 typedef struct {
868 bool verifyclient;
869 bool clientcert;
870 bool hostileclient;
871 bool authzclient;
872 const char *certhostname;
873 const char *certipaddr;
874 } TestMigrateTLSX509;
875
876 static void *
877 test_migrate_tls_x509_start_common(QTestState *from,
878 QTestState *to,
879 TestMigrateTLSX509 *args)
880 {
881 TestMigrateTLSX509Data *data = g_new0(TestMigrateTLSX509Data, 1);
882
883 data->workdir = g_strdup_printf("%s/tlscredsx5090", tmpfs);
884 data->keyfile = g_strdup_printf("%s/key.pem", data->workdir);
885
886 data->cacert = g_strdup_printf("%s/ca-cert.pem", data->workdir);
887 data->serverkey = g_strdup_printf("%s/server-key.pem", data->workdir);
888 data->servercert = g_strdup_printf("%s/server-cert.pem", data->workdir);
889 if (args->clientcert) {
890 data->clientkey = g_strdup_printf("%s/client-key.pem", data->workdir);
891 data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir);
892 }
893
894 g_mkdir_with_parents(data->workdir, 0700);
895
896 test_tls_init(data->keyfile);
897 #ifndef _WIN32
898 g_assert(link(data->keyfile, data->serverkey) == 0);
899 #else
900 g_assert(CreateHardLink(data->serverkey, data->keyfile, NULL) != 0);
901 #endif
902 if (args->clientcert) {
903 #ifndef _WIN32
904 g_assert(link(data->keyfile, data->clientkey) == 0);
905 #else
906 g_assert(CreateHardLink(data->clientkey, data->keyfile, NULL) != 0);
907 #endif
908 }
909
910 TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert);
911 if (args->clientcert) {
912 TLS_CERT_REQ_SIMPLE_CLIENT(servercertreq, cacertreq,
913 args->hostileclient ?
914 QCRYPTO_TLS_TEST_CLIENT_HOSTILE_NAME :
915 QCRYPTO_TLS_TEST_CLIENT_NAME,
916 data->clientcert);
917 }
918
919 TLS_CERT_REQ_SIMPLE_SERVER(clientcertreq, cacertreq,
920 data->servercert,
921 args->certhostname,
922 args->certipaddr);
923
924 qtest_qmp_assert_success(from,
925 "{ 'execute': 'object-add',"
926 " 'arguments': { 'qom-type': 'tls-creds-x509',"
927 " 'id': 'tlscredsx509client0',"
928 " 'endpoint': 'client',"
929 " 'dir': %s,"
930 " 'sanity-check': true,"
931 " 'verify-peer': true} }",
932 data->workdir);
933 migrate_set_parameter_str(from, "tls-creds", "tlscredsx509client0");
934 if (args->certhostname) {
935 migrate_set_parameter_str(from, "tls-hostname", args->certhostname);
936 }
937
938 qtest_qmp_assert_success(to,
939 "{ 'execute': 'object-add',"
940 " 'arguments': { 'qom-type': 'tls-creds-x509',"
941 " 'id': 'tlscredsx509server0',"
942 " 'endpoint': 'server',"
943 " 'dir': %s,"
944 " 'sanity-check': true,"
945 " 'verify-peer': %i} }",
946 data->workdir, args->verifyclient);
947 migrate_set_parameter_str(to, "tls-creds", "tlscredsx509server0");
948
949 if (args->authzclient) {
950 qtest_qmp_assert_success(to,
951 "{ 'execute': 'object-add',"
952 " 'arguments': { 'qom-type': 'authz-simple',"
953 " 'id': 'tlsauthz0',"
954 " 'identity': %s} }",
955 "CN=" QCRYPTO_TLS_TEST_CLIENT_NAME);
956 migrate_set_parameter_str(to, "tls-authz", "tlsauthz0");
957 }
958
959 return data;
960 }
961
962 /*
963 * The normal case: match server's cert hostname against
964 * whatever host we were telling QEMU to connect to (if any)
965 */
966 static void *
967 test_migrate_tls_x509_start_default_host(QTestState *from,
968 QTestState *to)
969 {
970 TestMigrateTLSX509 args = {
971 .verifyclient = true,
972 .clientcert = true,
973 .certipaddr = "127.0.0.1"
974 };
975 return test_migrate_tls_x509_start_common(from, to, &args);
976 }
977
978 /*
979 * The unusual case: the server's cert is different from
980 * the address we're telling QEMU to connect to (if any),
981 * so we must give QEMU an explicit hostname to validate
982 */
983 static void *
984 test_migrate_tls_x509_start_override_host(QTestState *from,
985 QTestState *to)
986 {
987 TestMigrateTLSX509 args = {
988 .verifyclient = true,
989 .clientcert = true,
990 .certhostname = "qemu.org",
991 };
992 return test_migrate_tls_x509_start_common(from, to, &args);
993 }
994
995 /*
996 * The unusual case: the server's cert is different from
997 * the address we're telling QEMU to connect to, and so we
998 * expect the client to reject the server
999 */
1000 static void *
1001 test_migrate_tls_x509_start_mismatch_host(QTestState *from,
1002 QTestState *to)
1003 {
1004 TestMigrateTLSX509 args = {
1005 .verifyclient = true,
1006 .clientcert = true,
1007 .certipaddr = "10.0.0.1",
1008 };
1009 return test_migrate_tls_x509_start_common(from, to, &args);
1010 }
1011
1012 static void *
1013 test_migrate_tls_x509_start_friendly_client(QTestState *from,
1014 QTestState *to)
1015 {
1016 TestMigrateTLSX509 args = {
1017 .verifyclient = true,
1018 .clientcert = true,
1019 .authzclient = true,
1020 .certipaddr = "127.0.0.1",
1021 };
1022 return test_migrate_tls_x509_start_common(from, to, &args);
1023 }
1024
1025 static void *
1026 test_migrate_tls_x509_start_hostile_client(QTestState *from,
1027 QTestState *to)
1028 {
1029 TestMigrateTLSX509 args = {
1030 .verifyclient = true,
1031 .clientcert = true,
1032 .hostileclient = true,
1033 .authzclient = true,
1034 .certipaddr = "127.0.0.1",
1035 };
1036 return test_migrate_tls_x509_start_common(from, to, &args);
1037 }
1038
1039 /*
1040 * The case with no client certificate presented,
1041 * and no server verification
1042 */
1043 static void *
1044 test_migrate_tls_x509_start_allow_anon_client(QTestState *from,
1045 QTestState *to)
1046 {
1047 TestMigrateTLSX509 args = {
1048 .certipaddr = "127.0.0.1",
1049 };
1050 return test_migrate_tls_x509_start_common(from, to, &args);
1051 }
1052
1053 /*
1054 * The case with no client certificate presented,
1055 * and server verification rejecting
1056 */
1057 static void *
1058 test_migrate_tls_x509_start_reject_anon_client(QTestState *from,
1059 QTestState *to)
1060 {
1061 TestMigrateTLSX509 args = {
1062 .verifyclient = true,
1063 .certipaddr = "127.0.0.1",
1064 };
1065 return test_migrate_tls_x509_start_common(from, to, &args);
1066 }
1067
1068 static void
1069 test_migrate_tls_x509_finish(QTestState *from,
1070 QTestState *to,
1071 void *opaque)
1072 {
1073 TestMigrateTLSX509Data *data = opaque;
1074
1075 test_tls_cleanup(data->keyfile);
1076 g_free(data->keyfile);
1077
1078 unlink(data->cacert);
1079 g_free(data->cacert);
1080 unlink(data->servercert);
1081 g_free(data->servercert);
1082 unlink(data->serverkey);
1083 g_free(data->serverkey);
1084
1085 if (data->clientcert) {
1086 unlink(data->clientcert);
1087 g_free(data->clientcert);
1088 }
1089 if (data->clientkey) {
1090 unlink(data->clientkey);
1091 g_free(data->clientkey);
1092 }
1093
1094 rmdir(data->workdir);
1095 g_free(data->workdir);
1096
1097 g_free(data);
1098 }
1099 #endif /* CONFIG_TASN1 */
1100 #endif /* CONFIG_GNUTLS */
1101
1102 static void *
1103 test_migrate_compress_start(QTestState *from,
1104 QTestState *to)
1105 {
1106 migrate_set_parameter_int(from, "compress-level", 1);
1107 migrate_set_parameter_int(from, "compress-threads", 4);
1108 migrate_set_parameter_bool(from, "compress-wait-thread", true);
1109 migrate_set_parameter_int(to, "decompress-threads", 4);
1110
1111 migrate_set_capability(from, "compress", true);
1112 migrate_set_capability(to, "compress", true);
1113
1114 return NULL;
1115 }
1116
1117 static void *
1118 test_migrate_compress_nowait_start(QTestState *from,
1119 QTestState *to)
1120 {
1121 migrate_set_parameter_int(from, "compress-level", 9);
1122 migrate_set_parameter_int(from, "compress-threads", 1);
1123 migrate_set_parameter_bool(from, "compress-wait-thread", false);
1124 migrate_set_parameter_int(to, "decompress-threads", 1);
1125
1126 migrate_set_capability(from, "compress", true);
1127 migrate_set_capability(to, "compress", true);
1128
1129 return NULL;
1130 }
1131
1132 static int migrate_postcopy_prepare(QTestState **from_ptr,
1133 QTestState **to_ptr,
1134 MigrateCommon *args)
1135 {
1136 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1137 QTestState *from, *to;
1138
1139 if (test_migrate_start(&from, &to, uri, &args->start)) {
1140 return -1;
1141 }
1142
1143 if (args->start_hook) {
1144 args->postcopy_data = args->start_hook(from, to);
1145 }
1146
1147 migrate_set_capability(from, "postcopy-ram", true);
1148 migrate_set_capability(to, "postcopy-ram", true);
1149 migrate_set_capability(to, "postcopy-blocktime", true);
1150
1151 if (args->postcopy_preempt) {
1152 migrate_set_capability(from, "postcopy-preempt", true);
1153 migrate_set_capability(to, "postcopy-preempt", true);
1154 }
1155
1156 migrate_ensure_non_converge(from);
1157
1158 /* Wait for the first serial output from the source */
1159 wait_for_serial("src_serial");
1160
1161 migrate_qmp(from, uri, "{}");
1162
1163 wait_for_migration_pass(from);
1164
1165 *from_ptr = from;
1166 *to_ptr = to;
1167
1168 return 0;
1169 }
1170
1171 static void migrate_postcopy_complete(QTestState *from, QTestState *to,
1172 MigrateCommon *args)
1173 {
1174 wait_for_migration_complete(from);
1175
1176 /* Make sure we get at least one "B" on destination */
1177 wait_for_serial("dest_serial");
1178
1179 if (uffd_feature_thread_id) {
1180 read_blocktime(to);
1181 }
1182
1183 if (args->finish_hook) {
1184 args->finish_hook(from, to, args->postcopy_data);
1185 args->postcopy_data = NULL;
1186 }
1187
1188 test_migrate_end(from, to, true);
1189 }
1190
1191 static void test_postcopy_common(MigrateCommon *args)
1192 {
1193 QTestState *from, *to;
1194
1195 if (migrate_postcopy_prepare(&from, &to, args)) {
1196 return;
1197 }
1198 migrate_postcopy_start(from, to);
1199 migrate_postcopy_complete(from, to, args);
1200 }
1201
1202 static void test_postcopy(void)
1203 {
1204 MigrateCommon args = { };
1205
1206 test_postcopy_common(&args);
1207 }
1208
1209 static void test_postcopy_compress(void)
1210 {
1211 MigrateCommon args = {
1212 .start_hook = test_migrate_compress_start
1213 };
1214
1215 test_postcopy_common(&args);
1216 }
1217
1218 static void test_postcopy_preempt(void)
1219 {
1220 MigrateCommon args = {
1221 .postcopy_preempt = true,
1222 };
1223
1224 test_postcopy_common(&args);
1225 }
1226
1227 #ifdef CONFIG_GNUTLS
1228 static void test_postcopy_tls_psk(void)
1229 {
1230 MigrateCommon args = {
1231 .start_hook = test_migrate_tls_psk_start_match,
1232 .finish_hook = test_migrate_tls_psk_finish,
1233 };
1234
1235 test_postcopy_common(&args);
1236 }
1237
1238 static void test_postcopy_preempt_tls_psk(void)
1239 {
1240 MigrateCommon args = {
1241 .postcopy_preempt = true,
1242 .start_hook = test_migrate_tls_psk_start_match,
1243 .finish_hook = test_migrate_tls_psk_finish,
1244 };
1245
1246 test_postcopy_common(&args);
1247 }
1248 #endif
1249
1250 static void test_postcopy_recovery_common(MigrateCommon *args)
1251 {
1252 QTestState *from, *to;
1253 g_autofree char *uri = NULL;
1254
1255 /* Always hide errors for postcopy recover tests since they're expected */
1256 args->start.hide_stderr = true;
1257
1258 if (migrate_postcopy_prepare(&from, &to, args)) {
1259 return;
1260 }
1261
1262 /* Turn postcopy speed down, 4K/s is slow enough on any machines */
1263 migrate_set_parameter_int(from, "max-postcopy-bandwidth", 4096);
1264
1265 /* Now we start the postcopy */
1266 migrate_postcopy_start(from, to);
1267
1268 /*
1269 * Wait until postcopy is really started; we can only run the
1270 * migrate-pause command during a postcopy
1271 */
1272 wait_for_migration_status(from, "postcopy-active", NULL);
1273
1274 /*
1275 * Manually stop the postcopy migration. This emulates a network
1276 * failure with the migration socket
1277 */
1278 migrate_pause(from);
1279
1280 /*
1281 * Wait for destination side to reach postcopy-paused state. The
1282 * migrate-recover command can only succeed if destination machine
1283 * is in the paused state
1284 */
1285 wait_for_migration_status(to, "postcopy-paused",
1286 (const char * []) { "failed", "active",
1287 "completed", NULL });
1288
1289 /*
1290 * Create a new socket to emulate a new channel that is different
1291 * from the broken migration channel; tell the destination to
1292 * listen to the new port
1293 */
1294 uri = g_strdup_printf("unix:%s/migsocket-recover", tmpfs);
1295 migrate_recover(to, uri);
1296
1297 /*
1298 * Try to rebuild the migration channel using the resume flag and
1299 * the newly created channel
1300 */
1301 wait_for_migration_status(from, "postcopy-paused",
1302 (const char * []) { "failed", "active",
1303 "completed", NULL });
1304 migrate_qmp(from, uri, "{'resume': true}");
1305
1306 /* Restore the postcopy bandwidth to unlimited */
1307 migrate_set_parameter_int(from, "max-postcopy-bandwidth", 0);
1308
1309 migrate_postcopy_complete(from, to, args);
1310 }
1311
1312 static void test_postcopy_recovery(void)
1313 {
1314 MigrateCommon args = { };
1315
1316 test_postcopy_recovery_common(&args);
1317 }
1318
1319 static void test_postcopy_recovery_compress(void)
1320 {
1321 MigrateCommon args = {
1322 .start_hook = test_migrate_compress_start
1323 };
1324
1325 test_postcopy_recovery_common(&args);
1326 }
1327
1328 #ifdef CONFIG_GNUTLS
1329 static void test_postcopy_recovery_tls_psk(void)
1330 {
1331 MigrateCommon args = {
1332 .start_hook = test_migrate_tls_psk_start_match,
1333 .finish_hook = test_migrate_tls_psk_finish,
1334 };
1335
1336 test_postcopy_recovery_common(&args);
1337 }
1338 #endif
1339
1340 static void test_postcopy_preempt_recovery(void)
1341 {
1342 MigrateCommon args = {
1343 .postcopy_preempt = true,
1344 };
1345
1346 test_postcopy_recovery_common(&args);
1347 }
1348
1349 #ifdef CONFIG_GNUTLS
1350 /* This contains preempt+recovery+tls test altogether */
1351 static void test_postcopy_preempt_all(void)
1352 {
1353 MigrateCommon args = {
1354 .postcopy_preempt = true,
1355 .start_hook = test_migrate_tls_psk_start_match,
1356 .finish_hook = test_migrate_tls_psk_finish,
1357 };
1358
1359 test_postcopy_recovery_common(&args);
1360 }
1361
1362 #endif
1363
1364 static void test_baddest(void)
1365 {
1366 MigrateStart args = {
1367 .hide_stderr = true
1368 };
1369 QTestState *from, *to;
1370
1371 if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
1372 return;
1373 }
1374 migrate_qmp(from, "tcp:127.0.0.1:0", "{}");
1375 wait_for_migration_fail(from, false);
1376 test_migrate_end(from, to, false);
1377 }
1378
1379 static void test_precopy_common(MigrateCommon *args)
1380 {
1381 QTestState *from, *to;
1382 void *data_hook = NULL;
1383
1384 if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
1385 return;
1386 }
1387
1388 migrate_ensure_non_converge(from);
1389
1390 if (args->start_hook) {
1391 data_hook = args->start_hook(from, to);
1392 }
1393
1394 /* Wait for the first serial output from the source */
1395 if (args->result == MIG_TEST_SUCCEED) {
1396 wait_for_serial("src_serial");
1397 }
1398
1399 if (!args->connect_uri) {
1400 g_autofree char *local_connect_uri =
1401 migrate_get_socket_address(to, "socket-address");
1402 migrate_qmp(from, local_connect_uri, "{}");
1403 } else {
1404 migrate_qmp(from, args->connect_uri, "{}");
1405 }
1406
1407
1408 if (args->result != MIG_TEST_SUCCEED) {
1409 bool allow_active = args->result == MIG_TEST_FAIL;
1410 wait_for_migration_fail(from, allow_active);
1411
1412 if (args->result == MIG_TEST_FAIL_DEST_QUIT_ERR) {
1413 qtest_set_expected_status(to, EXIT_FAILURE);
1414 }
1415 } else {
1416 if (args->iterations) {
1417 while (args->iterations--) {
1418 wait_for_migration_pass(from);
1419 }
1420 } else {
1421 wait_for_migration_pass(from);
1422 }
1423
1424 migrate_ensure_converge(from);
1425
1426 /* We do this first, as it has a timeout to stop us
1427 * hanging forever if migration didn't converge */
1428 wait_for_migration_complete(from);
1429
1430 if (!got_src_stop) {
1431 qtest_qmp_eventwait(from, "STOP");
1432 }
1433
1434 qtest_qmp_eventwait(to, "RESUME");
1435
1436 wait_for_serial("dest_serial");
1437 }
1438
1439 if (args->finish_hook) {
1440 args->finish_hook(from, to, data_hook);
1441 }
1442
1443 test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
1444 }
1445
1446 static void test_precopy_unix_plain(void)
1447 {
1448 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1449 MigrateCommon args = {
1450 .listen_uri = uri,
1451 .connect_uri = uri,
1452 };
1453
1454 test_precopy_common(&args);
1455 }
1456
1457
1458 static void test_precopy_unix_dirty_ring(void)
1459 {
1460 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1461 MigrateCommon args = {
1462 .start = {
1463 .use_dirty_ring = true,
1464 },
1465 .listen_uri = uri,
1466 .connect_uri = uri,
1467 };
1468
1469 test_precopy_common(&args);
1470 }
1471
1472 #ifdef CONFIG_GNUTLS
1473 static void test_precopy_unix_tls_psk(void)
1474 {
1475 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1476 MigrateCommon args = {
1477 .connect_uri = uri,
1478 .listen_uri = uri,
1479 .start_hook = test_migrate_tls_psk_start_match,
1480 .finish_hook = test_migrate_tls_psk_finish,
1481 };
1482
1483 test_precopy_common(&args);
1484 }
1485
1486 #ifdef CONFIG_TASN1
1487 static void test_precopy_unix_tls_x509_default_host(void)
1488 {
1489 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1490 MigrateCommon args = {
1491 .start = {
1492 .hide_stderr = true,
1493 },
1494 .connect_uri = uri,
1495 .listen_uri = uri,
1496 .start_hook = test_migrate_tls_x509_start_default_host,
1497 .finish_hook = test_migrate_tls_x509_finish,
1498 .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
1499 };
1500
1501 test_precopy_common(&args);
1502 }
1503
1504 static void test_precopy_unix_tls_x509_override_host(void)
1505 {
1506 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1507 MigrateCommon args = {
1508 .connect_uri = uri,
1509 .listen_uri = uri,
1510 .start_hook = test_migrate_tls_x509_start_override_host,
1511 .finish_hook = test_migrate_tls_x509_finish,
1512 };
1513
1514 test_precopy_common(&args);
1515 }
1516 #endif /* CONFIG_TASN1 */
1517 #endif /* CONFIG_GNUTLS */
1518
1519 #if 0
1520 /* Currently upset on aarch64 TCG */
1521 static void test_ignore_shared(void)
1522 {
1523 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1524 QTestState *from, *to;
1525
1526 if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) {
1527 return;
1528 }
1529
1530 migrate_set_capability(from, "x-ignore-shared", true);
1531 migrate_set_capability(to, "x-ignore-shared", true);
1532
1533 /* Wait for the first serial output from the source */
1534 wait_for_serial("src_serial");
1535
1536 migrate_qmp(from, uri, "{}");
1537
1538 wait_for_migration_pass(from);
1539
1540 if (!got_src_stop) {
1541 qtest_qmp_eventwait(from, "STOP");
1542 }
1543
1544 qtest_qmp_eventwait(to, "RESUME");
1545
1546 wait_for_serial("dest_serial");
1547 wait_for_migration_complete(from);
1548
1549 /* Check whether shared RAM has been really skipped */
1550 g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 1024);
1551
1552 test_migrate_end(from, to, true);
1553 }
1554 #endif
1555
1556 static void *
1557 test_migrate_xbzrle_start(QTestState *from,
1558 QTestState *to)
1559 {
1560 migrate_set_parameter_int(from, "xbzrle-cache-size", 33554432);
1561
1562 migrate_set_capability(from, "xbzrle", true);
1563 migrate_set_capability(to, "xbzrle", true);
1564
1565 return NULL;
1566 }
1567
1568 static void test_precopy_unix_xbzrle(void)
1569 {
1570 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1571 MigrateCommon args = {
1572 .connect_uri = uri,
1573 .listen_uri = uri,
1574
1575 .start_hook = test_migrate_xbzrle_start,
1576
1577 .iterations = 2,
1578 };
1579
1580 test_precopy_common(&args);
1581 }
1582
1583 static void test_precopy_unix_compress(void)
1584 {
1585 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1586 MigrateCommon args = {
1587 .connect_uri = uri,
1588 .listen_uri = uri,
1589 .start_hook = test_migrate_compress_start,
1590 /*
1591 * Test that no invalid thread state is left over from
1592 * the previous iteration.
1593 */
1594 .iterations = 2,
1595 };
1596
1597 test_precopy_common(&args);
1598 }
1599
1600 static void test_precopy_unix_compress_nowait(void)
1601 {
1602 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1603 MigrateCommon args = {
1604 .connect_uri = uri,
1605 .listen_uri = uri,
1606 .start_hook = test_migrate_compress_nowait_start,
1607 /*
1608 * Test that no invalid thread state is left over from
1609 * the previous iteration.
1610 */
1611 .iterations = 2,
1612 };
1613
1614 test_precopy_common(&args);
1615 }
1616
1617 static void test_precopy_tcp_plain(void)
1618 {
1619 MigrateCommon args = {
1620 .listen_uri = "tcp:127.0.0.1:0",
1621 };
1622
1623 test_precopy_common(&args);
1624 }
1625
1626 #ifdef CONFIG_GNUTLS
1627 static void test_precopy_tcp_tls_psk_match(void)
1628 {
1629 MigrateCommon args = {
1630 .listen_uri = "tcp:127.0.0.1:0",
1631 .start_hook = test_migrate_tls_psk_start_match,
1632 .finish_hook = test_migrate_tls_psk_finish,
1633 };
1634
1635 test_precopy_common(&args);
1636 }
1637
1638 static void test_precopy_tcp_tls_psk_mismatch(void)
1639 {
1640 MigrateCommon args = {
1641 .start = {
1642 .hide_stderr = true,
1643 },
1644 .listen_uri = "tcp:127.0.0.1:0",
1645 .start_hook = test_migrate_tls_psk_start_mismatch,
1646 .finish_hook = test_migrate_tls_psk_finish,
1647 .result = MIG_TEST_FAIL,
1648 };
1649
1650 test_precopy_common(&args);
1651 }
1652
1653 #ifdef CONFIG_TASN1
1654 static void test_precopy_tcp_tls_x509_default_host(void)
1655 {
1656 MigrateCommon args = {
1657 .listen_uri = "tcp:127.0.0.1:0",
1658 .start_hook = test_migrate_tls_x509_start_default_host,
1659 .finish_hook = test_migrate_tls_x509_finish,
1660 };
1661
1662 test_precopy_common(&args);
1663 }
1664
1665 static void test_precopy_tcp_tls_x509_override_host(void)
1666 {
1667 MigrateCommon args = {
1668 .listen_uri = "tcp:127.0.0.1:0",
1669 .start_hook = test_migrate_tls_x509_start_override_host,
1670 .finish_hook = test_migrate_tls_x509_finish,
1671 };
1672
1673 test_precopy_common(&args);
1674 }
1675
1676 static void test_precopy_tcp_tls_x509_mismatch_host(void)
1677 {
1678 MigrateCommon args = {
1679 .start = {
1680 .hide_stderr = true,
1681 },
1682 .listen_uri = "tcp:127.0.0.1:0",
1683 .start_hook = test_migrate_tls_x509_start_mismatch_host,
1684 .finish_hook = test_migrate_tls_x509_finish,
1685 .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
1686 };
1687
1688 test_precopy_common(&args);
1689 }
1690
1691 static void test_precopy_tcp_tls_x509_friendly_client(void)
1692 {
1693 MigrateCommon args = {
1694 .listen_uri = "tcp:127.0.0.1:0",
1695 .start_hook = test_migrate_tls_x509_start_friendly_client,
1696 .finish_hook = test_migrate_tls_x509_finish,
1697 };
1698
1699 test_precopy_common(&args);
1700 }
1701
1702 static void test_precopy_tcp_tls_x509_hostile_client(void)
1703 {
1704 MigrateCommon args = {
1705 .start = {
1706 .hide_stderr = true,
1707 },
1708 .listen_uri = "tcp:127.0.0.1:0",
1709 .start_hook = test_migrate_tls_x509_start_hostile_client,
1710 .finish_hook = test_migrate_tls_x509_finish,
1711 .result = MIG_TEST_FAIL,
1712 };
1713
1714 test_precopy_common(&args);
1715 }
1716
1717 static void test_precopy_tcp_tls_x509_allow_anon_client(void)
1718 {
1719 MigrateCommon args = {
1720 .listen_uri = "tcp:127.0.0.1:0",
1721 .start_hook = test_migrate_tls_x509_start_allow_anon_client,
1722 .finish_hook = test_migrate_tls_x509_finish,
1723 };
1724
1725 test_precopy_common(&args);
1726 }
1727
1728 static void test_precopy_tcp_tls_x509_reject_anon_client(void)
1729 {
1730 MigrateCommon args = {
1731 .start = {
1732 .hide_stderr = true,
1733 },
1734 .listen_uri = "tcp:127.0.0.1:0",
1735 .start_hook = test_migrate_tls_x509_start_reject_anon_client,
1736 .finish_hook = test_migrate_tls_x509_finish,
1737 .result = MIG_TEST_FAIL,
1738 };
1739
1740 test_precopy_common(&args);
1741 }
1742 #endif /* CONFIG_TASN1 */
1743 #endif /* CONFIG_GNUTLS */
1744
1745 #ifndef _WIN32
1746 static void *test_migrate_fd_start_hook(QTestState *from,
1747 QTestState *to)
1748 {
1749 int ret;
1750 int pair[2];
1751
1752 /* Create two connected sockets for migration */
1753 ret = qemu_socketpair(PF_LOCAL, SOCK_STREAM, 0, pair);
1754 g_assert_cmpint(ret, ==, 0);
1755
1756 /* Send the 1st socket to the target */
1757 qtest_qmp_fds_assert_success(to, &pair[0], 1,
1758 "{ 'execute': 'getfd',"
1759 " 'arguments': { 'fdname': 'fd-mig' }}");
1760 close(pair[0]);
1761
1762 /* Start incoming migration from the 1st socket */
1763 qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming',"
1764 " 'arguments': { 'uri': 'fd:fd-mig' }}");
1765
1766 /* Send the 2nd socket to the target */
1767 qtest_qmp_fds_assert_success(from, &pair[1], 1,
1768 "{ 'execute': 'getfd',"
1769 " 'arguments': { 'fdname': 'fd-mig' }}");
1770 close(pair[1]);
1771
1772 return NULL;
1773 }
1774
1775 static void test_migrate_fd_finish_hook(QTestState *from,
1776 QTestState *to,
1777 void *opaque)
1778 {
1779 QDict *rsp;
1780 const char *error_desc;
1781
1782 /* Test closing fds */
1783 /* We assume, that QEMU removes named fd from its list,
1784 * so this should fail */
1785 rsp = qtest_qmp(from, "{ 'execute': 'closefd',"
1786 " 'arguments': { 'fdname': 'fd-mig' }}");
1787 g_assert_true(qdict_haskey(rsp, "error"));
1788 error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
1789 g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
1790 qobject_unref(rsp);
1791
1792 rsp = qtest_qmp(to, "{ 'execute': 'closefd',"
1793 " 'arguments': { 'fdname': 'fd-mig' }}");
1794 g_assert_true(qdict_haskey(rsp, "error"));
1795 error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc");
1796 g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found");
1797 qobject_unref(rsp);
1798 }
1799
1800 static void test_migrate_fd_proto(void)
1801 {
1802 MigrateCommon args = {
1803 .listen_uri = "defer",
1804 .connect_uri = "fd:fd-mig",
1805 .start_hook = test_migrate_fd_start_hook,
1806 .finish_hook = test_migrate_fd_finish_hook
1807 };
1808 test_precopy_common(&args);
1809 }
1810 #endif /* _WIN32 */
1811
1812 static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
1813 {
1814 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1815 QTestState *from, *to;
1816
1817 if (test_migrate_start(&from, &to, uri, args)) {
1818 return;
1819 }
1820
1821 /*
1822 * UUID validation is at the begin of migration. So, the main process of
1823 * migration is not interesting for us here. Thus, set huge downtime for
1824 * very fast migration.
1825 */
1826 migrate_set_parameter_int(from, "downtime-limit", 1000000);
1827 migrate_set_capability(from, "validate-uuid", true);
1828
1829 /* Wait for the first serial output from the source */
1830 wait_for_serial("src_serial");
1831
1832 migrate_qmp(from, uri, "{}");
1833
1834 if (should_fail) {
1835 qtest_set_expected_status(to, EXIT_FAILURE);
1836 wait_for_migration_fail(from, true);
1837 } else {
1838 wait_for_migration_complete(from);
1839 }
1840
1841 test_migrate_end(from, to, false);
1842 }
1843
1844 static void test_validate_uuid(void)
1845 {
1846 MigrateStart args = {
1847 .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
1848 .opts_target = "-uuid 11111111-1111-1111-1111-111111111111",
1849 };
1850
1851 do_test_validate_uuid(&args, false);
1852 }
1853
1854 static void test_validate_uuid_error(void)
1855 {
1856 MigrateStart args = {
1857 .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
1858 .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
1859 .hide_stderr = true,
1860 };
1861
1862 do_test_validate_uuid(&args, true);
1863 }
1864
1865 static void test_validate_uuid_src_not_set(void)
1866 {
1867 MigrateStart args = {
1868 .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
1869 .hide_stderr = true,
1870 };
1871
1872 do_test_validate_uuid(&args, false);
1873 }
1874
1875 static void test_validate_uuid_dst_not_set(void)
1876 {
1877 MigrateStart args = {
1878 .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
1879 .hide_stderr = true,
1880 };
1881
1882 do_test_validate_uuid(&args, false);
1883 }
1884
1885 /*
1886 * The way auto_converge works, we need to do too many passes to
1887 * run this test. Auto_converge logic is only run once every
1888 * three iterations, so:
1889 *
1890 * - 3 iterations without auto_converge enabled
1891 * - 3 iterations with pct = 5
1892 * - 3 iterations with pct = 30
1893 * - 3 iterations with pct = 55
1894 * - 3 iterations with pct = 80
1895 * - 3 iterations with pct = 95 (max(95, 80 + 25))
1896 *
1897 * To make things even worse, we need to run the initial stage at
1898 * 3MB/s so we enter autoconverge even when host is (over)loaded.
1899 */
1900 static void test_migrate_auto_converge(void)
1901 {
1902 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
1903 MigrateStart args = {};
1904 QTestState *from, *to;
1905 int64_t percentage;
1906
1907 /*
1908 * We want the test to be stable and as fast as possible.
1909 * E.g., with 1Gb/s bandwith migration may pass without throttling,
1910 * so we need to decrease a bandwidth.
1911 */
1912 const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
1913
1914 if (test_migrate_start(&from, &to, uri, &args)) {
1915 return;
1916 }
1917
1918 migrate_set_capability(from, "auto-converge", true);
1919 migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct);
1920 migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct);
1921 migrate_set_parameter_int(from, "max-cpu-throttle", max_pct);
1922
1923 /*
1924 * Set the initial parameters so that the migration could not converge
1925 * without throttling.
1926 */
1927 migrate_ensure_non_converge(from);
1928
1929 /* To check remaining size after precopy */
1930 migrate_set_capability(from, "pause-before-switchover", true);
1931
1932 /* Wait for the first serial output from the source */
1933 wait_for_serial("src_serial");
1934
1935 migrate_qmp(from, uri, "{}");
1936
1937 /* Wait for throttling begins */
1938 percentage = 0;
1939 do {
1940 percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
1941 if (percentage != 0) {
1942 break;
1943 }
1944 usleep(20);
1945 g_assert_false(got_src_stop);
1946 } while (true);
1947 /* The first percentage of throttling should be at least init_pct */
1948 g_assert_cmpint(percentage, >=, init_pct);
1949 /* Now, when we tested that throttling works, let it converge */
1950 migrate_ensure_converge(from);
1951
1952 /*
1953 * Wait for pre-switchover status to check last throttle percentage
1954 * and remaining. These values will be zeroed later
1955 */
1956 wait_for_migration_status(from, "pre-switchover", NULL);
1957
1958 /* The final percentage of throttling shouldn't be greater than max_pct */
1959 percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
1960 g_assert_cmpint(percentage, <=, max_pct);
1961 migrate_continue(from, "pre-switchover");
1962
1963 qtest_qmp_eventwait(to, "RESUME");
1964
1965 wait_for_serial("dest_serial");
1966 wait_for_migration_complete(from);
1967
1968 test_migrate_end(from, to, true);
1969 }
1970
1971 static void *
1972 test_migrate_precopy_tcp_multifd_start_common(QTestState *from,
1973 QTestState *to,
1974 const char *method)
1975 {
1976 migrate_set_parameter_int(from, "multifd-channels", 16);
1977 migrate_set_parameter_int(to, "multifd-channels", 16);
1978
1979 migrate_set_parameter_str(from, "multifd-compression", method);
1980 migrate_set_parameter_str(to, "multifd-compression", method);
1981
1982 migrate_set_capability(from, "multifd", true);
1983 migrate_set_capability(to, "multifd", true);
1984
1985 /* Start incoming migration from the 1st socket */
1986 qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming',"
1987 " 'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
1988
1989 return NULL;
1990 }
1991
1992 static void *
1993 test_migrate_precopy_tcp_multifd_start(QTestState *from,
1994 QTestState *to)
1995 {
1996 return test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
1997 }
1998
1999 static void *
2000 test_migrate_precopy_tcp_multifd_zlib_start(QTestState *from,
2001 QTestState *to)
2002 {
2003 return test_migrate_precopy_tcp_multifd_start_common(from, to, "zlib");
2004 }
2005
2006 #ifdef CONFIG_ZSTD
2007 static void *
2008 test_migrate_precopy_tcp_multifd_zstd_start(QTestState *from,
2009 QTestState *to)
2010 {
2011 return test_migrate_precopy_tcp_multifd_start_common(from, to, "zstd");
2012 }
2013 #endif /* CONFIG_ZSTD */
2014
2015 static void test_multifd_tcp_none(void)
2016 {
2017 MigrateCommon args = {
2018 .listen_uri = "defer",
2019 .start_hook = test_migrate_precopy_tcp_multifd_start,
2020 };
2021 test_precopy_common(&args);
2022 }
2023
2024 static void test_multifd_tcp_zlib(void)
2025 {
2026 MigrateCommon args = {
2027 .listen_uri = "defer",
2028 .start_hook = test_migrate_precopy_tcp_multifd_zlib_start,
2029 };
2030 test_precopy_common(&args);
2031 }
2032
2033 #ifdef CONFIG_ZSTD
2034 static void test_multifd_tcp_zstd(void)
2035 {
2036 MigrateCommon args = {
2037 .listen_uri = "defer",
2038 .start_hook = test_migrate_precopy_tcp_multifd_zstd_start,
2039 };
2040 test_precopy_common(&args);
2041 }
2042 #endif
2043
2044 #ifdef CONFIG_GNUTLS
2045 static void *
2046 test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from,
2047 QTestState *to)
2048 {
2049 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2050 return test_migrate_tls_psk_start_match(from, to);
2051 }
2052
2053 static void *
2054 test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState *from,
2055 QTestState *to)
2056 {
2057 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2058 return test_migrate_tls_psk_start_mismatch(from, to);
2059 }
2060
2061 #ifdef CONFIG_TASN1
2062 static void *
2063 test_migrate_multifd_tls_x509_start_default_host(QTestState *from,
2064 QTestState *to)
2065 {
2066 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2067 return test_migrate_tls_x509_start_default_host(from, to);
2068 }
2069
2070 static void *
2071 test_migrate_multifd_tls_x509_start_override_host(QTestState *from,
2072 QTestState *to)
2073 {
2074 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2075 return test_migrate_tls_x509_start_override_host(from, to);
2076 }
2077
2078 static void *
2079 test_migrate_multifd_tls_x509_start_mismatch_host(QTestState *from,
2080 QTestState *to)
2081 {
2082 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2083 return test_migrate_tls_x509_start_mismatch_host(from, to);
2084 }
2085
2086 static void *
2087 test_migrate_multifd_tls_x509_start_allow_anon_client(QTestState *from,
2088 QTestState *to)
2089 {
2090 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2091 return test_migrate_tls_x509_start_allow_anon_client(from, to);
2092 }
2093
2094 static void *
2095 test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState *from,
2096 QTestState *to)
2097 {
2098 test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
2099 return test_migrate_tls_x509_start_reject_anon_client(from, to);
2100 }
2101 #endif /* CONFIG_TASN1 */
2102
2103 static void test_multifd_tcp_tls_psk_match(void)
2104 {
2105 MigrateCommon args = {
2106 .listen_uri = "defer",
2107 .start_hook = test_migrate_multifd_tcp_tls_psk_start_match,
2108 .finish_hook = test_migrate_tls_psk_finish,
2109 };
2110 test_precopy_common(&args);
2111 }
2112
2113 static void test_multifd_tcp_tls_psk_mismatch(void)
2114 {
2115 MigrateCommon args = {
2116 .start = {
2117 .hide_stderr = true,
2118 },
2119 .listen_uri = "defer",
2120 .start_hook = test_migrate_multifd_tcp_tls_psk_start_mismatch,
2121 .finish_hook = test_migrate_tls_psk_finish,
2122 .result = MIG_TEST_FAIL,
2123 };
2124 test_precopy_common(&args);
2125 }
2126
2127 #ifdef CONFIG_TASN1
2128 static void test_multifd_tcp_tls_x509_default_host(void)
2129 {
2130 MigrateCommon args = {
2131 .listen_uri = "defer",
2132 .start_hook = test_migrate_multifd_tls_x509_start_default_host,
2133 .finish_hook = test_migrate_tls_x509_finish,
2134 };
2135 test_precopy_common(&args);
2136 }
2137
2138 static void test_multifd_tcp_tls_x509_override_host(void)
2139 {
2140 MigrateCommon args = {
2141 .listen_uri = "defer",
2142 .start_hook = test_migrate_multifd_tls_x509_start_override_host,
2143 .finish_hook = test_migrate_tls_x509_finish,
2144 };
2145 test_precopy_common(&args);
2146 }
2147
2148 static void test_multifd_tcp_tls_x509_mismatch_host(void)
2149 {
2150 /*
2151 * This has different behaviour to the non-multifd case.
2152 *
2153 * In non-multifd case when client aborts due to mismatched
2154 * cert host, the server has already started trying to load
2155 * migration state, and so it exits with I/O failure.
2156 *
2157 * In multifd case when client aborts due to mismatched
2158 * cert host, the server is still waiting for the other
2159 * multifd connections to arrive so hasn't started trying
2160 * to load migration state, and thus just aborts the migration
2161 * without exiting.
2162 */
2163 MigrateCommon args = {
2164 .start = {
2165 .hide_stderr = true,
2166 },
2167 .listen_uri = "defer",
2168 .start_hook = test_migrate_multifd_tls_x509_start_mismatch_host,
2169 .finish_hook = test_migrate_tls_x509_finish,
2170 .result = MIG_TEST_FAIL,
2171 };
2172 test_precopy_common(&args);
2173 }
2174
2175 static void test_multifd_tcp_tls_x509_allow_anon_client(void)
2176 {
2177 MigrateCommon args = {
2178 .listen_uri = "defer",
2179 .start_hook = test_migrate_multifd_tls_x509_start_allow_anon_client,
2180 .finish_hook = test_migrate_tls_x509_finish,
2181 };
2182 test_precopy_common(&args);
2183 }
2184
2185 static void test_multifd_tcp_tls_x509_reject_anon_client(void)
2186 {
2187 MigrateCommon args = {
2188 .start = {
2189 .hide_stderr = true,
2190 },
2191 .listen_uri = "defer",
2192 .start_hook = test_migrate_multifd_tls_x509_start_reject_anon_client,
2193 .finish_hook = test_migrate_tls_x509_finish,
2194 .result = MIG_TEST_FAIL,
2195 };
2196 test_precopy_common(&args);
2197 }
2198 #endif /* CONFIG_TASN1 */
2199 #endif /* CONFIG_GNUTLS */
2200
2201 /*
2202 * This test does:
2203 * source target
2204 * migrate_incoming
2205 * migrate
2206 * migrate_cancel
2207 * launch another target
2208 * migrate
2209 *
2210 * And see that it works
2211 */
2212 static void test_multifd_tcp_cancel(void)
2213 {
2214 MigrateStart args = {
2215 .hide_stderr = true,
2216 };
2217 QTestState *from, *to, *to2;
2218 g_autofree char *uri = NULL;
2219
2220 if (test_migrate_start(&from, &to, "defer", &args)) {
2221 return;
2222 }
2223
2224 migrate_ensure_non_converge(from);
2225
2226 migrate_set_parameter_int(from, "multifd-channels", 16);
2227 migrate_set_parameter_int(to, "multifd-channels", 16);
2228
2229 migrate_set_capability(from, "multifd", true);
2230 migrate_set_capability(to, "multifd", true);
2231
2232 /* Start incoming migration from the 1st socket */
2233 qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming',"
2234 " 'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
2235
2236 /* Wait for the first serial output from the source */
2237 wait_for_serial("src_serial");
2238
2239 uri = migrate_get_socket_address(to, "socket-address");
2240
2241 migrate_qmp(from, uri, "{}");
2242
2243 wait_for_migration_pass(from);
2244
2245 migrate_cancel(from);
2246
2247 /* Make sure QEMU process "to" exited */
2248 qtest_set_expected_status(to, EXIT_FAILURE);
2249 qtest_wait_qemu(to);
2250
2251 args = (MigrateStart){
2252 .only_target = true,
2253 };
2254
2255 if (test_migrate_start(&from, &to2, "defer", &args)) {
2256 return;
2257 }
2258
2259 migrate_set_parameter_int(to2, "multifd-channels", 16);
2260
2261 migrate_set_capability(to2, "multifd", true);
2262
2263 /* Start incoming migration from the 1st socket */
2264 qtest_qmp_assert_success(to2, "{ 'execute': 'migrate-incoming',"
2265 " 'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
2266
2267 g_free(uri);
2268 uri = migrate_get_socket_address(to2, "socket-address");
2269
2270 wait_for_migration_status(from, "cancelled", NULL);
2271
2272 migrate_ensure_converge(from);
2273
2274 migrate_qmp(from, uri, "{}");
2275
2276 wait_for_migration_pass(from);
2277
2278 if (!got_src_stop) {
2279 qtest_qmp_eventwait(from, "STOP");
2280 }
2281 qtest_qmp_eventwait(to2, "RESUME");
2282
2283 wait_for_serial("dest_serial");
2284 wait_for_migration_complete(from);
2285 test_migrate_end(from, to2, true);
2286 }
2287
2288 static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
2289 {
2290 qtest_qmp_assert_success(who,
2291 "{ 'execute': 'calc-dirty-rate',"
2292 "'arguments': { "
2293 "'calc-time': %" PRIu64 ","
2294 "'mode': 'dirty-ring' }}",
2295 calc_time);
2296 }
2297
2298 static QDict *query_dirty_rate(QTestState *who)
2299 {
2300 return qtest_qmp_assert_success_ref(who,
2301 "{ 'execute': 'query-dirty-rate' }");
2302 }
2303
2304 static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate)
2305 {
2306 qtest_qmp_assert_success(who,
2307 "{ 'execute': 'set-vcpu-dirty-limit',"
2308 "'arguments': { "
2309 "'dirty-rate': %" PRIu64 " } }",
2310 dirtyrate);
2311 }
2312
2313 static void cancel_vcpu_dirty_limit(QTestState *who)
2314 {
2315 qtest_qmp_assert_success(who,
2316 "{ 'execute': 'cancel-vcpu-dirty-limit' }");
2317 }
2318
2319 static QDict *query_vcpu_dirty_limit(QTestState *who)
2320 {
2321 QDict *rsp;
2322
2323 rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }");
2324 g_assert(!qdict_haskey(rsp, "error"));
2325 g_assert(qdict_haskey(rsp, "return"));
2326
2327 return rsp;
2328 }
2329
2330 static bool calc_dirtyrate_ready(QTestState *who)
2331 {
2332 QDict *rsp_return;
2333 gchar *status;
2334
2335 rsp_return = query_dirty_rate(who);
2336 g_assert(rsp_return);
2337
2338 status = g_strdup(qdict_get_str(rsp_return, "status"));
2339 g_assert(status);
2340
2341 return g_strcmp0(status, "measuring");
2342 }
2343
2344 static void wait_for_calc_dirtyrate_complete(QTestState *who,
2345 int64_t time_s)
2346 {
2347 int max_try_count = 10000;
2348 usleep(time_s * 1000000);
2349
2350 while (!calc_dirtyrate_ready(who) && max_try_count--) {
2351 usleep(1000);
2352 }
2353
2354 /*
2355 * Set the timeout with 10 s(max_try_count * 1000us),
2356 * if dirtyrate measurement not complete, fail test.
2357 */
2358 g_assert_cmpint(max_try_count, !=, 0);
2359 }
2360
2361 static int64_t get_dirty_rate(QTestState *who)
2362 {
2363 QDict *rsp_return;
2364 gchar *status;
2365 QList *rates;
2366 const QListEntry *entry;
2367 QDict *rate;
2368 int64_t dirtyrate;
2369
2370 rsp_return = query_dirty_rate(who);
2371 g_assert(rsp_return);
2372
2373 status = g_strdup(qdict_get_str(rsp_return, "status"));
2374 g_assert(status);
2375 g_assert_cmpstr(status, ==, "measured");
2376
2377 rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate");
2378 g_assert(rates && !qlist_empty(rates));
2379
2380 entry = qlist_first(rates);
2381 g_assert(entry);
2382
2383 rate = qobject_to(QDict, qlist_entry_obj(entry));
2384 g_assert(rate);
2385
2386 dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1);
2387
2388 qobject_unref(rsp_return);
2389 return dirtyrate;
2390 }
2391
2392 static int64_t get_limit_rate(QTestState *who)
2393 {
2394 QDict *rsp_return;
2395 QList *rates;
2396 const QListEntry *entry;
2397 QDict *rate;
2398 int64_t dirtyrate;
2399
2400 rsp_return = query_vcpu_dirty_limit(who);
2401 g_assert(rsp_return);
2402
2403 rates = qdict_get_qlist(rsp_return, "return");
2404 g_assert(rates && !qlist_empty(rates));
2405
2406 entry = qlist_first(rates);
2407 g_assert(entry);
2408
2409 rate = qobject_to(QDict, qlist_entry_obj(entry));
2410 g_assert(rate);
2411
2412 dirtyrate = qdict_get_try_int(rate, "limit-rate", -1);
2413
2414 qobject_unref(rsp_return);
2415 return dirtyrate;
2416 }
2417
2418 static QTestState *dirtylimit_start_vm(void)
2419 {
2420 QTestState *vm = NULL;
2421 g_autofree gchar *cmd = NULL;
2422 const char *arch = qtest_get_arch();
2423 g_autofree char *bootpath = NULL;
2424
2425 assert((strcmp(arch, "x86_64") == 0));
2426 bootpath = g_strdup_printf("%s/bootsect", tmpfs);
2427 assert(sizeof(x86_bootsect) == 512);
2428 init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
2429
2430 cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
2431 "-name dirtylimit-test,debug-threads=on "
2432 "-m 150M -smp 1 "
2433 "-serial file:%s/vm_serial "
2434 "-drive file=%s,format=raw ",
2435 tmpfs, bootpath);
2436
2437 vm = qtest_init(cmd);
2438 return vm;
2439 }
2440
2441 static void dirtylimit_stop_vm(QTestState *vm)
2442 {
2443 qtest_quit(vm);
2444 cleanup("bootsect");
2445 cleanup("vm_serial");
2446 }
2447
2448 static void test_vcpu_dirty_limit(void)
2449 {
2450 QTestState *vm;
2451 int64_t origin_rate;
2452 int64_t quota_rate;
2453 int64_t rate ;
2454 int max_try_count = 20;
2455 int hit = 0;
2456
2457 /* Start vm for vcpu dirtylimit test */
2458 vm = dirtylimit_start_vm();
2459
2460 /* Wait for the first serial output from the vm*/
2461 wait_for_serial("vm_serial");
2462
2463 /* Do dirtyrate measurement with calc time equals 1s */
2464 calc_dirty_rate(vm, 1);
2465
2466 /* Sleep calc time and wait for calc dirtyrate complete */
2467 wait_for_calc_dirtyrate_complete(vm, 1);
2468
2469 /* Query original dirty page rate */
2470 origin_rate = get_dirty_rate(vm);
2471
2472 /* VM booted from bootsect should dirty memory steadily */
2473 assert(origin_rate != 0);
2474
2475 /* Setup quota dirty page rate at half of origin */
2476 quota_rate = origin_rate / 2;
2477
2478 /* Set dirtylimit */
2479 dirtylimit_set_all(vm, quota_rate);
2480
2481 /*
2482 * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit
2483 * works literally
2484 */
2485 g_assert_cmpint(quota_rate, ==, get_limit_rate(vm));
2486
2487 /* Sleep a bit to check if it take effect */
2488 usleep(2000000);
2489
2490 /*
2491 * Check if dirtylimit take effect realistically, set the
2492 * timeout with 20 s(max_try_count * 1s), if dirtylimit
2493 * doesn't take effect, fail test.
2494 */
2495 while (--max_try_count) {
2496 calc_dirty_rate(vm, 1);
2497 wait_for_calc_dirtyrate_complete(vm, 1);
2498 rate = get_dirty_rate(vm);
2499
2500 /*
2501 * Assume hitting if current rate is less
2502 * than quota rate (within accepting error)
2503 */
2504 if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
2505 hit = 1;
2506 break;
2507 }
2508 }
2509
2510 g_assert_cmpint(hit, ==, 1);
2511
2512 hit = 0;
2513 max_try_count = 20;
2514
2515 /* Check if dirtylimit cancellation take effect */
2516 cancel_vcpu_dirty_limit(vm);
2517 while (--max_try_count) {
2518 calc_dirty_rate(vm, 1);
2519 wait_for_calc_dirtyrate_complete(vm, 1);
2520 rate = get_dirty_rate(vm);
2521
2522 /*
2523 * Assume dirtylimit be canceled if current rate is
2524 * greater than quota rate (within accepting error)
2525 */
2526 if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
2527 hit = 1;
2528 break;
2529 }
2530 }
2531
2532 g_assert_cmpint(hit, ==, 1);
2533 dirtylimit_stop_vm(vm);
2534 }
2535
2536 static bool kvm_dirty_ring_supported(void)
2537 {
2538 #if defined(__linux__) && defined(HOST_X86_64)
2539 int ret, kvm_fd = open("/dev/kvm", O_RDONLY);
2540
2541 if (kvm_fd < 0) {
2542 return false;
2543 }
2544
2545 ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
2546 close(kvm_fd);
2547
2548 /* We test with 4096 slots */
2549 if (ret < 4096) {
2550 return false;
2551 }
2552
2553 return true;
2554 #else
2555 return false;
2556 #endif
2557 }
2558
2559 int main(int argc, char **argv)
2560 {
2561 bool has_kvm, has_tcg;
2562 bool has_uffd;
2563 const char *arch;
2564 g_autoptr(GError) err = NULL;
2565 int ret;
2566
2567 g_test_init(&argc, &argv, NULL);
2568
2569 has_kvm = qtest_has_accel("kvm");
2570 has_tcg = qtest_has_accel("tcg");
2571
2572 if (!has_tcg && !has_kvm) {
2573 g_test_skip("No KVM or TCG accelerator available");
2574 return 0;
2575 }
2576
2577 has_uffd = ufd_version_check();
2578 arch = qtest_get_arch();
2579
2580 /*
2581 * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG
2582 * is touchy due to race conditions on dirty bits (especially on PPC for
2583 * some reason)
2584 */
2585 if (g_str_equal(arch, "ppc64") &&
2586 (!has_kvm || access("/sys/module/kvm_hv", F_OK))) {
2587 g_test_message("Skipping test: kvm_hv not available");
2588 return g_test_run();
2589 }
2590
2591 /*
2592 * Similar to ppc64, s390x seems to be touchy with TCG, so disable it
2593 * there until the problems are resolved
2594 */
2595 if (g_str_equal(arch, "s390x") && !has_kvm) {
2596 g_test_message("Skipping test: s390x host with KVM is required");
2597 return g_test_run();
2598 }
2599
2600 tmpfs = g_dir_make_tmp("migration-test-XXXXXX", &err);
2601 if (!tmpfs) {
2602 g_test_message("Can't create temporary directory in %s: %s",
2603 g_get_tmp_dir(), err->message);
2604 }
2605 g_assert(tmpfs);
2606
2607 module_call_init(MODULE_INIT_QOM);
2608
2609 if (has_uffd) {
2610 qtest_add_func("/migration/postcopy/plain", test_postcopy);
2611 qtest_add_func("/migration/postcopy/recovery/plain",
2612 test_postcopy_recovery);
2613 qtest_add_func("/migration/postcopy/preempt/plain", test_postcopy_preempt);
2614 qtest_add_func("/migration/postcopy/preempt/recovery/plain",
2615 test_postcopy_preempt_recovery);
2616 if (getenv("QEMU_TEST_FLAKY_TESTS")) {
2617 qtest_add_func("/migration/postcopy/compress/plain",
2618 test_postcopy_compress);
2619 qtest_add_func("/migration/postcopy/recovery/compress/plain",
2620 test_postcopy_recovery_compress);
2621 }
2622 }
2623
2624 qtest_add_func("/migration/bad_dest", test_baddest);
2625 qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain);
2626 qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle);
2627 /*
2628 * Compression fails from time to time.
2629 * Put test here but don't enable it until everything is fixed.
2630 */
2631 if (getenv("QEMU_TEST_FLAKY_TESTS")) {
2632 qtest_add_func("/migration/precopy/unix/compress/wait",
2633 test_precopy_unix_compress);
2634 qtest_add_func("/migration/precopy/unix/compress/nowait",
2635 test_precopy_unix_compress_nowait);
2636 }
2637 #ifdef CONFIG_GNUTLS
2638 qtest_add_func("/migration/precopy/unix/tls/psk",
2639 test_precopy_unix_tls_psk);
2640
2641 if (has_uffd) {
2642 /*
2643 * NOTE: psk test is enough for postcopy, as other types of TLS
2644 * channels are tested under precopy. Here what we want to test is the
2645 * general postcopy path that has TLS channel enabled.
2646 */
2647 qtest_add_func("/migration/postcopy/tls/psk", test_postcopy_tls_psk);
2648 qtest_add_func("/migration/postcopy/recovery/tls/psk",
2649 test_postcopy_recovery_tls_psk);
2650 qtest_add_func("/migration/postcopy/preempt/tls/psk",
2651 test_postcopy_preempt_tls_psk);
2652 qtest_add_func("/migration/postcopy/preempt/recovery/tls/psk",
2653 test_postcopy_preempt_all);
2654 }
2655 #ifdef CONFIG_TASN1
2656 qtest_add_func("/migration/precopy/unix/tls/x509/default-host",
2657 test_precopy_unix_tls_x509_default_host);
2658 qtest_add_func("/migration/precopy/unix/tls/x509/override-host",
2659 test_precopy_unix_tls_x509_override_host);
2660 #endif /* CONFIG_TASN1 */
2661 #endif /* CONFIG_GNUTLS */
2662
2663 qtest_add_func("/migration/precopy/tcp/plain", test_precopy_tcp_plain);
2664 #ifdef CONFIG_GNUTLS
2665 qtest_add_func("/migration/precopy/tcp/tls/psk/match",
2666 test_precopy_tcp_tls_psk_match);
2667 qtest_add_func("/migration/precopy/tcp/tls/psk/mismatch",
2668 test_precopy_tcp_tls_psk_mismatch);
2669 #ifdef CONFIG_TASN1
2670 qtest_add_func("/migration/precopy/tcp/tls/x509/default-host",
2671 test_precopy_tcp_tls_x509_default_host);
2672 qtest_add_func("/migration/precopy/tcp/tls/x509/override-host",
2673 test_precopy_tcp_tls_x509_override_host);
2674 qtest_add_func("/migration/precopy/tcp/tls/x509/mismatch-host",
2675 test_precopy_tcp_tls_x509_mismatch_host);
2676 qtest_add_func("/migration/precopy/tcp/tls/x509/friendly-client",
2677 test_precopy_tcp_tls_x509_friendly_client);
2678 qtest_add_func("/migration/precopy/tcp/tls/x509/hostile-client",
2679 test_precopy_tcp_tls_x509_hostile_client);
2680 qtest_add_func("/migration/precopy/tcp/tls/x509/allow-anon-client",
2681 test_precopy_tcp_tls_x509_allow_anon_client);
2682 qtest_add_func("/migration/precopy/tcp/tls/x509/reject-anon-client",
2683 test_precopy_tcp_tls_x509_reject_anon_client);
2684 #endif /* CONFIG_TASN1 */
2685 #endif /* CONFIG_GNUTLS */
2686
2687 /* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */
2688 #ifndef _WIN32
2689 qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
2690 #endif
2691 qtest_add_func("/migration/validate_uuid", test_validate_uuid);
2692 qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error);
2693 qtest_add_func("/migration/validate_uuid_src_not_set",
2694 test_validate_uuid_src_not_set);
2695 qtest_add_func("/migration/validate_uuid_dst_not_set",
2696 test_validate_uuid_dst_not_set);
2697 /*
2698 * See explanation why this test is slow on function definition
2699 */
2700 if (g_test_slow()) {
2701 qtest_add_func("/migration/auto_converge", test_migrate_auto_converge);
2702 }
2703 qtest_add_func("/migration/multifd/tcp/plain/none",
2704 test_multifd_tcp_none);
2705 /*
2706 * This test is flaky and sometimes fails in CI and otherwise:
2707 * don't run unless user opts in via environment variable.
2708 */
2709 if (getenv("QEMU_TEST_FLAKY_TESTS")) {
2710 qtest_add_func("/migration/multifd/tcp/plain/cancel",
2711 test_multifd_tcp_cancel);
2712 }
2713 qtest_add_func("/migration/multifd/tcp/plain/zlib",
2714 test_multifd_tcp_zlib);
2715 #ifdef CONFIG_ZSTD
2716 qtest_add_func("/migration/multifd/tcp/plain/zstd",
2717 test_multifd_tcp_zstd);
2718 #endif
2719 #ifdef CONFIG_GNUTLS
2720 qtest_add_func("/migration/multifd/tcp/tls/psk/match",
2721 test_multifd_tcp_tls_psk_match);
2722 qtest_add_func("/migration/multifd/tcp/tls/psk/mismatch",
2723 test_multifd_tcp_tls_psk_mismatch);
2724 #ifdef CONFIG_TASN1
2725 qtest_add_func("/migration/multifd/tcp/tls/x509/default-host",
2726 test_multifd_tcp_tls_x509_default_host);
2727 qtest_add_func("/migration/multifd/tcp/tls/x509/override-host",
2728 test_multifd_tcp_tls_x509_override_host);
2729 qtest_add_func("/migration/multifd/tcp/tls/x509/mismatch-host",
2730 test_multifd_tcp_tls_x509_mismatch_host);
2731 qtest_add_func("/migration/multifd/tcp/tls/x509/allow-anon-client",
2732 test_multifd_tcp_tls_x509_allow_anon_client);
2733 qtest_add_func("/migration/multifd/tcp/tls/x509/reject-anon-client",
2734 test_multifd_tcp_tls_x509_reject_anon_client);
2735 #endif /* CONFIG_TASN1 */
2736 #endif /* CONFIG_GNUTLS */
2737
2738 if (g_str_equal(arch, "x86_64") && has_kvm && kvm_dirty_ring_supported()) {
2739 qtest_add_func("/migration/dirty_ring",
2740 test_precopy_unix_dirty_ring);
2741 qtest_add_func("/migration/vcpu_dirty_limit",
2742 test_vcpu_dirty_limit);
2743 }
2744
2745 ret = g_test_run();
2746
2747 g_assert_cmpint(ret, ==, 0);
2748
2749 ret = rmdir(tmpfs);
2750 if (ret != 0) {
2751 g_test_message("unable to rmdir: path (%s): %s",
2752 tmpfs, strerror(errno));
2753 }
2754 g_free(tmpfs);
2755
2756 return ret;
2757 }