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