1 /*
2 * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
3 * based on the vhost-user-test.c that is:
4 * Copyright (c) 2014 Virtual Open Systems Sarl.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 *
9 */
10
11 #ifndef TEST_FRAMEWORK_H
12 #define TEST_FRAMEWORK_H
13
14 #include "libqtest.h"
15
16 #define FILE_TEST_FILENAME "migfile"
17 #define FILE_TEST_OFFSET 0x1000
18 #define FILE_TEST_MARKER 'X'
19
20 typedef struct MigrationTestEnv {
21 bool has_kvm;
22 bool has_tcg;
23 bool has_uffd;
24 bool uffd_feature_thread_id;
25 bool has_dirty_ring;
26 bool is_x86;
27 bool full_set;
28 const char *arch;
29 const char *qemu_src;
30 const char *qemu_dst;
31 char *tmpfs;
32 } MigrationTestEnv;
33
34 MigrationTestEnv *migration_get_env(void);
35 int migration_env_clean(MigrationTestEnv *env);
36
37 /*
38 * A hook that runs after the src and dst QEMUs have been
39 * created, but before the migration is started. This can
40 * be used to set migration parameters and capabilities.
41 *
42 * Returns: NULL, or a pointer to opaque state to be
43 * later passed to the TestMigrateEndHook
44 */
45 typedef void * (*TestMigrateStartHook)(QTestState *from,
46 QTestState *to);
47
48 /*
49 * A hook that runs after the migration has finished,
50 * regardless of whether it succeeded or failed, but
51 * before QEMU has terminated (unless it self-terminated
52 * due to migration error)
53 *
54 * @opaque is a pointer to state previously returned
55 * by the TestMigrateStartHook if any, or NULL.
56 */
57 typedef void (*TestMigrateEndHook)(QTestState *from,
58 QTestState *to,
59 void *opaque);
60
61 /*
62 * Our goal is to ensure that we run a single full migration
63 * iteration, and also dirty memory, ensuring that at least
64 * one further iteration is required.
65 *
66 * We can't directly synchronize with the start of a migration
67 * so we have to apply some tricks monitoring memory that is
68 * transferred.
69 *
70 * Initially we set the migration bandwidth to an insanely
71 * low value, with tiny max downtime too. This basically
72 * guarantees migration will never complete.
73 *
74 * This will result in a test that is unacceptably slow though,
75 * so we can't let the entire migration pass run at this speed.
76 * Our intent is to let it run just long enough that we can
77 * prove data prior to the marker has been transferred *AND*
78 * also prove this transferred data is dirty again.
79 *
80 * Before migration starts, we write a 64-bit magic marker
81 * into a fixed location in the src VM RAM.
82 *
83 * Then watch dst memory until the marker appears. This is
84 * proof that start_address -> MAGIC_OFFSET_BASE has been
85 * transferred.
86 *
87 * Finally we go back to the source and read a byte just
88 * before the marker until we see it flip in value. This
89 * is proof that start_address -> MAGIC_OFFSET_BASE
90 * is now dirty again.
91 *
92 * IOW, we're guaranteed at least a 2nd migration pass
93 * at this point.
94 *
95 * We can now let migration run at full speed to finish
96 * the test
97 */
98 typedef struct {
99 /*
100 * QTEST_LOG=1 may override this. When QTEST_LOG=1, we always dump errors
101 * unconditionally, because it means the user would like to be verbose.
102 */
103 bool hide_stderr;
104 bool use_shmem;
105 /* only launch the target process */
106 bool only_target;
107 /* Use dirty ring if true; dirty logging otherwise */
108 bool use_dirty_ring;
109 const char *opts_source;
110 const char *opts_target;
111 /* suspend the src before migrating to dest. */
112 bool suspend_me;
113 /* enable OOB QMP capability */
114 bool oob;
115 /*
116 * Format string for the main memory backend, containing one %s where the
117 * size is plugged in. If omitted, "-m %s" is used.
118 */
119 const char *memory_backend;
120
121 /* Do not connect to target monitor and qtest sockets in qtest_init */
122 bool defer_target_connect;
123 } MigrateStart;
124
125 typedef enum PostcopyRecoveryFailStage {
126 /*
127 * "no failure" must be 0 as it's the default. OTOH, real failure
128 * cases must be >0 to make sure they trigger by a "if" test.
129 */
130 POSTCOPY_FAIL_NONE = 0,
131 POSTCOPY_FAIL_CHANNEL_ESTABLISH,
132 POSTCOPY_FAIL_RECOVERY,
133 POSTCOPY_FAIL_MAX
134 } PostcopyRecoveryFailStage;
135
136 typedef struct {
137 /* Optional: fine tune start parameters */
138 MigrateStart start;
139
140 /* Required: the URI for the dst QEMU to listen on */
141 const char *listen_uri;
142
143 /*
144 * Optional: the URI for the src QEMU to connect to
145 * If NULL, then it will query the dst QEMU for its actual
146 * listening address and use that as the connect address.
147 * This allows for dynamically picking a free TCP port.
148 */
149 const char *connect_uri;
150
151 /*
152 * Optional: JSON-formatted list of src QEMU URIs. If a port is
153 * defined as '0' in any QDict key a value of '0' will be
154 * automatically converted to the correct destination port.
155 */
156 const char *connect_channels;
157
158 /* Optional: the cpr migration channel, in JSON or dotted keys format */
159 const char *cpr_channel;
160
161 /* Optional: callback to run at start to set migration parameters */
162 TestMigrateStartHook start_hook;
163 /* Optional: callback to run at finish to cleanup */
164 TestMigrateEndHook end_hook;
165
166 /*
167 * Optional: normally we expect the migration process to complete.
168 *
169 * There can be a variety of reasons and stages in which failure
170 * can happen during tests.
171 *
172 * If a failure is expected to happen at time of establishing
173 * the connection, then MIG_TEST_FAIL will indicate that the dst
174 * QEMU is expected to stay running and accept future migration
175 * connections.
176 *
177 * If a failure is expected to happen while processing the
178 * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
179 * that the dst QEMU is expected to quit with non-zero exit status
180 */
181 enum {
182 /* This test should succeed, the default */
183 MIG_TEST_SUCCEED = 0,
184 /* This test should fail, dest qemu should keep alive */
185 MIG_TEST_FAIL,
186 /* This test should fail, dest qemu should fail with abnormal status */
187 MIG_TEST_FAIL_DEST_QUIT_ERR,
188 /* The QMP command for this migration should fail with an error */
189 MIG_TEST_QMP_ERROR,
190 } result;
191
192 /*
193 * Optional: set number of migration passes to wait for, if live==true.
194 * If zero, then merely wait for a few MB of dirty data
195 */
196 unsigned int iterations;
197
198 /*
199 * Optional: whether the guest CPUs should be running during a precopy
200 * migration test. We used to always run with live but it took much
201 * longer so we reduced live tests to only the ones that have solid
202 * reason to be tested live-only. For each of the new test cases for
203 * precopy please provide justifications to use live explicitly (please
204 * refer to existing ones with live=true), or use live=off by default.
205 */
206 bool live;
207
208 /* Postcopy specific fields */
209 void *postcopy_data;
210 bool postcopy_preempt;
211 PostcopyRecoveryFailStage postcopy_recovery_fail_stage;
212 } MigrateCommon;
213
214 void wait_for_serial(const char *side);
215 void migrate_prepare_for_dirty_mem(QTestState *from);
216 void migrate_wait_for_dirty_mem(QTestState *from, QTestState *to);
217 int migrate_start(QTestState **from, QTestState **to, const char *uri,
218 MigrateStart *args);
219 void migrate_end(QTestState *from, QTestState *to, bool test_dest);
220
221 void test_postcopy_common(MigrateCommon *args);
222 void test_postcopy_recovery_common(MigrateCommon *args);
223 void test_precopy_common(MigrateCommon *args);
224 void test_file_common(MigrateCommon *args, bool stop_src);
225 void *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from,
226 QTestState *to,
227 const char *method);
228
229 typedef struct QTestMigrationState QTestMigrationState;
230 QTestMigrationState *get_src(void);
231
232 #ifdef CONFIG_GNUTLS
233 void migration_test_add_tls(MigrationTestEnv *env);
234 #else
migration_test_add_tls(MigrationTestEnv * env)235 static inline void migration_test_add_tls(MigrationTestEnv *env) {};
236 #endif
237 void migration_test_add_compression(MigrationTestEnv *env);
238 void migration_test_add_postcopy(MigrationTestEnv *env);
239 void migration_test_add_file(MigrationTestEnv *env);
240 void migration_test_add_precopy(MigrationTestEnv *env);
241 void migration_test_add_cpr(MigrationTestEnv *env);
242 void migration_test_add_misc(MigrationTestEnv *env);
243
244 #endif /* TEST_FRAMEWORK_H */
245