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