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 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