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