1e32b96b5SLaurent Vivier /* 2e32b96b5SLaurent Vivier * QTest testcase for virtio-net failover 3e32b96b5SLaurent Vivier * 4e32b96b5SLaurent Vivier * See docs/system/virtio-net-failover.rst 5e32b96b5SLaurent Vivier * 6e32b96b5SLaurent Vivier * Copyright (c) 2021 Red Hat, Inc. 7e32b96b5SLaurent Vivier * 8e32b96b5SLaurent Vivier * SPDX-License-Identifier: GPL-2.0-or-later 9e32b96b5SLaurent Vivier */ 10e32b96b5SLaurent Vivier #include "qemu/osdep.h" 11907b5105SMarc-André Lureau #include "libqtest.h" 12e32b96b5SLaurent Vivier #include "libqos/pci.h" 13e32b96b5SLaurent Vivier #include "libqos/pci-pc.h" 14e6c57040SFabiano Rosas #include "migration/migration-qmp.h" 15*b7d7f723SFabiano Rosas #include "migration/migration-util.h" 16e32b96b5SLaurent Vivier #include "qapi/qmp/qdict.h" 17e32b96b5SLaurent Vivier #include "qapi/qmp/qlist.h" 18e32b96b5SLaurent Vivier #include "qapi/qmp/qjson.h" 19e32b96b5SLaurent Vivier #include "libqos/malloc-pc.h" 20e32b96b5SLaurent Vivier #include "libqos/virtio-pci.h" 21e32b96b5SLaurent Vivier #include "hw/pci/pci.h" 22e32b96b5SLaurent Vivier 2393262464SLaurent Vivier #define VIRTIO_NET_F_STANDBY 62 2493262464SLaurent Vivier 25e32b96b5SLaurent Vivier #define ACPI_PCIHP_ADDR_ICH9 0x0cc0 26e32b96b5SLaurent Vivier #define PCI_EJ_BASE 0x0008 27e1e3d321SLaurent Vivier #define PCI_SEL_BASE 0x0010 28e32b96b5SLaurent Vivier 29e32b96b5SLaurent Vivier #define BASE_MACHINE "-M q35 -nodefaults " \ 30e32b96b5SLaurent Vivier "-device pcie-root-port,id=root0,addr=0x1,bus=pcie.0,chassis=1 " \ 31e32b96b5SLaurent Vivier "-device pcie-root-port,id=root1,addr=0x2,bus=pcie.0,chassis=2 " 32e32b96b5SLaurent Vivier 33e32b96b5SLaurent Vivier #define MAC_PRIMARY0 "52:54:00:11:11:11" 34e32b96b5SLaurent Vivier #define MAC_STANDBY0 "52:54:00:22:22:22" 35e1e3d321SLaurent Vivier #define MAC_PRIMARY1 "52:54:00:33:33:33" 36e1e3d321SLaurent Vivier #define MAC_STANDBY1 "52:54:00:44:44:44" 37e32b96b5SLaurent Vivier 38e32b96b5SLaurent Vivier static QGuestAllocator guest_malloc; 39e32b96b5SLaurent Vivier static QPCIBus *pcibus; 40e32b96b5SLaurent Vivier 41e32b96b5SLaurent Vivier static QTestState *machine_start(const char *args, int numbus) 42e32b96b5SLaurent Vivier { 43e32b96b5SLaurent Vivier QTestState *qts; 44e32b96b5SLaurent Vivier QPCIDevice *dev; 45e32b96b5SLaurent Vivier int bus; 46e32b96b5SLaurent Vivier 47e32b96b5SLaurent Vivier qts = qtest_init(args); 48e32b96b5SLaurent Vivier 49e32b96b5SLaurent Vivier pc_alloc_init(&guest_malloc, qts, 0); 50e32b96b5SLaurent Vivier pcibus = qpci_new_pc(qts, &guest_malloc); 51e32b96b5SLaurent Vivier g_assert(qpci_secondary_buses_init(pcibus) == numbus); 52e32b96b5SLaurent Vivier 53e32b96b5SLaurent Vivier for (bus = 1; bus <= numbus; bus++) { 54e32b96b5SLaurent Vivier dev = qpci_device_find(pcibus, QPCI_DEVFN(bus, 0)); 55e32b96b5SLaurent Vivier g_assert_nonnull(dev); 56e32b96b5SLaurent Vivier 57e32b96b5SLaurent Vivier qpci_device_enable(dev); 58e32b96b5SLaurent Vivier qpci_iomap(dev, 4, NULL); 59e32b96b5SLaurent Vivier 60e32b96b5SLaurent Vivier g_free(dev); 61e32b96b5SLaurent Vivier } 62e32b96b5SLaurent Vivier 63e32b96b5SLaurent Vivier return qts; 64e32b96b5SLaurent Vivier } 65e32b96b5SLaurent Vivier 66e32b96b5SLaurent Vivier static void machine_stop(QTestState *qts) 67e32b96b5SLaurent Vivier { 68e32b96b5SLaurent Vivier qpci_free_pc(pcibus); 69e32b96b5SLaurent Vivier alloc_destroy(&guest_malloc); 70e32b96b5SLaurent Vivier qtest_quit(qts); 71e32b96b5SLaurent Vivier } 72e32b96b5SLaurent Vivier 73e32b96b5SLaurent Vivier static void test_error_id(void) 74e32b96b5SLaurent Vivier { 75e32b96b5SLaurent Vivier QTestState *qts; 76e32b96b5SLaurent Vivier QDict *resp; 77e32b96b5SLaurent Vivier QDict *err; 78e32b96b5SLaurent Vivier 79e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 80e32b96b5SLaurent Vivier "-device virtio-net,bus=root0,id=standby0,failover=on", 81e32b96b5SLaurent Vivier 2); 82e32b96b5SLaurent Vivier 83e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{'execute': 'device_add'," 84e32b96b5SLaurent Vivier "'arguments': {" 85e32b96b5SLaurent Vivier "'driver': 'virtio-net'," 86e32b96b5SLaurent Vivier "'bus': 'root1'," 87e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'" 88e32b96b5SLaurent Vivier "} }"); 89e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "error")); 90e32b96b5SLaurent Vivier 91e32b96b5SLaurent Vivier err = qdict_get_qdict(resp, "error"); 92e32b96b5SLaurent Vivier g_assert(qdict_haskey(err, "desc")); 93e32b96b5SLaurent Vivier 94e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(err, "desc"), ==, 95e32b96b5SLaurent Vivier "Device with failover_pair_id needs to have id"); 96e32b96b5SLaurent Vivier 97e32b96b5SLaurent Vivier qobject_unref(resp); 98e32b96b5SLaurent Vivier 99e32b96b5SLaurent Vivier machine_stop(qts); 100e32b96b5SLaurent Vivier } 101e32b96b5SLaurent Vivier 102e32b96b5SLaurent Vivier static void test_error_pcie(void) 103e32b96b5SLaurent Vivier { 104e32b96b5SLaurent Vivier QTestState *qts; 105e32b96b5SLaurent Vivier QDict *resp; 106e32b96b5SLaurent Vivier QDict *err; 107e32b96b5SLaurent Vivier 108e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 109e32b96b5SLaurent Vivier "-device virtio-net,bus=root0,id=standby0,failover=on", 110e32b96b5SLaurent Vivier 2); 111e32b96b5SLaurent Vivier 112e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{'execute': 'device_add'," 113e32b96b5SLaurent Vivier "'arguments': {" 114e32b96b5SLaurent Vivier "'driver': 'virtio-net'," 115e32b96b5SLaurent Vivier "'id': 'primary0'," 116e32b96b5SLaurent Vivier "'bus': 'pcie.0'," 117e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'" 118e32b96b5SLaurent Vivier "} }"); 119e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "error")); 120e32b96b5SLaurent Vivier 121e32b96b5SLaurent Vivier err = qdict_get_qdict(resp, "error"); 122e32b96b5SLaurent Vivier g_assert(qdict_haskey(err, "desc")); 123e32b96b5SLaurent Vivier 124e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(err, "desc"), ==, 125e32b96b5SLaurent Vivier "Bus 'pcie.0' does not support hotplugging"); 126e32b96b5SLaurent Vivier 127e32b96b5SLaurent Vivier qobject_unref(resp); 128e32b96b5SLaurent Vivier 129e32b96b5SLaurent Vivier machine_stop(qts); 130e32b96b5SLaurent Vivier } 131e32b96b5SLaurent Vivier 132e32b96b5SLaurent Vivier static QDict *find_device(QDict *bus, const char *name) 133e32b96b5SLaurent Vivier { 134e32b96b5SLaurent Vivier const QObject *obj; 135e32b96b5SLaurent Vivier QList *devices; 136e32b96b5SLaurent Vivier QList *list; 137e32b96b5SLaurent Vivier 138e32b96b5SLaurent Vivier devices = qdict_get_qlist(bus, "devices"); 139e32b96b5SLaurent Vivier if (devices == NULL) { 140e32b96b5SLaurent Vivier return NULL; 141e32b96b5SLaurent Vivier } 142e32b96b5SLaurent Vivier 143e32b96b5SLaurent Vivier list = qlist_copy(devices); 144e32b96b5SLaurent Vivier while ((obj = qlist_pop(list))) { 145e32b96b5SLaurent Vivier QDict *device; 146e32b96b5SLaurent Vivier 147e32b96b5SLaurent Vivier device = qobject_to(QDict, obj); 148e32b96b5SLaurent Vivier 149e32b96b5SLaurent Vivier if (qdict_haskey(device, "pci_bridge")) { 150e32b96b5SLaurent Vivier QDict *bridge; 151e32b96b5SLaurent Vivier QDict *bridge_device; 152e32b96b5SLaurent Vivier 153e32b96b5SLaurent Vivier bridge = qdict_get_qdict(device, "pci_bridge"); 154e32b96b5SLaurent Vivier 155e32b96b5SLaurent Vivier if (qdict_haskey(bridge, "devices")) { 156e32b96b5SLaurent Vivier bridge_device = find_device(bridge, name); 157e32b96b5SLaurent Vivier if (bridge_device) { 158e32b96b5SLaurent Vivier qobject_unref(device); 159e32b96b5SLaurent Vivier qobject_unref(list); 160e32b96b5SLaurent Vivier return bridge_device; 161e32b96b5SLaurent Vivier } 162e32b96b5SLaurent Vivier } 163e32b96b5SLaurent Vivier } 164e32b96b5SLaurent Vivier 165e32b96b5SLaurent Vivier if (!qdict_haskey(device, "qdev_id")) { 166e32b96b5SLaurent Vivier qobject_unref(device); 167e32b96b5SLaurent Vivier continue; 168e32b96b5SLaurent Vivier } 169e32b96b5SLaurent Vivier 170e32b96b5SLaurent Vivier if (strcmp(qdict_get_str(device, "qdev_id"), name) == 0) { 171e32b96b5SLaurent Vivier qobject_unref(list); 172e32b96b5SLaurent Vivier return device; 173e32b96b5SLaurent Vivier } 174e32b96b5SLaurent Vivier qobject_unref(device); 175e32b96b5SLaurent Vivier } 176e32b96b5SLaurent Vivier qobject_unref(list); 177e32b96b5SLaurent Vivier 178e32b96b5SLaurent Vivier return NULL; 179e32b96b5SLaurent Vivier } 180e32b96b5SLaurent Vivier 181e32b96b5SLaurent Vivier static QDict *get_bus(QTestState *qts, int num) 182e32b96b5SLaurent Vivier { 183e32b96b5SLaurent Vivier QObject *obj; 184e32b96b5SLaurent Vivier QDict *resp; 185e32b96b5SLaurent Vivier QList *ret; 186e32b96b5SLaurent Vivier 187e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'query-pci' }"); 188e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 189e32b96b5SLaurent Vivier 190e32b96b5SLaurent Vivier ret = qdict_get_qlist(resp, "return"); 191e32b96b5SLaurent Vivier g_assert_nonnull(ret); 192e32b96b5SLaurent Vivier 193e32b96b5SLaurent Vivier while ((obj = qlist_pop(ret))) { 194e32b96b5SLaurent Vivier QDict *bus; 195e32b96b5SLaurent Vivier 196e32b96b5SLaurent Vivier bus = qobject_to(QDict, obj); 197e32b96b5SLaurent Vivier if (!qdict_haskey(bus, "bus")) { 198e32b96b5SLaurent Vivier qobject_unref(bus); 199e32b96b5SLaurent Vivier continue; 200e32b96b5SLaurent Vivier } 201e32b96b5SLaurent Vivier if (qdict_get_int(bus, "bus") == num) { 202e32b96b5SLaurent Vivier qobject_unref(resp); 203e32b96b5SLaurent Vivier return bus; 204e32b96b5SLaurent Vivier } 205e32b96b5SLaurent Vivier qobject_ref(bus); 206e32b96b5SLaurent Vivier } 207e32b96b5SLaurent Vivier qobject_unref(resp); 208e32b96b5SLaurent Vivier 209e32b96b5SLaurent Vivier return NULL; 210e32b96b5SLaurent Vivier } 211e32b96b5SLaurent Vivier 212e32b96b5SLaurent Vivier static char *get_mac(QTestState *qts, const char *name) 213e32b96b5SLaurent Vivier { 214e32b96b5SLaurent Vivier QDict *resp; 215e32b96b5SLaurent Vivier char *mac; 216e32b96b5SLaurent Vivier 217e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'qom-get', " 218e32b96b5SLaurent Vivier "'arguments': { " 219e32b96b5SLaurent Vivier "'path': %s, " 220e32b96b5SLaurent Vivier "'property': 'mac' } }", name); 221e32b96b5SLaurent Vivier 222e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 223e32b96b5SLaurent Vivier 224e32b96b5SLaurent Vivier mac = g_strdup(qdict_get_str(resp, "return")); 225e32b96b5SLaurent Vivier 226e32b96b5SLaurent Vivier qobject_unref(resp); 227e32b96b5SLaurent Vivier 228e32b96b5SLaurent Vivier return mac; 229e32b96b5SLaurent Vivier } 230e32b96b5SLaurent Vivier 2311a800870SLaurent Vivier #define check_one_card(qts, present, id, mac) \ 2321a800870SLaurent Vivier do { \ 2331a800870SLaurent Vivier QDict *device; \ 2341a800870SLaurent Vivier QDict *bus; \ 2351a800870SLaurent Vivier char *addr; \ 2361a800870SLaurent Vivier bus = get_bus(qts, 0); \ 2371a800870SLaurent Vivier device = find_device(bus, id); \ 2381a800870SLaurent Vivier if (present) { \ 2391a800870SLaurent Vivier char *path; \ 2401a800870SLaurent Vivier g_assert_nonnull(device); \ 2411a800870SLaurent Vivier qobject_unref(device); \ 2421a800870SLaurent Vivier path = g_strdup_printf("/machine/peripheral/%s", id); \ 2431a800870SLaurent Vivier addr = get_mac(qts, path); \ 2441a800870SLaurent Vivier g_free(path); \ 2451a800870SLaurent Vivier g_assert_cmpstr(mac, ==, addr); \ 2461a800870SLaurent Vivier g_free(addr); \ 2471a800870SLaurent Vivier } else { \ 2481a800870SLaurent Vivier g_assert_null(device); \ 2491a800870SLaurent Vivier } \ 2501a800870SLaurent Vivier qobject_unref(bus); \ 2511a800870SLaurent Vivier } while (0) 252e32b96b5SLaurent Vivier 253e32b96b5SLaurent Vivier static QDict *get_failover_negociated_event(QTestState *qts) 254e32b96b5SLaurent Vivier { 255e32b96b5SLaurent Vivier QDict *resp; 256e32b96b5SLaurent Vivier QDict *data; 257e32b96b5SLaurent Vivier 258e32b96b5SLaurent Vivier resp = qtest_qmp_eventwait_ref(qts, "FAILOVER_NEGOTIATED"); 259e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "data")); 260e32b96b5SLaurent Vivier 261e32b96b5SLaurent Vivier data = qdict_get_qdict(resp, "data"); 262e32b96b5SLaurent Vivier g_assert(qdict_haskey(data, "device-id")); 263e32b96b5SLaurent Vivier qobject_ref(data); 264e32b96b5SLaurent Vivier qobject_unref(resp); 265e32b96b5SLaurent Vivier 266e32b96b5SLaurent Vivier return data; 267e32b96b5SLaurent Vivier } 268e32b96b5SLaurent Vivier 26993262464SLaurent Vivier static QVirtioPCIDevice *start_virtio_net_internal(QTestState *qts, 27093262464SLaurent Vivier int bus, int slot, 27193262464SLaurent Vivier uint64_t *features) 272e32b96b5SLaurent Vivier { 273e32b96b5SLaurent Vivier QVirtioPCIDevice *dev; 274e32b96b5SLaurent Vivier QPCIAddress addr; 275e32b96b5SLaurent Vivier 276e32b96b5SLaurent Vivier addr.devfn = QPCI_DEVFN((bus << 5) + slot, 0); 277e32b96b5SLaurent Vivier dev = virtio_pci_new(pcibus, &addr); 278e32b96b5SLaurent Vivier g_assert_nonnull(dev); 279e32b96b5SLaurent Vivier qvirtio_pci_device_enable(dev); 280e32b96b5SLaurent Vivier qvirtio_start_device(&dev->vdev); 28193262464SLaurent Vivier *features &= qvirtio_get_features(&dev->vdev); 28293262464SLaurent Vivier qvirtio_set_features(&dev->vdev, *features); 28393262464SLaurent Vivier qvirtio_set_driver_ok(&dev->vdev); 28493262464SLaurent Vivier return dev; 28593262464SLaurent Vivier } 28693262464SLaurent Vivier 28793262464SLaurent Vivier static QVirtioPCIDevice *start_virtio_net(QTestState *qts, int bus, int slot, 28893262464SLaurent Vivier const char *id, bool failover) 28993262464SLaurent Vivier { 29093262464SLaurent Vivier QVirtioPCIDevice *dev; 29193262464SLaurent Vivier uint64_t features; 29293262464SLaurent Vivier 29393262464SLaurent Vivier features = ~(QVIRTIO_F_BAD_FEATURE | 294e32b96b5SLaurent Vivier (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 295e32b96b5SLaurent Vivier (1ull << VIRTIO_RING_F_EVENT_IDX)); 29693262464SLaurent Vivier 29793262464SLaurent Vivier dev = start_virtio_net_internal(qts, bus, slot, &features); 29893262464SLaurent Vivier 29993262464SLaurent Vivier g_assert(!!(features & (1ull << VIRTIO_NET_F_STANDBY)) == failover); 30093262464SLaurent Vivier 30193262464SLaurent Vivier if (failover) { 30293262464SLaurent Vivier QDict *resp; 303e32b96b5SLaurent Vivier 304e32b96b5SLaurent Vivier resp = get_failover_negociated_event(qts); 305e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, id); 306e32b96b5SLaurent Vivier qobject_unref(resp); 30793262464SLaurent Vivier } 308e32b96b5SLaurent Vivier 309e32b96b5SLaurent Vivier return dev; 310e32b96b5SLaurent Vivier } 311e32b96b5SLaurent Vivier 31293262464SLaurent Vivier static void test_on(void) 31393262464SLaurent Vivier { 31493262464SLaurent Vivier QTestState *qts; 31593262464SLaurent Vivier 31693262464SLaurent Vivier qts = machine_start(BASE_MACHINE 31793262464SLaurent Vivier "-netdev user,id=hs0 " 31893262464SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 31993262464SLaurent Vivier "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 32093262464SLaurent Vivier "-netdev user,id=hs1 " 32193262464SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 32293262464SLaurent Vivier "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0, 32393262464SLaurent Vivier 2); 32493262464SLaurent Vivier 32593262464SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 32693262464SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 32793262464SLaurent Vivier 32893262464SLaurent Vivier machine_stop(qts); 32993262464SLaurent Vivier } 33093262464SLaurent Vivier 33193262464SLaurent Vivier static void test_on_mismatch(void) 33293262464SLaurent Vivier { 33393262464SLaurent Vivier QTestState *qts; 33493262464SLaurent Vivier QVirtioPCIDevice *vdev; 33593262464SLaurent Vivier 33693262464SLaurent Vivier qts = machine_start(BASE_MACHINE 33793262464SLaurent Vivier "-netdev user,id=hs0 " 33893262464SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 33993262464SLaurent Vivier "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 34093262464SLaurent Vivier "-netdev user,id=hs1 " 34193262464SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 34293262464SLaurent Vivier "failover_pair_id=standby1,netdev=hs1,mac="MAC_PRIMARY0, 34393262464SLaurent Vivier 2); 34493262464SLaurent Vivier 34593262464SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 34693262464SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 34793262464SLaurent Vivier 34893262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 34993262464SLaurent Vivier 35093262464SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 35193262464SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 35293262464SLaurent Vivier 35393262464SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 35493262464SLaurent Vivier machine_stop(qts); 35593262464SLaurent Vivier } 35693262464SLaurent Vivier 35793262464SLaurent Vivier static void test_off(void) 35893262464SLaurent Vivier { 35993262464SLaurent Vivier QTestState *qts; 36093262464SLaurent Vivier QVirtioPCIDevice *vdev; 36193262464SLaurent Vivier 36293262464SLaurent Vivier qts = machine_start(BASE_MACHINE 36393262464SLaurent Vivier "-netdev user,id=hs0 " 36493262464SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 36593262464SLaurent Vivier "failover=off,netdev=hs0,mac="MAC_STANDBY0" " 36693262464SLaurent Vivier "-netdev user,id=hs1 " 36793262464SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 36893262464SLaurent Vivier "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0, 36993262464SLaurent Vivier 2); 37093262464SLaurent Vivier 37193262464SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 37293262464SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 37393262464SLaurent Vivier 37493262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", false); 37593262464SLaurent Vivier 37693262464SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 37793262464SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 37893262464SLaurent Vivier 37993262464SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 38093262464SLaurent Vivier machine_stop(qts); 38193262464SLaurent Vivier } 38293262464SLaurent Vivier 383e32b96b5SLaurent Vivier static void test_enabled(void) 384e32b96b5SLaurent Vivier { 385e32b96b5SLaurent Vivier QTestState *qts; 386e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 387e32b96b5SLaurent Vivier 388e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 389e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 390e32b96b5SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 391e32b96b5SLaurent Vivier "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 392e32b96b5SLaurent Vivier "-netdev user,id=hs1 " 393e32b96b5SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 394e32b96b5SLaurent Vivier "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 395e32b96b5SLaurent Vivier 2); 396e32b96b5SLaurent Vivier 397e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 398e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 399e32b96b5SLaurent Vivier 40093262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 401e32b96b5SLaurent Vivier 402e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 403e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 404e32b96b5SLaurent Vivier 405e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 406e32b96b5SLaurent Vivier machine_stop(qts); 407e32b96b5SLaurent Vivier } 408e32b96b5SLaurent Vivier 40978475083SLaurent Vivier static void test_guest_off(void) 41078475083SLaurent Vivier { 41178475083SLaurent Vivier QTestState *qts; 41278475083SLaurent Vivier QVirtioPCIDevice *vdev; 41378475083SLaurent Vivier uint64_t features; 41478475083SLaurent Vivier 41578475083SLaurent Vivier qts = machine_start(BASE_MACHINE 41678475083SLaurent Vivier "-netdev user,id=hs0 " 41778475083SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 41878475083SLaurent Vivier "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 41978475083SLaurent Vivier "-netdev user,id=hs1 " 42078475083SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 42178475083SLaurent Vivier "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 42278475083SLaurent Vivier 2); 42378475083SLaurent Vivier 42478475083SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 42578475083SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 42678475083SLaurent Vivier 42778475083SLaurent Vivier features = ~(QVIRTIO_F_BAD_FEATURE | 42878475083SLaurent Vivier (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 42978475083SLaurent Vivier (1ull << VIRTIO_RING_F_EVENT_IDX) | 43078475083SLaurent Vivier (1ull << VIRTIO_NET_F_STANDBY)); 43178475083SLaurent Vivier 43278475083SLaurent Vivier vdev = start_virtio_net_internal(qts, 1, 0, &features); 43378475083SLaurent Vivier 43478475083SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 43578475083SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 43678475083SLaurent Vivier 43778475083SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 43878475083SLaurent Vivier machine_stop(qts); 43978475083SLaurent Vivier } 44078475083SLaurent Vivier 441e32b96b5SLaurent Vivier static void test_hotplug_1(void) 442e32b96b5SLaurent Vivier { 443e32b96b5SLaurent Vivier QTestState *qts; 444e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 445e32b96b5SLaurent Vivier 446e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 447e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 448e32b96b5SLaurent Vivier "-device virtio-net,bus=root0,id=standby0," 449e32b96b5SLaurent Vivier "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 450e32b96b5SLaurent Vivier "-netdev user,id=hs1 ", 2); 451e32b96b5SLaurent Vivier 452e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 453e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 454e32b96b5SLaurent Vivier 45593262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 456e32b96b5SLaurent Vivier 457e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 458e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 459e32b96b5SLaurent Vivier 460e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 461e32b96b5SLaurent Vivier "{'bus': 'root1'," 462e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'," 463e32b96b5SLaurent Vivier "'netdev': 'hs1'," 464e32b96b5SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 465e32b96b5SLaurent Vivier 466e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 467e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 468e32b96b5SLaurent Vivier 469e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 470e32b96b5SLaurent Vivier machine_stop(qts); 471e32b96b5SLaurent Vivier } 472e32b96b5SLaurent Vivier 473e32b96b5SLaurent Vivier static void test_hotplug_1_reverse(void) 474e32b96b5SLaurent Vivier { 475e32b96b5SLaurent Vivier QTestState *qts; 476e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 477e32b96b5SLaurent Vivier 478e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 479e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 480e32b96b5SLaurent Vivier "-netdev user,id=hs1 " 481e32b96b5SLaurent Vivier "-device virtio-net,bus=root1,id=primary0," 482e32b96b5SLaurent Vivier "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 483e32b96b5SLaurent Vivier 2); 484e32b96b5SLaurent Vivier 485e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 486e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 487e32b96b5SLaurent Vivier 488e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 489e32b96b5SLaurent Vivier "{'bus': 'root0'," 490b0193288SDaniel P. Berrangé "'failover': true," 491e32b96b5SLaurent Vivier "'netdev': 'hs0'," 492e32b96b5SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 493e32b96b5SLaurent Vivier 494e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 495e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 496e32b96b5SLaurent Vivier 49793262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 498e32b96b5SLaurent Vivier 499e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 500e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 501e32b96b5SLaurent Vivier 502e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 503e32b96b5SLaurent Vivier machine_stop(qts); 504e32b96b5SLaurent Vivier } 505e32b96b5SLaurent Vivier 506e32b96b5SLaurent Vivier static void test_hotplug_2(void) 507e32b96b5SLaurent Vivier { 508e32b96b5SLaurent Vivier QTestState *qts; 509e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 510e32b96b5SLaurent Vivier 511e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 512e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 513e32b96b5SLaurent Vivier "-netdev user,id=hs1 ", 514e32b96b5SLaurent Vivier 2); 515e32b96b5SLaurent Vivier 516e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 517e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 518e32b96b5SLaurent Vivier 519e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 520e32b96b5SLaurent Vivier "{'bus': 'root0'," 521b0193288SDaniel P. Berrangé "'failover': true," 522e32b96b5SLaurent Vivier "'netdev': 'hs0'," 523e32b96b5SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 524e32b96b5SLaurent Vivier 525e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 526e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 527e32b96b5SLaurent Vivier 52893262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 529e32b96b5SLaurent Vivier 530e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 531e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 532e32b96b5SLaurent Vivier 533e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 534e32b96b5SLaurent Vivier "{'bus': 'root1'," 535e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'," 536e32b96b5SLaurent Vivier "'netdev': 'hs1'," 537e32b96b5SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 538e32b96b5SLaurent Vivier 539e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 540e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 541e32b96b5SLaurent Vivier 542e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 543e32b96b5SLaurent Vivier machine_stop(qts); 544e32b96b5SLaurent Vivier } 545e32b96b5SLaurent Vivier 546e32b96b5SLaurent Vivier static void test_hotplug_2_reverse(void) 547e32b96b5SLaurent Vivier { 548e32b96b5SLaurent Vivier QTestState *qts; 549e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 550e32b96b5SLaurent Vivier 551e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 552e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 553e32b96b5SLaurent Vivier "-netdev user,id=hs1 ", 554e32b96b5SLaurent Vivier 2); 555e32b96b5SLaurent Vivier 556e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 557e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 558e32b96b5SLaurent Vivier 559e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 560e32b96b5SLaurent Vivier "{'bus': 'root1'," 561e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'," 562e32b96b5SLaurent Vivier "'netdev': 'hs1'," 563e32b96b5SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 564e32b96b5SLaurent Vivier 565e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 566e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 567e32b96b5SLaurent Vivier 568e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 569e32b96b5SLaurent Vivier "{'bus': 'root0'," 570b0193288SDaniel P. Berrangé "'failover': true," 571e32b96b5SLaurent Vivier "'netdev': 'hs0'," 572e32b96b5SLaurent Vivier "'rombar': 0," 573e32b96b5SLaurent Vivier "'romfile': ''," 574e32b96b5SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 575e32b96b5SLaurent Vivier 576e32b96b5SLaurent Vivier /* 577e32b96b5SLaurent Vivier * XXX: sounds like a bug: 578e32b96b5SLaurent Vivier * The primary should be hidden until the virtio-net driver 579e32b96b5SLaurent Vivier * negotiates the VIRTIO_NET_F_STANDBY feature by start_virtio_net() 580e32b96b5SLaurent Vivier */ 581e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 582e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 583e32b96b5SLaurent Vivier 58493262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 585e32b96b5SLaurent Vivier 586e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 587e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 588e32b96b5SLaurent Vivier 589e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 590e32b96b5SLaurent Vivier machine_stop(qts); 591e32b96b5SLaurent Vivier } 592e32b96b5SLaurent Vivier 593a6866706SXuzhou Cheng #ifndef _WIN32 594e32b96b5SLaurent Vivier static QDict *migrate_status(QTestState *qts) 595e32b96b5SLaurent Vivier { 596e32b96b5SLaurent Vivier QDict *resp, *ret; 597e32b96b5SLaurent Vivier 598e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'query-migrate' }"); 599e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 600e32b96b5SLaurent Vivier 601e32b96b5SLaurent Vivier ret = qdict_get_qdict(resp, "return"); 602e32b96b5SLaurent Vivier g_assert(qdict_haskey(ret, "status")); 603e32b96b5SLaurent Vivier qobject_ref(ret); 604e32b96b5SLaurent Vivier qobject_unref(resp); 605e32b96b5SLaurent Vivier 606e32b96b5SLaurent Vivier return ret; 607e32b96b5SLaurent Vivier } 608e32b96b5SLaurent Vivier 609e32b96b5SLaurent Vivier static QDict *get_unplug_primary_event(QTestState *qts) 610e32b96b5SLaurent Vivier { 611e32b96b5SLaurent Vivier QDict *resp; 612e32b96b5SLaurent Vivier QDict *data; 613e32b96b5SLaurent Vivier 614e32b96b5SLaurent Vivier resp = qtest_qmp_eventwait_ref(qts, "UNPLUG_PRIMARY"); 615e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "data")); 616e32b96b5SLaurent Vivier 617e32b96b5SLaurent Vivier data = qdict_get_qdict(resp, "data"); 618e32b96b5SLaurent Vivier g_assert(qdict_haskey(data, "device-id")); 619e32b96b5SLaurent Vivier qobject_ref(data); 620e32b96b5SLaurent Vivier qobject_unref(resp); 621e32b96b5SLaurent Vivier 622e32b96b5SLaurent Vivier return data; 623e32b96b5SLaurent Vivier } 624e32b96b5SLaurent Vivier 625e32b96b5SLaurent Vivier static void test_migrate_out(gconstpointer opaque) 626e32b96b5SLaurent Vivier { 627e32b96b5SLaurent Vivier QTestState *qts; 628e32b96b5SLaurent Vivier QDict *resp, *args, *ret; 629e32b96b5SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 630e32b96b5SLaurent Vivier const gchar *status; 631e32b96b5SLaurent Vivier QVirtioPCIDevice *vdev; 632e32b96b5SLaurent Vivier 633e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 634e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 635e32b96b5SLaurent Vivier "-netdev user,id=hs1 ", 636e32b96b5SLaurent Vivier 2); 637e32b96b5SLaurent Vivier 638e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 639e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 640e32b96b5SLaurent Vivier 641e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 642e32b96b5SLaurent Vivier "{'bus': 'root0'," 643b0193288SDaniel P. Berrangé "'failover': true," 644e32b96b5SLaurent Vivier "'netdev': 'hs0'," 645e32b96b5SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 646e32b96b5SLaurent Vivier 647e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 648e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 649e32b96b5SLaurent Vivier 65093262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 651e32b96b5SLaurent Vivier 652e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 653e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 654e32b96b5SLaurent Vivier 655e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 656e32b96b5SLaurent Vivier "{'bus': 'root1'," 657e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'," 658e32b96b5SLaurent Vivier "'netdev': 'hs1'," 659e32b96b5SLaurent Vivier "'rombar': 0," 660e32b96b5SLaurent Vivier "'romfile': ''," 661e32b96b5SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 662e32b96b5SLaurent Vivier 663e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 664e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 665e32b96b5SLaurent Vivier 666e32b96b5SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 667e32b96b5SLaurent Vivier g_assert_nonnull(args); 668e32b96b5SLaurent Vivier qdict_put_str(args, "uri", uri); 669e32b96b5SLaurent Vivier 670e32b96b5SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 671e32b96b5SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 672e32b96b5SLaurent Vivier qobject_unref(resp); 673e32b96b5SLaurent Vivier 674e32b96b5SLaurent Vivier /* the event is sent when QEMU asks the OS to unplug the card */ 675e32b96b5SLaurent Vivier resp = get_unplug_primary_event(qts); 676e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 677e32b96b5SLaurent Vivier qobject_unref(resp); 678e32b96b5SLaurent Vivier 679e32b96b5SLaurent Vivier /* wait the end of the migration setup phase */ 680e32b96b5SLaurent Vivier while (true) { 681e32b96b5SLaurent Vivier ret = migrate_status(qts); 682e32b96b5SLaurent Vivier 683e32b96b5SLaurent Vivier status = qdict_get_str(ret, "status"); 684e32b96b5SLaurent Vivier if (strcmp(status, "wait-unplug") == 0) { 685e32b96b5SLaurent Vivier qobject_unref(ret); 686e32b96b5SLaurent Vivier break; 687e32b96b5SLaurent Vivier } 688e32b96b5SLaurent Vivier 689e32b96b5SLaurent Vivier /* The migration must not start if the card is not ejected */ 690e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "active"); 691e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "completed"); 692e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 693e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 694e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 695e32b96b5SLaurent Vivier 696e32b96b5SLaurent Vivier qobject_unref(ret); 697e32b96b5SLaurent Vivier } 698e32b96b5SLaurent Vivier 699e32b96b5SLaurent Vivier if (g_test_slow()) { 700e32b96b5SLaurent Vivier /* check we stay in wait-unplug while the card is not ejected */ 701e32b96b5SLaurent Vivier for (int i = 0; i < 5; i++) { 702e32b96b5SLaurent Vivier sleep(1); 703e32b96b5SLaurent Vivier ret = migrate_status(qts); 704e32b96b5SLaurent Vivier status = qdict_get_str(ret, "status"); 705e32b96b5SLaurent Vivier g_assert_cmpstr(status, ==, "wait-unplug"); 706e32b96b5SLaurent Vivier qobject_unref(ret); 707e32b96b5SLaurent Vivier } 708e32b96b5SLaurent Vivier } 709e32b96b5SLaurent Vivier 710e32b96b5SLaurent Vivier /* OS unplugs the cards, QEMU can move from wait-unplug state */ 711e32b96b5SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 712e32b96b5SLaurent Vivier 713e32b96b5SLaurent Vivier while (true) { 714e32b96b5SLaurent Vivier ret = migrate_status(qts); 715e32b96b5SLaurent Vivier 716e32b96b5SLaurent Vivier status = qdict_get_str(ret, "status"); 717e32b96b5SLaurent Vivier if (strcmp(status, "completed") == 0) { 718e32b96b5SLaurent Vivier qobject_unref(ret); 719e32b96b5SLaurent Vivier break; 720e32b96b5SLaurent Vivier } 721e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 722e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 723e32b96b5SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 724e32b96b5SLaurent Vivier qobject_unref(ret); 725e32b96b5SLaurent Vivier } 726e32b96b5SLaurent Vivier 727e32b96b5SLaurent Vivier qtest_qmp_eventwait(qts, "STOP"); 728e32b96b5SLaurent Vivier 729e32b96b5SLaurent Vivier /* 730e32b96b5SLaurent Vivier * in fact, the card is ejected from the point of view of kernel 731e32b96b5SLaurent Vivier * but not really from QEMU to be able to hotplug it back if 732e32b96b5SLaurent Vivier * migration fails. So we can't check that: 733e32b96b5SLaurent Vivier * check_one_card(qts, true, "standby0", MAC_STANDBY0); 734e32b96b5SLaurent Vivier * check_one_card(qts, false, "primary0", MAC_PRIMARY0); 735e32b96b5SLaurent Vivier */ 736e32b96b5SLaurent Vivier 737e32b96b5SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 738e32b96b5SLaurent Vivier machine_stop(qts); 739e32b96b5SLaurent Vivier } 740e32b96b5SLaurent Vivier 741e32b96b5SLaurent Vivier static void test_migrate_in(gconstpointer opaque) 742e32b96b5SLaurent Vivier { 743e32b96b5SLaurent Vivier QTestState *qts; 7446830e53bSFabiano Rosas QDict *resp, *ret; 745e32b96b5SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 746e32b96b5SLaurent Vivier 747e32b96b5SLaurent Vivier qts = machine_start(BASE_MACHINE 748e32b96b5SLaurent Vivier "-netdev user,id=hs0 " 749e32b96b5SLaurent Vivier "-netdev user,id=hs1 " 750e32b96b5SLaurent Vivier "-incoming defer ", 751e32b96b5SLaurent Vivier 2); 752e32b96b5SLaurent Vivier 753e32b96b5SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 754e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 755e32b96b5SLaurent Vivier 756e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 757e32b96b5SLaurent Vivier "{'bus': 'root0'," 758b0193288SDaniel P. Berrangé "'failover': true," 759e32b96b5SLaurent Vivier "'netdev': 'hs0'," 760e32b96b5SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 761e32b96b5SLaurent Vivier 762e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 763e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 764e32b96b5SLaurent Vivier 765e32b96b5SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 766e32b96b5SLaurent Vivier "{'bus': 'root1'," 767e32b96b5SLaurent Vivier "'failover_pair_id': 'standby0'," 768e32b96b5SLaurent Vivier "'netdev': 'hs1'," 769e32b96b5SLaurent Vivier "'rombar': 0," 770e32b96b5SLaurent Vivier "'romfile': ''," 771e32b96b5SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 772e32b96b5SLaurent Vivier 773e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 774e32b96b5SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 775e32b96b5SLaurent Vivier 7766830e53bSFabiano Rosas migrate_incoming_qmp(qts, uri, "{}"); 777e32b96b5SLaurent Vivier 778e32b96b5SLaurent Vivier resp = get_failover_negociated_event(qts); 779e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 780e32b96b5SLaurent Vivier qobject_unref(resp); 781e32b96b5SLaurent Vivier 782e32b96b5SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 783e32b96b5SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 784e32b96b5SLaurent Vivier 785e32b96b5SLaurent Vivier qtest_qmp_eventwait(qts, "RESUME"); 786e32b96b5SLaurent Vivier 787e32b96b5SLaurent Vivier ret = migrate_status(qts); 788e32b96b5SLaurent Vivier g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 789e32b96b5SLaurent Vivier qobject_unref(ret); 790e32b96b5SLaurent Vivier 791e32b96b5SLaurent Vivier machine_stop(qts); 792e32b96b5SLaurent Vivier } 793e32b96b5SLaurent Vivier 7947f998491SLaurent Vivier static void test_off_migrate_out(gconstpointer opaque) 7957f998491SLaurent Vivier { 7967f998491SLaurent Vivier QTestState *qts; 7977f998491SLaurent Vivier QDict *resp, *args, *ret; 7987f998491SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 7997f998491SLaurent Vivier const gchar *status; 8007f998491SLaurent Vivier QVirtioPCIDevice *vdev; 8017f998491SLaurent Vivier 8027f998491SLaurent Vivier qts = machine_start(BASE_MACHINE 8037f998491SLaurent Vivier "-netdev user,id=hs0 " 8047f998491SLaurent Vivier "-netdev user,id=hs1 ", 8057f998491SLaurent Vivier 2); 8067f998491SLaurent Vivier 8077f998491SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 8087f998491SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 8097f998491SLaurent Vivier 8107f998491SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 8117f998491SLaurent Vivier "{'bus': 'root0'," 812b0193288SDaniel P. Berrangé "'failover': false," 8137f998491SLaurent Vivier "'netdev': 'hs0'," 8147f998491SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 8157f998491SLaurent Vivier 8167f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 8177f998491SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 8187f998491SLaurent Vivier 8197f998491SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 8207f998491SLaurent Vivier "{'bus': 'root1'," 8217f998491SLaurent Vivier "'failover_pair_id': 'standby0'," 8227f998491SLaurent Vivier "'netdev': 'hs1'," 8237f998491SLaurent Vivier "'rombar': 0," 8247f998491SLaurent Vivier "'romfile': ''," 8257f998491SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 8267f998491SLaurent Vivier 8277f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 8287f998491SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 8297f998491SLaurent Vivier 8307f998491SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", false); 8317f998491SLaurent Vivier 8327f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 8337f998491SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 8347f998491SLaurent Vivier 8357f998491SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 8367f998491SLaurent Vivier g_assert_nonnull(args); 8377f998491SLaurent Vivier qdict_put_str(args, "uri", uri); 8387f998491SLaurent Vivier 8397f998491SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 8407f998491SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 8417f998491SLaurent Vivier qobject_unref(resp); 8427f998491SLaurent Vivier 8437f998491SLaurent Vivier while (true) { 8447f998491SLaurent Vivier ret = migrate_status(qts); 8457f998491SLaurent Vivier 8467f998491SLaurent Vivier status = qdict_get_str(ret, "status"); 8477f998491SLaurent Vivier if (strcmp(status, "completed") == 0) { 8487f998491SLaurent Vivier qobject_unref(ret); 8497f998491SLaurent Vivier break; 8507f998491SLaurent Vivier } 8517f998491SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 8527f998491SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 8537f998491SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 8547f998491SLaurent Vivier qobject_unref(ret); 8557f998491SLaurent Vivier } 8567f998491SLaurent Vivier 8577f998491SLaurent Vivier qtest_qmp_eventwait(qts, "STOP"); 8587f998491SLaurent Vivier 8597f998491SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 8607f998491SLaurent Vivier machine_stop(qts); 8617f998491SLaurent Vivier } 8627f998491SLaurent Vivier 8637f998491SLaurent Vivier static void test_off_migrate_in(gconstpointer opaque) 8647f998491SLaurent Vivier { 8657f998491SLaurent Vivier QTestState *qts; 8666830e53bSFabiano Rosas QDict *ret; 8677f998491SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 8687f998491SLaurent Vivier 8697f998491SLaurent Vivier qts = machine_start(BASE_MACHINE 8707f998491SLaurent Vivier "-netdev user,id=hs0 " 8717f998491SLaurent Vivier "-netdev user,id=hs1 " 8727f998491SLaurent Vivier "-incoming defer ", 8737f998491SLaurent Vivier 2); 8747f998491SLaurent Vivier 8757f998491SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 8767f998491SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 8777f998491SLaurent Vivier 8787f998491SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 8797f998491SLaurent Vivier "{'bus': 'root0'," 880b0193288SDaniel P. Berrangé "'failover': false," 8817f998491SLaurent Vivier "'netdev': 'hs0'," 8827f998491SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 8837f998491SLaurent Vivier 8847f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 8857f998491SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 8867f998491SLaurent Vivier 8877f998491SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 8887f998491SLaurent Vivier "{'bus': 'root1'," 8897f998491SLaurent Vivier "'failover_pair_id': 'standby0'," 8907f998491SLaurent Vivier "'netdev': 'hs1'," 8917f998491SLaurent Vivier "'rombar': 0," 8927f998491SLaurent Vivier "'romfile': ''," 8937f998491SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 8947f998491SLaurent Vivier 8957f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 8967f998491SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 8977f998491SLaurent Vivier 8986830e53bSFabiano Rosas migrate_incoming_qmp(qts, uri, "{}"); 8997f998491SLaurent Vivier 9007f998491SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 9017f998491SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 9027f998491SLaurent Vivier 9037f998491SLaurent Vivier qtest_qmp_eventwait(qts, "RESUME"); 9047f998491SLaurent Vivier 9057f998491SLaurent Vivier ret = migrate_status(qts); 9067f998491SLaurent Vivier g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 9077f998491SLaurent Vivier qobject_unref(ret); 9087f998491SLaurent Vivier 9097f998491SLaurent Vivier machine_stop(qts); 9107f998491SLaurent Vivier } 9117f998491SLaurent Vivier 912d9872c00SLaurent Vivier static void test_guest_off_migrate_out(gconstpointer opaque) 913d9872c00SLaurent Vivier { 914d9872c00SLaurent Vivier QTestState *qts; 915d9872c00SLaurent Vivier QDict *resp, *args, *ret; 916d9872c00SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 917d9872c00SLaurent Vivier const gchar *status; 918d9872c00SLaurent Vivier QVirtioPCIDevice *vdev; 919d9872c00SLaurent Vivier uint64_t features; 920d9872c00SLaurent Vivier 921d9872c00SLaurent Vivier qts = machine_start(BASE_MACHINE 922d9872c00SLaurent Vivier "-netdev user,id=hs0 " 923d9872c00SLaurent Vivier "-netdev user,id=hs1 ", 924d9872c00SLaurent Vivier 2); 925d9872c00SLaurent Vivier 926d9872c00SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 927d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 928d9872c00SLaurent Vivier 929d9872c00SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 930d9872c00SLaurent Vivier "{'bus': 'root0'," 931b0193288SDaniel P. Berrangé "'failover': true," 932d9872c00SLaurent Vivier "'netdev': 'hs0'," 933d9872c00SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 934d9872c00SLaurent Vivier 935d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 936d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 937d9872c00SLaurent Vivier 938d9872c00SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 939d9872c00SLaurent Vivier "{'bus': 'root1'," 940d9872c00SLaurent Vivier "'failover_pair_id': 'standby0'," 941d9872c00SLaurent Vivier "'netdev': 'hs1'," 942d9872c00SLaurent Vivier "'rombar': 0," 943d9872c00SLaurent Vivier "'romfile': ''," 944d9872c00SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 945d9872c00SLaurent Vivier 946d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 947d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 948d9872c00SLaurent Vivier 949d9872c00SLaurent Vivier features = ~(QVIRTIO_F_BAD_FEATURE | 950d9872c00SLaurent Vivier (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 951d9872c00SLaurent Vivier (1ull << VIRTIO_RING_F_EVENT_IDX) | 952d9872c00SLaurent Vivier (1ull << VIRTIO_NET_F_STANDBY)); 953d9872c00SLaurent Vivier 954d9872c00SLaurent Vivier vdev = start_virtio_net_internal(qts, 1, 0, &features); 955d9872c00SLaurent Vivier 956d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 957d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 958d9872c00SLaurent Vivier 959d9872c00SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 960d9872c00SLaurent Vivier g_assert_nonnull(args); 961d9872c00SLaurent Vivier qdict_put_str(args, "uri", uri); 962d9872c00SLaurent Vivier 963d9872c00SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 964d9872c00SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 965d9872c00SLaurent Vivier qobject_unref(resp); 966d9872c00SLaurent Vivier 967d9872c00SLaurent Vivier while (true) { 968d9872c00SLaurent Vivier ret = migrate_status(qts); 969d9872c00SLaurent Vivier 970d9872c00SLaurent Vivier status = qdict_get_str(ret, "status"); 971d9872c00SLaurent Vivier if (strcmp(status, "completed") == 0) { 972d9872c00SLaurent Vivier qobject_unref(ret); 973d9872c00SLaurent Vivier break; 974d9872c00SLaurent Vivier } 975d9872c00SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 976d9872c00SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 977d9872c00SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 978d9872c00SLaurent Vivier qobject_unref(ret); 979d9872c00SLaurent Vivier } 980d9872c00SLaurent Vivier 981d9872c00SLaurent Vivier qtest_qmp_eventwait(qts, "STOP"); 982d9872c00SLaurent Vivier 983d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 984d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 985d9872c00SLaurent Vivier 986d9872c00SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 987d9872c00SLaurent Vivier machine_stop(qts); 988d9872c00SLaurent Vivier } 989d9872c00SLaurent Vivier 990d9872c00SLaurent Vivier static void test_guest_off_migrate_in(gconstpointer opaque) 991d9872c00SLaurent Vivier { 992d9872c00SLaurent Vivier QTestState *qts; 9936830e53bSFabiano Rosas QDict *ret; 994d9872c00SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 995d9872c00SLaurent Vivier 996d9872c00SLaurent Vivier qts = machine_start(BASE_MACHINE 997d9872c00SLaurent Vivier "-netdev user,id=hs0 " 998d9872c00SLaurent Vivier "-netdev user,id=hs1 " 999d9872c00SLaurent Vivier "-incoming defer ", 1000d9872c00SLaurent Vivier 2); 1001d9872c00SLaurent Vivier 1002d9872c00SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 1003d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1004d9872c00SLaurent Vivier 1005d9872c00SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 1006d9872c00SLaurent Vivier "{'bus': 'root0'," 1007b0193288SDaniel P. Berrangé "'failover': true," 1008d9872c00SLaurent Vivier "'netdev': 'hs0'," 1009d9872c00SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 1010d9872c00SLaurent Vivier 1011d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1012d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1013d9872c00SLaurent Vivier 1014d9872c00SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 1015d9872c00SLaurent Vivier "{'bus': 'root1'," 1016d9872c00SLaurent Vivier "'failover_pair_id': 'standby0'," 1017d9872c00SLaurent Vivier "'netdev': 'hs1'," 1018d9872c00SLaurent Vivier "'rombar': 0," 1019d9872c00SLaurent Vivier "'romfile': ''," 1020d9872c00SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 1021d9872c00SLaurent Vivier 1022d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1023d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1024d9872c00SLaurent Vivier 10256830e53bSFabiano Rosas migrate_incoming_qmp(qts, uri, "{}"); 1026d9872c00SLaurent Vivier 1027d9872c00SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1028d9872c00SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1029d9872c00SLaurent Vivier 1030d9872c00SLaurent Vivier qtest_qmp_eventwait(qts, "RESUME"); 1031d9872c00SLaurent Vivier 1032d9872c00SLaurent Vivier ret = migrate_status(qts); 1033d9872c00SLaurent Vivier g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1034d9872c00SLaurent Vivier qobject_unref(ret); 1035d9872c00SLaurent Vivier 1036d9872c00SLaurent Vivier machine_stop(qts); 1037d9872c00SLaurent Vivier } 1038d9872c00SLaurent Vivier 1039e20977b7SLaurent Vivier static void test_migrate_guest_off_abort(gconstpointer opaque) 1040e20977b7SLaurent Vivier { 1041e20977b7SLaurent Vivier QTestState *qts; 1042e20977b7SLaurent Vivier QDict *resp, *args, *ret; 1043e20977b7SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1044e20977b7SLaurent Vivier const gchar *status; 1045e20977b7SLaurent Vivier QVirtioPCIDevice *vdev; 1046e20977b7SLaurent Vivier uint64_t features; 1047e20977b7SLaurent Vivier 1048e20977b7SLaurent Vivier qts = machine_start(BASE_MACHINE 1049e20977b7SLaurent Vivier "-netdev user,id=hs0 " 1050e20977b7SLaurent Vivier "-netdev user,id=hs1 ", 1051e20977b7SLaurent Vivier 2); 1052e20977b7SLaurent Vivier 1053e20977b7SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 1054e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1055e20977b7SLaurent Vivier 1056e20977b7SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 1057e20977b7SLaurent Vivier "{'bus': 'root0'," 1058b0193288SDaniel P. Berrangé "'failover': true," 1059e20977b7SLaurent Vivier "'netdev': 'hs0'," 1060e20977b7SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 1061e20977b7SLaurent Vivier 1062e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1063e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1064e20977b7SLaurent Vivier 1065e20977b7SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 1066e20977b7SLaurent Vivier "{'bus': 'root1'," 1067e20977b7SLaurent Vivier "'failover_pair_id': 'standby0'," 1068e20977b7SLaurent Vivier "'netdev': 'hs1'," 1069e20977b7SLaurent Vivier "'rombar': 0," 1070e20977b7SLaurent Vivier "'romfile': ''," 1071e20977b7SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 1072e20977b7SLaurent Vivier 1073e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1074e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1075e20977b7SLaurent Vivier 1076e20977b7SLaurent Vivier features = ~(QVIRTIO_F_BAD_FEATURE | 1077e20977b7SLaurent Vivier (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 1078e20977b7SLaurent Vivier (1ull << VIRTIO_RING_F_EVENT_IDX) | 1079e20977b7SLaurent Vivier (1ull << VIRTIO_NET_F_STANDBY)); 1080e20977b7SLaurent Vivier 1081e20977b7SLaurent Vivier vdev = start_virtio_net_internal(qts, 1, 0, &features); 1082e20977b7SLaurent Vivier 1083e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1084e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1085e20977b7SLaurent Vivier 1086e20977b7SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 1087e20977b7SLaurent Vivier g_assert_nonnull(args); 1088e20977b7SLaurent Vivier qdict_put_str(args, "uri", uri); 1089e20977b7SLaurent Vivier 1090e20977b7SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1091e20977b7SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 1092e20977b7SLaurent Vivier qobject_unref(resp); 1093e20977b7SLaurent Vivier 1094e20977b7SLaurent Vivier while (true) { 1095e20977b7SLaurent Vivier ret = migrate_status(qts); 1096e20977b7SLaurent Vivier 1097e20977b7SLaurent Vivier status = qdict_get_str(ret, "status"); 10986ae6a30cSLaurent Vivier if (strcmp(status, "completed") == 0) { 10996ae6a30cSLaurent Vivier g_test_skip("Failed to cancel the migration"); 11006ae6a30cSLaurent Vivier qobject_unref(ret); 11016ae6a30cSLaurent Vivier goto out; 11026ae6a30cSLaurent Vivier } 1103e20977b7SLaurent Vivier if (strcmp(status, "active") == 0) { 1104e20977b7SLaurent Vivier qobject_unref(ret); 1105e20977b7SLaurent Vivier break; 1106e20977b7SLaurent Vivier } 1107e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1108e20977b7SLaurent Vivier qobject_unref(ret); 1109e20977b7SLaurent Vivier } 1110e20977b7SLaurent Vivier 1111e20977b7SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1112e20977b7SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 1113e20977b7SLaurent Vivier qobject_unref(resp); 1114e20977b7SLaurent Vivier 1115e20977b7SLaurent Vivier while (true) { 1116e20977b7SLaurent Vivier ret = migrate_status(qts); 1117e20977b7SLaurent Vivier status = qdict_get_str(ret, "status"); 11186ae6a30cSLaurent Vivier if (strcmp(status, "completed") == 0) { 11196ae6a30cSLaurent Vivier g_test_skip("Failed to cancel the migration"); 11206ae6a30cSLaurent Vivier qobject_unref(ret); 11216ae6a30cSLaurent Vivier goto out; 11226ae6a30cSLaurent Vivier } 1123e20977b7SLaurent Vivier if (strcmp(status, "cancelled") == 0) { 1124e20977b7SLaurent Vivier qobject_unref(ret); 1125e20977b7SLaurent Vivier break; 1126e20977b7SLaurent Vivier } 1127e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1128e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "active"); 1129e20977b7SLaurent Vivier qobject_unref(ret); 1130e20977b7SLaurent Vivier } 1131e20977b7SLaurent Vivier 1132e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1133e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1134e20977b7SLaurent Vivier 11356ae6a30cSLaurent Vivier out: 1136e20977b7SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 1137e20977b7SLaurent Vivier machine_stop(qts); 1138e20977b7SLaurent Vivier } 1139e20977b7SLaurent Vivier 11401e2077e2SLaurent Vivier static void test_migrate_abort_wait_unplug(gconstpointer opaque) 11411e2077e2SLaurent Vivier { 11421e2077e2SLaurent Vivier QTestState *qts; 11431e2077e2SLaurent Vivier QDict *resp, *args, *ret; 11441e2077e2SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 11451e2077e2SLaurent Vivier const gchar *status; 11461e2077e2SLaurent Vivier QVirtioPCIDevice *vdev; 11471e2077e2SLaurent Vivier 11481e2077e2SLaurent Vivier qts = machine_start(BASE_MACHINE 11491e2077e2SLaurent Vivier "-netdev user,id=hs0 " 11501e2077e2SLaurent Vivier "-netdev user,id=hs1 ", 11511e2077e2SLaurent Vivier 2); 11521e2077e2SLaurent Vivier 11531e2077e2SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 11541e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 11551e2077e2SLaurent Vivier 11561e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 11571e2077e2SLaurent Vivier "{'bus': 'root0'," 1158b0193288SDaniel P. Berrangé "'failover': true," 11591e2077e2SLaurent Vivier "'netdev': 'hs0'," 11601e2077e2SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 11611e2077e2SLaurent Vivier 11621e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 11631e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 11641e2077e2SLaurent Vivier 116593262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 11661e2077e2SLaurent Vivier 11671e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 11681e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 11691e2077e2SLaurent Vivier 11701e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 11711e2077e2SLaurent Vivier "{'bus': 'root1'," 11721e2077e2SLaurent Vivier "'failover_pair_id': 'standby0'," 11731e2077e2SLaurent Vivier "'netdev': 'hs1'," 11741e2077e2SLaurent Vivier "'rombar': 0," 11751e2077e2SLaurent Vivier "'romfile': ''," 11761e2077e2SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 11771e2077e2SLaurent Vivier 11781e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 11791e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 11801e2077e2SLaurent Vivier 11811e2077e2SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 11821e2077e2SLaurent Vivier g_assert_nonnull(args); 11831e2077e2SLaurent Vivier qdict_put_str(args, "uri", uri); 11841e2077e2SLaurent Vivier 11851e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 11861e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 11871e2077e2SLaurent Vivier qobject_unref(resp); 11881e2077e2SLaurent Vivier 11891e2077e2SLaurent Vivier /* the event is sent when QEMU asks the OS to unplug the card */ 11901e2077e2SLaurent Vivier resp = get_unplug_primary_event(qts); 11911e2077e2SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 11921e2077e2SLaurent Vivier qobject_unref(resp); 11931e2077e2SLaurent Vivier 11941e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 11951e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 11961e2077e2SLaurent Vivier qobject_unref(resp); 11971e2077e2SLaurent Vivier 11981e2077e2SLaurent Vivier /* migration has been cancelled while the unplug was in progress */ 11991e2077e2SLaurent Vivier 12001e2077e2SLaurent Vivier /* while the card is not ejected, we must be in "cancelling" state */ 12011e2077e2SLaurent Vivier ret = migrate_status(qts); 12021e2077e2SLaurent Vivier 12031e2077e2SLaurent Vivier status = qdict_get_str(ret, "status"); 12041e2077e2SLaurent Vivier g_assert_cmpstr(status, ==, "cancelling"); 12051e2077e2SLaurent Vivier qobject_unref(ret); 12061e2077e2SLaurent Vivier 12071e2077e2SLaurent Vivier /* OS unplugs the cards, QEMU can move from wait-unplug state */ 12081e2077e2SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 12091e2077e2SLaurent Vivier 12101e2077e2SLaurent Vivier while (true) { 12111e2077e2SLaurent Vivier ret = migrate_status(qts); 12121e2077e2SLaurent Vivier 12131e2077e2SLaurent Vivier status = qdict_get_str(ret, "status"); 12141e2077e2SLaurent Vivier if (strcmp(status, "cancelled") == 0) { 12151e2077e2SLaurent Vivier qobject_unref(ret); 12161e2077e2SLaurent Vivier break; 12171e2077e2SLaurent Vivier } 12186ae6a30cSLaurent Vivier g_assert_cmpstr(status, ==, "cancelling"); 12191e2077e2SLaurent Vivier qobject_unref(ret); 12201e2077e2SLaurent Vivier } 12211e2077e2SLaurent Vivier 12221e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 12231e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 12241e2077e2SLaurent Vivier 12251e2077e2SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 12261e2077e2SLaurent Vivier machine_stop(qts); 12271e2077e2SLaurent Vivier } 12281e2077e2SLaurent Vivier 12291e2077e2SLaurent Vivier static void test_migrate_abort_active(gconstpointer opaque) 12301e2077e2SLaurent Vivier { 12311e2077e2SLaurent Vivier QTestState *qts; 12321e2077e2SLaurent Vivier QDict *resp, *args, *ret; 12331e2077e2SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 12341e2077e2SLaurent Vivier const gchar *status; 12351e2077e2SLaurent Vivier QVirtioPCIDevice *vdev; 12361e2077e2SLaurent Vivier 12371e2077e2SLaurent Vivier qts = machine_start(BASE_MACHINE 12381e2077e2SLaurent Vivier "-netdev user,id=hs0 " 12391e2077e2SLaurent Vivier "-netdev user,id=hs1 ", 12401e2077e2SLaurent Vivier 2); 12411e2077e2SLaurent Vivier 12421e2077e2SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 12431e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 12441e2077e2SLaurent Vivier 12451e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 12461e2077e2SLaurent Vivier "{'bus': 'root0'," 1247b0193288SDaniel P. Berrangé "'failover': true," 12481e2077e2SLaurent Vivier "'netdev': 'hs0'," 12491e2077e2SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 12501e2077e2SLaurent Vivier 12511e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 12521e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 12531e2077e2SLaurent Vivier 125493262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 12551e2077e2SLaurent Vivier 12561e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 12571e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 12581e2077e2SLaurent Vivier 12591e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 12601e2077e2SLaurent Vivier "{'bus': 'root1'," 12611e2077e2SLaurent Vivier "'failover_pair_id': 'standby0'," 12621e2077e2SLaurent Vivier "'netdev': 'hs1'," 12631e2077e2SLaurent Vivier "'rombar': 0," 12641e2077e2SLaurent Vivier "'romfile': ''," 12651e2077e2SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 12661e2077e2SLaurent Vivier 12671e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 12681e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 12691e2077e2SLaurent Vivier 12701e2077e2SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 12711e2077e2SLaurent Vivier g_assert_nonnull(args); 12721e2077e2SLaurent Vivier qdict_put_str(args, "uri", uri); 12731e2077e2SLaurent Vivier 12741e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 12751e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 12761e2077e2SLaurent Vivier qobject_unref(resp); 12771e2077e2SLaurent Vivier 12781e2077e2SLaurent Vivier /* the event is sent when QEMU asks the OS to unplug the card */ 12791e2077e2SLaurent Vivier resp = get_unplug_primary_event(qts); 12801e2077e2SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 12811e2077e2SLaurent Vivier qobject_unref(resp); 12821e2077e2SLaurent Vivier 12831e2077e2SLaurent Vivier /* OS unplugs the cards, QEMU can move from wait-unplug state */ 12841e2077e2SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 12851e2077e2SLaurent Vivier 12861e2077e2SLaurent Vivier while (true) { 12871e2077e2SLaurent Vivier ret = migrate_status(qts); 12881e2077e2SLaurent Vivier 12891e2077e2SLaurent Vivier status = qdict_get_str(ret, "status"); 12906ae6a30cSLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 12911e2077e2SLaurent Vivier if (strcmp(status, "wait-unplug") != 0) { 12921e2077e2SLaurent Vivier qobject_unref(ret); 12931e2077e2SLaurent Vivier break; 12941e2077e2SLaurent Vivier } 12951e2077e2SLaurent Vivier qobject_unref(ret); 12961e2077e2SLaurent Vivier } 12971e2077e2SLaurent Vivier 12981e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 12991e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 13001e2077e2SLaurent Vivier qobject_unref(resp); 13011e2077e2SLaurent Vivier 13021e2077e2SLaurent Vivier while (true) { 13031e2077e2SLaurent Vivier ret = migrate_status(qts); 13041e2077e2SLaurent Vivier 13051e2077e2SLaurent Vivier status = qdict_get_str(ret, "status"); 13066ae6a30cSLaurent Vivier if (strcmp(status, "completed") == 0) { 13076ae6a30cSLaurent Vivier g_test_skip("Failed to cancel the migration"); 13086ae6a30cSLaurent Vivier qobject_unref(ret); 13096ae6a30cSLaurent Vivier goto out; 13106ae6a30cSLaurent Vivier } 13111e2077e2SLaurent Vivier if (strcmp(status, "cancelled") == 0) { 13121e2077e2SLaurent Vivier qobject_unref(ret); 13131e2077e2SLaurent Vivier break; 13141e2077e2SLaurent Vivier } 13151e2077e2SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 13161e2077e2SLaurent Vivier g_assert_cmpstr(status, !=, "active"); 13171e2077e2SLaurent Vivier qobject_unref(ret); 13181e2077e2SLaurent Vivier } 13191e2077e2SLaurent Vivier 13201e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 13211e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 13221e2077e2SLaurent Vivier 13236ae6a30cSLaurent Vivier out: 13241e2077e2SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 13251e2077e2SLaurent Vivier machine_stop(qts); 13261e2077e2SLaurent Vivier } 13271e2077e2SLaurent Vivier 1328e20977b7SLaurent Vivier static void test_migrate_off_abort(gconstpointer opaque) 1329e20977b7SLaurent Vivier { 1330e20977b7SLaurent Vivier QTestState *qts; 1331e20977b7SLaurent Vivier QDict *resp, *args, *ret; 1332e20977b7SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1333e20977b7SLaurent Vivier const gchar *status; 1334e20977b7SLaurent Vivier QVirtioPCIDevice *vdev; 1335e20977b7SLaurent Vivier 1336e20977b7SLaurent Vivier qts = machine_start(BASE_MACHINE 1337e20977b7SLaurent Vivier "-netdev user,id=hs0 " 1338e20977b7SLaurent Vivier "-netdev user,id=hs1 ", 1339e20977b7SLaurent Vivier 2); 1340e20977b7SLaurent Vivier 1341e20977b7SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 1342e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1343e20977b7SLaurent Vivier 1344e20977b7SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 1345e20977b7SLaurent Vivier "{'bus': 'root0'," 1346b0193288SDaniel P. Berrangé "'failover': false," 1347e20977b7SLaurent Vivier "'netdev': 'hs0'," 1348e20977b7SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 1349e20977b7SLaurent Vivier 1350e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1351e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1352e20977b7SLaurent Vivier 1353e20977b7SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", false); 1354e20977b7SLaurent Vivier 1355e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1356e20977b7SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1357e20977b7SLaurent Vivier 1358e20977b7SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 1359e20977b7SLaurent Vivier "{'bus': 'root1'," 1360e20977b7SLaurent Vivier "'failover_pair_id': 'standby0'," 1361e20977b7SLaurent Vivier "'netdev': 'hs1'," 1362e20977b7SLaurent Vivier "'rombar': 0," 1363e20977b7SLaurent Vivier "'romfile': ''," 1364e20977b7SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 1365e20977b7SLaurent Vivier 1366e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1367e20977b7SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1368e20977b7SLaurent Vivier 1369e20977b7SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 1370e20977b7SLaurent Vivier g_assert_nonnull(args); 1371e20977b7SLaurent Vivier qdict_put_str(args, "uri", uri); 1372e20977b7SLaurent Vivier 1373e20977b7SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1374e20977b7SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 1375e20977b7SLaurent Vivier qobject_unref(resp); 1376e20977b7SLaurent Vivier 1377e20977b7SLaurent Vivier while (true) { 1378e20977b7SLaurent Vivier ret = migrate_status(qts); 1379e20977b7SLaurent Vivier 1380e20977b7SLaurent Vivier status = qdict_get_str(ret, "status"); 1381e20977b7SLaurent Vivier if (strcmp(status, "active") == 0) { 1382e20977b7SLaurent Vivier qobject_unref(ret); 1383e20977b7SLaurent Vivier break; 1384e20977b7SLaurent Vivier } 1385e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1386e20977b7SLaurent Vivier qobject_unref(ret); 1387e20977b7SLaurent Vivier } 1388e20977b7SLaurent Vivier 1389e20977b7SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1390e20977b7SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 1391e20977b7SLaurent Vivier qobject_unref(resp); 1392e20977b7SLaurent Vivier 1393e20977b7SLaurent Vivier while (true) { 1394e20977b7SLaurent Vivier ret = migrate_status(qts); 1395e20977b7SLaurent Vivier 1396e20977b7SLaurent Vivier status = qdict_get_str(ret, "status"); 13976ae6a30cSLaurent Vivier if (strcmp(status, "completed") == 0) { 13986ae6a30cSLaurent Vivier g_test_skip("Failed to cancel the migration"); 13996ae6a30cSLaurent Vivier qobject_unref(ret); 14006ae6a30cSLaurent Vivier goto out; 14016ae6a30cSLaurent Vivier } 1402e20977b7SLaurent Vivier if (strcmp(status, "cancelled") == 0) { 1403e20977b7SLaurent Vivier qobject_unref(ret); 1404e20977b7SLaurent Vivier break; 1405e20977b7SLaurent Vivier } 1406e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1407e20977b7SLaurent Vivier g_assert_cmpstr(status, !=, "active"); 1408e20977b7SLaurent Vivier qobject_unref(ret); 1409e20977b7SLaurent Vivier } 1410e20977b7SLaurent Vivier 1411e20977b7SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1412e20977b7SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1413e20977b7SLaurent Vivier 14146ae6a30cSLaurent Vivier out: 1415e20977b7SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 1416e20977b7SLaurent Vivier machine_stop(qts); 1417e20977b7SLaurent Vivier } 1418e20977b7SLaurent Vivier 14191e2077e2SLaurent Vivier static void test_migrate_abort_timeout(gconstpointer opaque) 14201e2077e2SLaurent Vivier { 14211e2077e2SLaurent Vivier QTestState *qts; 14221e2077e2SLaurent Vivier QDict *resp, *args, *ret; 14231e2077e2SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 14241e2077e2SLaurent Vivier const gchar *status; 14251e2077e2SLaurent Vivier int total; 14261e2077e2SLaurent Vivier QVirtioPCIDevice *vdev; 14271e2077e2SLaurent Vivier 14281e2077e2SLaurent Vivier qts = machine_start(BASE_MACHINE 14291e2077e2SLaurent Vivier "-netdev user,id=hs0 " 14301e2077e2SLaurent Vivier "-netdev user,id=hs1 ", 14311e2077e2SLaurent Vivier 2); 14321e2077e2SLaurent Vivier 14331e2077e2SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 14341e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 14351e2077e2SLaurent Vivier 14361e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 14371e2077e2SLaurent Vivier "{'bus': 'root0'," 1438b0193288SDaniel P. Berrangé "'failover': true," 14391e2077e2SLaurent Vivier "'netdev': 'hs0'," 14401e2077e2SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 14411e2077e2SLaurent Vivier 14421e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 14431e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 14441e2077e2SLaurent Vivier 144593262464SLaurent Vivier vdev = start_virtio_net(qts, 1, 0, "standby0", true); 14461e2077e2SLaurent Vivier 14471e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 14481e2077e2SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 14491e2077e2SLaurent Vivier 14501e2077e2SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 14511e2077e2SLaurent Vivier "{'bus': 'root1'," 14521e2077e2SLaurent Vivier "'failover_pair_id': 'standby0'," 14531e2077e2SLaurent Vivier "'netdev': 'hs1'," 14541e2077e2SLaurent Vivier "'rombar': 0," 14551e2077e2SLaurent Vivier "'romfile': ''," 14561e2077e2SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 14571e2077e2SLaurent Vivier 14581e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 14591e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 14601e2077e2SLaurent Vivier 14611e2077e2SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 14621e2077e2SLaurent Vivier g_assert_nonnull(args); 14631e2077e2SLaurent Vivier qdict_put_str(args, "uri", uri); 14641e2077e2SLaurent Vivier 14651e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 14661e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 14671e2077e2SLaurent Vivier qobject_unref(resp); 14681e2077e2SLaurent Vivier 14691e2077e2SLaurent Vivier /* the event is sent when QEMU asks the OS to unplug the card */ 14701e2077e2SLaurent Vivier resp = get_unplug_primary_event(qts); 14711e2077e2SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 14721e2077e2SLaurent Vivier qobject_unref(resp); 14731e2077e2SLaurent Vivier 14741e2077e2SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 14751e2077e2SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 14761e2077e2SLaurent Vivier qobject_unref(resp); 14771e2077e2SLaurent Vivier 14781e2077e2SLaurent Vivier /* migration has been cancelled while the unplug was in progress */ 14791e2077e2SLaurent Vivier 14801e2077e2SLaurent Vivier /* while the card is not ejected, we must be in "cancelling" state */ 14811e2077e2SLaurent Vivier 14821e2077e2SLaurent Vivier total = 0; 14831e2077e2SLaurent Vivier while (true) { 14841e2077e2SLaurent Vivier ret = migrate_status(qts); 14851e2077e2SLaurent Vivier 14861e2077e2SLaurent Vivier status = qdict_get_str(ret, "status"); 14871e2077e2SLaurent Vivier if (strcmp(status, "cancelled") == 0) { 14881e2077e2SLaurent Vivier qobject_unref(ret); 14891e2077e2SLaurent Vivier break; 14901e2077e2SLaurent Vivier } 14911e2077e2SLaurent Vivier g_assert_cmpstr(status, ==, "cancelling"); 14921e2077e2SLaurent Vivier g_assert(qdict_haskey(ret, "total-time")); 14931e2077e2SLaurent Vivier total = qdict_get_int(ret, "total-time"); 14941e2077e2SLaurent Vivier qobject_unref(ret); 14951e2077e2SLaurent Vivier } 14961e2077e2SLaurent Vivier 14971e2077e2SLaurent Vivier /* 14981e2077e2SLaurent Vivier * migration timeout in this case is 30 seconds 14991e2077e2SLaurent Vivier * check we exit on the timeout (ms) 15001e2077e2SLaurent Vivier */ 15011e2077e2SLaurent Vivier g_assert_cmpint(total, >, 30000); 15021e2077e2SLaurent Vivier 15031e2077e2SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 15041e2077e2SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 15051e2077e2SLaurent Vivier 15061e2077e2SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev); 15071e2077e2SLaurent Vivier machine_stop(qts); 15081e2077e2SLaurent Vivier } 15091e2077e2SLaurent Vivier 1510e1e3d321SLaurent Vivier static void test_multi_out(gconstpointer opaque) 1511e1e3d321SLaurent Vivier { 1512e1e3d321SLaurent Vivier QTestState *qts; 1513e1e3d321SLaurent Vivier QDict *resp, *args, *ret; 1514e1e3d321SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1515e1e3d321SLaurent Vivier const gchar *status, *expected; 1516e1e3d321SLaurent Vivier QVirtioPCIDevice *vdev0, *vdev1; 1517e1e3d321SLaurent Vivier 1518e1e3d321SLaurent Vivier qts = machine_start(BASE_MACHINE 1519e1e3d321SLaurent Vivier "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1520e1e3d321SLaurent Vivier "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1521e1e3d321SLaurent Vivier "-netdev user,id=hs0 " 1522e1e3d321SLaurent Vivier "-netdev user,id=hs1 " 1523e1e3d321SLaurent Vivier "-netdev user,id=hs2 " 1524e1e3d321SLaurent Vivier "-netdev user,id=hs3 ", 1525e1e3d321SLaurent Vivier 4); 1526e1e3d321SLaurent Vivier 1527e1e3d321SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 1528e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1529e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1530e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1531e1e3d321SLaurent Vivier 1532e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 1533e1e3d321SLaurent Vivier "{'bus': 'root0'," 1534b0193288SDaniel P. Berrangé "'failover': true," 1535e1e3d321SLaurent Vivier "'netdev': 'hs0'," 1536e1e3d321SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 1537e1e3d321SLaurent Vivier 1538e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1539e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1540e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1541e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1542e1e3d321SLaurent Vivier 1543e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 1544e1e3d321SLaurent Vivier "{'bus': 'root1'," 1545e1e3d321SLaurent Vivier "'failover_pair_id': 'standby0'," 1546e1e3d321SLaurent Vivier "'netdev': 'hs1'," 1547e1e3d321SLaurent Vivier "'rombar': 0," 1548e1e3d321SLaurent Vivier "'romfile': ''," 1549e1e3d321SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 1550e1e3d321SLaurent Vivier 1551e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1552e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1553e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1554e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1555e1e3d321SLaurent Vivier 155693262464SLaurent Vivier vdev0 = start_virtio_net(qts, 1, 0, "standby0", true); 1557e1e3d321SLaurent Vivier 1558e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1559e1e3d321SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1560e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1561e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1562e1e3d321SLaurent Vivier 1563e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby1", 1564e1e3d321SLaurent Vivier "{'bus': 'root2'," 1565b0193288SDaniel P. Berrangé "'failover': true," 1566e1e3d321SLaurent Vivier "'netdev': 'hs2'," 1567e1e3d321SLaurent Vivier "'mac': '"MAC_STANDBY1"'}"); 1568e1e3d321SLaurent Vivier 1569e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1570e1e3d321SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1571e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1572e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1573e1e3d321SLaurent Vivier 1574e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary1", 1575e1e3d321SLaurent Vivier "{'bus': 'root3'," 1576e1e3d321SLaurent Vivier "'failover_pair_id': 'standby1'," 1577e1e3d321SLaurent Vivier "'netdev': 'hs3'," 1578e1e3d321SLaurent Vivier "'rombar': 0," 1579e1e3d321SLaurent Vivier "'romfile': ''," 1580e1e3d321SLaurent Vivier "'mac': '"MAC_PRIMARY1"'}"); 1581e1e3d321SLaurent Vivier 1582e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1583e1e3d321SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1584e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1585e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1586e1e3d321SLaurent Vivier 158793262464SLaurent Vivier vdev1 = start_virtio_net(qts, 3, 0, "standby1", true); 1588e1e3d321SLaurent Vivier 1589e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1590e1e3d321SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1591e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1592e1e3d321SLaurent Vivier check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1593e1e3d321SLaurent Vivier 1594e1e3d321SLaurent Vivier args = qdict_from_jsonf_nofail("{}"); 1595e1e3d321SLaurent Vivier g_assert_nonnull(args); 1596e1e3d321SLaurent Vivier qdict_put_str(args, "uri", uri); 1597e1e3d321SLaurent Vivier 1598e1e3d321SLaurent Vivier resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1599e1e3d321SLaurent Vivier g_assert(qdict_haskey(resp, "return")); 1600e1e3d321SLaurent Vivier qobject_unref(resp); 1601e1e3d321SLaurent Vivier 1602e1e3d321SLaurent Vivier /* the event is sent when QEMU asks the OS to unplug the card */ 1603e1e3d321SLaurent Vivier resp = get_unplug_primary_event(qts); 1604e1e3d321SLaurent Vivier if (strcmp(qdict_get_str(resp, "device-id"), "primary0") == 0) { 1605e1e3d321SLaurent Vivier expected = "primary1"; 1606e1e3d321SLaurent Vivier } else if (strcmp(qdict_get_str(resp, "device-id"), "primary1") == 0) { 1607e1e3d321SLaurent Vivier expected = "primary0"; 1608e1e3d321SLaurent Vivier } else { 1609e1e3d321SLaurent Vivier g_assert_not_reached(); 1610e1e3d321SLaurent Vivier } 1611e1e3d321SLaurent Vivier qobject_unref(resp); 1612e1e3d321SLaurent Vivier 1613e1e3d321SLaurent Vivier resp = get_unplug_primary_event(qts); 1614e1e3d321SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, expected); 1615e1e3d321SLaurent Vivier qobject_unref(resp); 1616e1e3d321SLaurent Vivier 1617e1e3d321SLaurent Vivier /* wait the end of the migration setup phase */ 1618e1e3d321SLaurent Vivier while (true) { 1619e1e3d321SLaurent Vivier ret = migrate_status(qts); 1620e1e3d321SLaurent Vivier 1621e1e3d321SLaurent Vivier status = qdict_get_str(ret, "status"); 1622e1e3d321SLaurent Vivier if (strcmp(status, "wait-unplug") == 0) { 1623e1e3d321SLaurent Vivier qobject_unref(ret); 1624e1e3d321SLaurent Vivier break; 1625e1e3d321SLaurent Vivier } 1626e1e3d321SLaurent Vivier 1627e1e3d321SLaurent Vivier /* The migration must not start if the card is not ejected */ 1628e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "active"); 1629e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "completed"); 1630e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1631e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 1632e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 1633e1e3d321SLaurent Vivier 1634e1e3d321SLaurent Vivier qobject_unref(ret); 1635e1e3d321SLaurent Vivier } 1636e1e3d321SLaurent Vivier 1637e1e3d321SLaurent Vivier /* OS unplugs primary1, but we must wait the second */ 1638e1e3d321SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1639e1e3d321SLaurent Vivier 1640e1e3d321SLaurent Vivier ret = migrate_status(qts); 1641e1e3d321SLaurent Vivier status = qdict_get_str(ret, "status"); 1642e1e3d321SLaurent Vivier g_assert_cmpstr(status, ==, "wait-unplug"); 1643e1e3d321SLaurent Vivier qobject_unref(ret); 1644e1e3d321SLaurent Vivier 1645e1e3d321SLaurent Vivier if (g_test_slow()) { 1646e1e3d321SLaurent Vivier /* check we stay in wait-unplug while the card is not ejected */ 1647e1e3d321SLaurent Vivier for (int i = 0; i < 5; i++) { 1648e1e3d321SLaurent Vivier sleep(1); 1649e1e3d321SLaurent Vivier ret = migrate_status(qts); 1650e1e3d321SLaurent Vivier status = qdict_get_str(ret, "status"); 1651e1e3d321SLaurent Vivier g_assert_cmpstr(status, ==, "wait-unplug"); 1652e1e3d321SLaurent Vivier qobject_unref(ret); 1653e1e3d321SLaurent Vivier } 1654e1e3d321SLaurent Vivier } 1655e1e3d321SLaurent Vivier 1656e1e3d321SLaurent Vivier /* OS unplugs primary0, QEMU can move from wait-unplug state */ 1657e1e3d321SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_SEL_BASE, 2); 1658e1e3d321SLaurent Vivier qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1659e1e3d321SLaurent Vivier 1660e1e3d321SLaurent Vivier while (true) { 1661e1e3d321SLaurent Vivier ret = migrate_status(qts); 1662e1e3d321SLaurent Vivier 1663e1e3d321SLaurent Vivier status = qdict_get_str(ret, "status"); 1664e1e3d321SLaurent Vivier if (strcmp(status, "completed") == 0) { 1665e1e3d321SLaurent Vivier qobject_unref(ret); 1666e1e3d321SLaurent Vivier break; 1667e1e3d321SLaurent Vivier } 1668e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "failed"); 1669e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "cancelling"); 1670e1e3d321SLaurent Vivier g_assert_cmpstr(status, !=, "cancelled"); 1671e1e3d321SLaurent Vivier qobject_unref(ret); 1672e1e3d321SLaurent Vivier } 1673e1e3d321SLaurent Vivier 1674e1e3d321SLaurent Vivier qtest_qmp_eventwait(qts, "STOP"); 1675e1e3d321SLaurent Vivier 1676e1e3d321SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev0); 1677e1e3d321SLaurent Vivier qos_object_destroy((QOSGraphObject *)vdev1); 1678e1e3d321SLaurent Vivier machine_stop(qts); 1679e1e3d321SLaurent Vivier } 1680e1e3d321SLaurent Vivier 1681e1e3d321SLaurent Vivier static void test_multi_in(gconstpointer opaque) 1682e1e3d321SLaurent Vivier { 1683e1e3d321SLaurent Vivier QTestState *qts; 16846830e53bSFabiano Rosas QDict *resp, *ret; 1685e1e3d321SLaurent Vivier g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1686e1e3d321SLaurent Vivier 1687e1e3d321SLaurent Vivier qts = machine_start(BASE_MACHINE 1688e1e3d321SLaurent Vivier "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1689e1e3d321SLaurent Vivier "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1690e1e3d321SLaurent Vivier "-netdev user,id=hs0 " 1691e1e3d321SLaurent Vivier "-netdev user,id=hs1 " 1692e1e3d321SLaurent Vivier "-netdev user,id=hs2 " 1693e1e3d321SLaurent Vivier "-netdev user,id=hs3 " 1694e1e3d321SLaurent Vivier "-incoming defer ", 1695e1e3d321SLaurent Vivier 4); 1696e1e3d321SLaurent Vivier 1697e1e3d321SLaurent Vivier check_one_card(qts, false, "standby0", MAC_STANDBY0); 1698e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1699e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1700e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1701e1e3d321SLaurent Vivier 1702e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby0", 1703e1e3d321SLaurent Vivier "{'bus': 'root0'," 1704b0193288SDaniel P. Berrangé "'failover': true," 1705e1e3d321SLaurent Vivier "'netdev': 'hs0'," 1706e1e3d321SLaurent Vivier "'mac': '"MAC_STANDBY0"'}"); 1707e1e3d321SLaurent Vivier 1708e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1709e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1710e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1711e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1712e1e3d321SLaurent Vivier 1713e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary0", 1714e1e3d321SLaurent Vivier "{'bus': 'root1'," 1715e1e3d321SLaurent Vivier "'failover_pair_id': 'standby0'," 1716e1e3d321SLaurent Vivier "'netdev': 'hs1'," 1717e1e3d321SLaurent Vivier "'rombar': 0," 1718e1e3d321SLaurent Vivier "'romfile': ''," 1719e1e3d321SLaurent Vivier "'mac': '"MAC_PRIMARY0"'}"); 1720e1e3d321SLaurent Vivier 1721e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1722e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1723e1e3d321SLaurent Vivier check_one_card(qts, false, "standby1", MAC_STANDBY1); 1724e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1725e1e3d321SLaurent Vivier 1726e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "standby1", 1727e1e3d321SLaurent Vivier "{'bus': 'root2'," 1728b0193288SDaniel P. Berrangé "'failover': true," 1729e1e3d321SLaurent Vivier "'netdev': 'hs2'," 1730e1e3d321SLaurent Vivier "'mac': '"MAC_STANDBY1"'}"); 1731e1e3d321SLaurent Vivier 1732e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1733e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1734e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1735e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1736e1e3d321SLaurent Vivier 1737e1e3d321SLaurent Vivier qtest_qmp_device_add(qts, "virtio-net", "primary1", 1738e1e3d321SLaurent Vivier "{'bus': 'root3'," 1739e1e3d321SLaurent Vivier "'failover_pair_id': 'standby1'," 1740e1e3d321SLaurent Vivier "'netdev': 'hs3'," 1741e1e3d321SLaurent Vivier "'rombar': 0," 1742e1e3d321SLaurent Vivier "'romfile': ''," 1743e1e3d321SLaurent Vivier "'mac': '"MAC_PRIMARY1"'}"); 1744e1e3d321SLaurent Vivier 1745e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1746e1e3d321SLaurent Vivier check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1747e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1748e1e3d321SLaurent Vivier check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1749e1e3d321SLaurent Vivier 17506830e53bSFabiano Rosas migrate_incoming_qmp(qts, uri, "{}"); 1751e1e3d321SLaurent Vivier 1752e1e3d321SLaurent Vivier resp = get_failover_negociated_event(qts); 1753e1e3d321SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 1754e1e3d321SLaurent Vivier qobject_unref(resp); 1755e1e3d321SLaurent Vivier 1756e1e3d321SLaurent Vivier resp = get_failover_negociated_event(qts); 1757e1e3d321SLaurent Vivier g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby1"); 1758e1e3d321SLaurent Vivier qobject_unref(resp); 1759e1e3d321SLaurent Vivier 1760e1e3d321SLaurent Vivier check_one_card(qts, true, "standby0", MAC_STANDBY0); 1761e1e3d321SLaurent Vivier check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1762e1e3d321SLaurent Vivier check_one_card(qts, true, "standby1", MAC_STANDBY1); 1763e1e3d321SLaurent Vivier check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1764e1e3d321SLaurent Vivier 1765e1e3d321SLaurent Vivier qtest_qmp_eventwait(qts, "RESUME"); 1766e1e3d321SLaurent Vivier 1767e1e3d321SLaurent Vivier ret = migrate_status(qts); 1768e1e3d321SLaurent Vivier g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1769e1e3d321SLaurent Vivier qobject_unref(ret); 1770e1e3d321SLaurent Vivier 1771e1e3d321SLaurent Vivier machine_stop(qts); 1772e1e3d321SLaurent Vivier } 1773a6866706SXuzhou Cheng #endif /* _WIN32 */ 1774e1e3d321SLaurent Vivier 1775e32b96b5SLaurent Vivier int main(int argc, char **argv) 1776e32b96b5SLaurent Vivier { 1777e63ed64cSThomas Huth gchar *tmpfile; 1778e32b96b5SLaurent Vivier int ret; 1779e32b96b5SLaurent Vivier 1780e32b96b5SLaurent Vivier g_test_init(&argc, &argv, NULL); 1781e32b96b5SLaurent Vivier 1782e63ed64cSThomas Huth ret = g_file_open_tmp("failover_test_migrate-XXXXXX", &tmpfile, NULL); 1783e63ed64cSThomas Huth g_assert_true(ret >= 0); 1784e63ed64cSThomas Huth close(ret); 1785e63ed64cSThomas Huth 1786fbd2913cSLaurent Vivier /* parameters tests */ 1787e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/error/id", test_error_id); 1788e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/error/pcie", test_error_pcie); 1789e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/on", test_on); 1790e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/on_mismatch", 1791e32b96b5SLaurent Vivier test_on_mismatch); 1792e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/off", test_off); 1793e32b96b5SLaurent Vivier qtest_add_func("failover-virtio-net/params/enabled", test_enabled); 179478475083SLaurent Vivier qtest_add_func("failover-virtio-net/params/guest_off", test_guest_off); 1795fbd2913cSLaurent Vivier 1796fbd2913cSLaurent Vivier /* hotplug tests */ 1797fbd2913cSLaurent Vivier qtest_add_func("failover-virtio-net/hotplug/1", test_hotplug_1); 1798fbd2913cSLaurent Vivier qtest_add_func("failover-virtio-net/hotplug/1_reverse", 1799e32b96b5SLaurent Vivier test_hotplug_1_reverse); 1800fbd2913cSLaurent Vivier qtest_add_func("failover-virtio-net/hotplug/2", test_hotplug_2); 1801fbd2913cSLaurent Vivier qtest_add_func("failover-virtio-net/hotplug/2_reverse", 1802e32b96b5SLaurent Vivier test_hotplug_2_reverse); 1803fbd2913cSLaurent Vivier 1804a6866706SXuzhou Cheng #ifndef _WIN32 1805a6866706SXuzhou Cheng /* 1806a6866706SXuzhou Cheng * These migration tests cases use the exec migration protocol, 1807a6866706SXuzhou Cheng * which is unsupported on Windows. 1808a6866706SXuzhou Cheng */ 1809fbd2913cSLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/on/out", tmpfile, 1810e32b96b5SLaurent Vivier test_migrate_out); 1811fbd2913cSLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/on/in", tmpfile, 1812e32b96b5SLaurent Vivier test_migrate_in); 18137f998491SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/off/out", tmpfile, 18147f998491SLaurent Vivier test_off_migrate_out); 18157f998491SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/off/in", tmpfile, 18167f998491SLaurent Vivier test_off_migrate_in); 1817e20977b7SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/off/abort", tmpfile, 1818e20977b7SLaurent Vivier test_migrate_off_abort); 1819d9872c00SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/guest_off/out", tmpfile, 1820d9872c00SLaurent Vivier test_guest_off_migrate_out); 1821d9872c00SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/guest_off/in", tmpfile, 1822d9872c00SLaurent Vivier test_guest_off_migrate_in); 1823e20977b7SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/guest_off/abort", tmpfile, 1824e20977b7SLaurent Vivier test_migrate_guest_off_abort); 18251e2077e2SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/abort/wait-unplug", 18261e2077e2SLaurent Vivier tmpfile, test_migrate_abort_wait_unplug); 18271e2077e2SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/abort/active", tmpfile, 18281e2077e2SLaurent Vivier test_migrate_abort_active); 18291e2077e2SLaurent Vivier if (g_test_slow()) { 18301e2077e2SLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/abort/timeout", 18311e2077e2SLaurent Vivier tmpfile, test_migrate_abort_timeout); 18321e2077e2SLaurent Vivier } 1833fbd2913cSLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/multi/out", 1834e1e3d321SLaurent Vivier tmpfile, test_multi_out); 1835fbd2913cSLaurent Vivier qtest_add_data_func("failover-virtio-net/migrate/multi/in", 1836e1e3d321SLaurent Vivier tmpfile, test_multi_in); 1837a6866706SXuzhou Cheng #endif /* _WIN32 */ 1838e32b96b5SLaurent Vivier 1839e32b96b5SLaurent Vivier ret = g_test_run(); 1840e32b96b5SLaurent Vivier 1841e32b96b5SLaurent Vivier unlink(tmpfile); 1842e32b96b5SLaurent Vivier g_free(tmpfile); 1843e32b96b5SLaurent Vivier 1844e32b96b5SLaurent Vivier return ret; 1845e32b96b5SLaurent Vivier } 1846