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