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