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