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