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