1 /* 2 * QTest testcase for virtio-net failover 3 * 4 * See docs/system/virtio-net-failover.rst 5 * 6 * Copyright (c) 2021 Red Hat, Inc. 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 #include "qemu/osdep.h" 11 #include "libqtest.h" 12 #include "libqos/pci.h" 13 #include "libqos/pci-pc.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qlist.h" 16 #include "qapi/qmp/qjson.h" 17 #include "libqos/malloc-pc.h" 18 #include "libqos/virtio-pci.h" 19 #include "hw/pci/pci.h" 20 21 #define VIRTIO_NET_F_STANDBY 62 22 23 #define ACPI_PCIHP_ADDR_ICH9 0x0cc0 24 #define PCI_EJ_BASE 0x0008 25 #define PCI_SEL_BASE 0x0010 26 27 #define BASE_MACHINE "-M q35 -nodefaults " \ 28 "-device pcie-root-port,id=root0,addr=0x1,bus=pcie.0,chassis=1 " \ 29 "-device pcie-root-port,id=root1,addr=0x2,bus=pcie.0,chassis=2 " 30 31 #define MAC_PRIMARY0 "52:54:00:11:11:11" 32 #define MAC_STANDBY0 "52:54:00:22:22:22" 33 #define MAC_PRIMARY1 "52:54:00:33:33:33" 34 #define MAC_STANDBY1 "52:54:00:44:44:44" 35 36 static QGuestAllocator guest_malloc; 37 static QPCIBus *pcibus; 38 39 static QTestState *machine_start(const char *args, int numbus) 40 { 41 QTestState *qts; 42 QPCIDevice *dev; 43 int bus; 44 45 qts = qtest_init(args); 46 47 pc_alloc_init(&guest_malloc, qts, 0); 48 pcibus = qpci_new_pc(qts, &guest_malloc); 49 g_assert(qpci_secondary_buses_init(pcibus) == numbus); 50 51 for (bus = 1; bus <= numbus; bus++) { 52 dev = qpci_device_find(pcibus, QPCI_DEVFN(bus, 0)); 53 g_assert_nonnull(dev); 54 55 qpci_device_enable(dev); 56 qpci_iomap(dev, 4, NULL); 57 58 g_free(dev); 59 } 60 61 return qts; 62 } 63 64 static void machine_stop(QTestState *qts) 65 { 66 qpci_free_pc(pcibus); 67 alloc_destroy(&guest_malloc); 68 qtest_quit(qts); 69 } 70 71 static void test_error_id(void) 72 { 73 QTestState *qts; 74 QDict *resp; 75 QDict *err; 76 77 qts = machine_start(BASE_MACHINE 78 "-device virtio-net,bus=root0,id=standby0,failover=on", 79 2); 80 81 resp = qtest_qmp(qts, "{'execute': 'device_add'," 82 "'arguments': {" 83 "'driver': 'virtio-net'," 84 "'bus': 'root1'," 85 "'failover_pair_id': 'standby0'" 86 "} }"); 87 g_assert(qdict_haskey(resp, "error")); 88 89 err = qdict_get_qdict(resp, "error"); 90 g_assert(qdict_haskey(err, "desc")); 91 92 g_assert_cmpstr(qdict_get_str(err, "desc"), ==, 93 "Device with failover_pair_id needs to have id"); 94 95 qobject_unref(resp); 96 97 machine_stop(qts); 98 } 99 100 static void test_error_pcie(void) 101 { 102 QTestState *qts; 103 QDict *resp; 104 QDict *err; 105 106 qts = machine_start(BASE_MACHINE 107 "-device virtio-net,bus=root0,id=standby0,failover=on", 108 2); 109 110 resp = qtest_qmp(qts, "{'execute': 'device_add'," 111 "'arguments': {" 112 "'driver': 'virtio-net'," 113 "'id': 'primary0'," 114 "'bus': 'pcie.0'," 115 "'failover_pair_id': 'standby0'" 116 "} }"); 117 g_assert(qdict_haskey(resp, "error")); 118 119 err = qdict_get_qdict(resp, "error"); 120 g_assert(qdict_haskey(err, "desc")); 121 122 g_assert_cmpstr(qdict_get_str(err, "desc"), ==, 123 "Bus 'pcie.0' does not support hotplugging"); 124 125 qobject_unref(resp); 126 127 machine_stop(qts); 128 } 129 130 static QDict *find_device(QDict *bus, const char *name) 131 { 132 const QObject *obj; 133 QList *devices; 134 QList *list; 135 136 devices = qdict_get_qlist(bus, "devices"); 137 if (devices == NULL) { 138 return NULL; 139 } 140 141 list = qlist_copy(devices); 142 while ((obj = qlist_pop(list))) { 143 QDict *device; 144 145 device = qobject_to(QDict, obj); 146 147 if (qdict_haskey(device, "pci_bridge")) { 148 QDict *bridge; 149 QDict *bridge_device; 150 151 bridge = qdict_get_qdict(device, "pci_bridge"); 152 153 if (qdict_haskey(bridge, "devices")) { 154 bridge_device = find_device(bridge, name); 155 if (bridge_device) { 156 qobject_unref(device); 157 qobject_unref(list); 158 return bridge_device; 159 } 160 } 161 } 162 163 if (!qdict_haskey(device, "qdev_id")) { 164 qobject_unref(device); 165 continue; 166 } 167 168 if (strcmp(qdict_get_str(device, "qdev_id"), name) == 0) { 169 qobject_unref(list); 170 return device; 171 } 172 qobject_unref(device); 173 } 174 qobject_unref(list); 175 176 return NULL; 177 } 178 179 static QDict *get_bus(QTestState *qts, int num) 180 { 181 QObject *obj; 182 QDict *resp; 183 QList *ret; 184 185 resp = qtest_qmp(qts, "{ 'execute': 'query-pci' }"); 186 g_assert(qdict_haskey(resp, "return")); 187 188 ret = qdict_get_qlist(resp, "return"); 189 g_assert_nonnull(ret); 190 191 while ((obj = qlist_pop(ret))) { 192 QDict *bus; 193 194 bus = qobject_to(QDict, obj); 195 if (!qdict_haskey(bus, "bus")) { 196 qobject_unref(bus); 197 continue; 198 } 199 if (qdict_get_int(bus, "bus") == num) { 200 qobject_unref(resp); 201 return bus; 202 } 203 qobject_ref(bus); 204 } 205 qobject_unref(resp); 206 207 return NULL; 208 } 209 210 static char *get_mac(QTestState *qts, const char *name) 211 { 212 QDict *resp; 213 char *mac; 214 215 resp = qtest_qmp(qts, "{ 'execute': 'qom-get', " 216 "'arguments': { " 217 "'path': %s, " 218 "'property': 'mac' } }", name); 219 220 g_assert(qdict_haskey(resp, "return")); 221 222 mac = g_strdup(qdict_get_str(resp, "return")); 223 224 qobject_unref(resp); 225 226 return mac; 227 } 228 229 #define check_one_card(qts, present, id, mac) \ 230 do { \ 231 QDict *device; \ 232 QDict *bus; \ 233 char *addr; \ 234 bus = get_bus(qts, 0); \ 235 device = find_device(bus, id); \ 236 if (present) { \ 237 char *path; \ 238 g_assert_nonnull(device); \ 239 qobject_unref(device); \ 240 path = g_strdup_printf("/machine/peripheral/%s", id); \ 241 addr = get_mac(qts, path); \ 242 g_free(path); \ 243 g_assert_cmpstr(mac, ==, addr); \ 244 g_free(addr); \ 245 } else { \ 246 g_assert_null(device); \ 247 } \ 248 qobject_unref(bus); \ 249 } while (0) 250 251 static QDict *get_failover_negociated_event(QTestState *qts) 252 { 253 QDict *resp; 254 QDict *data; 255 256 resp = qtest_qmp_eventwait_ref(qts, "FAILOVER_NEGOTIATED"); 257 g_assert(qdict_haskey(resp, "data")); 258 259 data = qdict_get_qdict(resp, "data"); 260 g_assert(qdict_haskey(data, "device-id")); 261 qobject_ref(data); 262 qobject_unref(resp); 263 264 return data; 265 } 266 267 static QVirtioPCIDevice *start_virtio_net_internal(QTestState *qts, 268 int bus, int slot, 269 uint64_t *features) 270 { 271 QVirtioPCIDevice *dev; 272 QPCIAddress addr; 273 274 addr.devfn = QPCI_DEVFN((bus << 5) + slot, 0); 275 dev = virtio_pci_new(pcibus, &addr); 276 g_assert_nonnull(dev); 277 qvirtio_pci_device_enable(dev); 278 qvirtio_start_device(&dev->vdev); 279 *features &= qvirtio_get_features(&dev->vdev); 280 qvirtio_set_features(&dev->vdev, *features); 281 qvirtio_set_driver_ok(&dev->vdev); 282 return dev; 283 } 284 285 static QVirtioPCIDevice *start_virtio_net(QTestState *qts, int bus, int slot, 286 const char *id, bool failover) 287 { 288 QVirtioPCIDevice *dev; 289 uint64_t features; 290 291 features = ~(QVIRTIO_F_BAD_FEATURE | 292 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 293 (1ull << VIRTIO_RING_F_EVENT_IDX)); 294 295 dev = start_virtio_net_internal(qts, bus, slot, &features); 296 297 g_assert(!!(features & (1ull << VIRTIO_NET_F_STANDBY)) == failover); 298 299 if (failover) { 300 QDict *resp; 301 302 resp = get_failover_negociated_event(qts); 303 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, id); 304 qobject_unref(resp); 305 } 306 307 return dev; 308 } 309 310 static void test_on(void) 311 { 312 QTestState *qts; 313 314 qts = machine_start(BASE_MACHINE 315 "-netdev user,id=hs0 " 316 "-device virtio-net,bus=root0,id=standby0," 317 "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 318 "-netdev user,id=hs1 " 319 "-device virtio-net,bus=root1,id=primary0," 320 "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0, 321 2); 322 323 check_one_card(qts, true, "standby0", MAC_STANDBY0); 324 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 325 326 machine_stop(qts); 327 } 328 329 static void test_on_mismatch(void) 330 { 331 QTestState *qts; 332 QVirtioPCIDevice *vdev; 333 334 qts = machine_start(BASE_MACHINE 335 "-netdev user,id=hs0 " 336 "-device virtio-net,bus=root0,id=standby0," 337 "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 338 "-netdev user,id=hs1 " 339 "-device virtio-net,bus=root1,id=primary0," 340 "failover_pair_id=standby1,netdev=hs1,mac="MAC_PRIMARY0, 341 2); 342 343 check_one_card(qts, true, "standby0", MAC_STANDBY0); 344 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 345 346 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 347 348 check_one_card(qts, true, "standby0", MAC_STANDBY0); 349 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 350 351 qos_object_destroy((QOSGraphObject *)vdev); 352 machine_stop(qts); 353 } 354 355 static void test_off(void) 356 { 357 QTestState *qts; 358 QVirtioPCIDevice *vdev; 359 360 qts = machine_start(BASE_MACHINE 361 "-netdev user,id=hs0 " 362 "-device virtio-net,bus=root0,id=standby0," 363 "failover=off,netdev=hs0,mac="MAC_STANDBY0" " 364 "-netdev user,id=hs1 " 365 "-device virtio-net,bus=root1,id=primary0," 366 "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0, 367 2); 368 369 check_one_card(qts, true, "standby0", MAC_STANDBY0); 370 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 371 372 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 373 374 check_one_card(qts, true, "standby0", MAC_STANDBY0); 375 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 376 377 qos_object_destroy((QOSGraphObject *)vdev); 378 machine_stop(qts); 379 } 380 381 static void test_enabled(void) 382 { 383 QTestState *qts; 384 QVirtioPCIDevice *vdev; 385 386 qts = machine_start(BASE_MACHINE 387 "-netdev user,id=hs0 " 388 "-device virtio-net,bus=root0,id=standby0," 389 "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 390 "-netdev user,id=hs1 " 391 "-device virtio-net,bus=root1,id=primary0," 392 "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 393 2); 394 395 check_one_card(qts, true, "standby0", MAC_STANDBY0); 396 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 397 398 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 399 400 check_one_card(qts, true, "standby0", MAC_STANDBY0); 401 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 402 403 qos_object_destroy((QOSGraphObject *)vdev); 404 machine_stop(qts); 405 } 406 407 static void test_guest_off(void) 408 { 409 QTestState *qts; 410 QVirtioPCIDevice *vdev; 411 uint64_t features; 412 413 qts = machine_start(BASE_MACHINE 414 "-netdev user,id=hs0 " 415 "-device virtio-net,bus=root0,id=standby0," 416 "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 417 "-netdev user,id=hs1 " 418 "-device virtio-net,bus=root1,id=primary0," 419 "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 420 2); 421 422 check_one_card(qts, true, "standby0", MAC_STANDBY0); 423 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 424 425 features = ~(QVIRTIO_F_BAD_FEATURE | 426 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 427 (1ull << VIRTIO_RING_F_EVENT_IDX) | 428 (1ull << VIRTIO_NET_F_STANDBY)); 429 430 vdev = start_virtio_net_internal(qts, 1, 0, &features); 431 432 check_one_card(qts, true, "standby0", MAC_STANDBY0); 433 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 434 435 qos_object_destroy((QOSGraphObject *)vdev); 436 machine_stop(qts); 437 } 438 439 static void test_hotplug_1(void) 440 { 441 QTestState *qts; 442 QVirtioPCIDevice *vdev; 443 444 qts = machine_start(BASE_MACHINE 445 "-netdev user,id=hs0 " 446 "-device virtio-net,bus=root0,id=standby0," 447 "failover=on,netdev=hs0,mac="MAC_STANDBY0" " 448 "-netdev user,id=hs1 ", 2); 449 450 check_one_card(qts, true, "standby0", MAC_STANDBY0); 451 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 452 453 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 454 455 check_one_card(qts, true, "standby0", MAC_STANDBY0); 456 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 457 458 qtest_qmp_device_add(qts, "virtio-net", "primary0", 459 "{'bus': 'root1'," 460 "'failover_pair_id': 'standby0'," 461 "'netdev': 'hs1'," 462 "'mac': '"MAC_PRIMARY0"'}"); 463 464 check_one_card(qts, true, "standby0", MAC_STANDBY0); 465 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 466 467 qos_object_destroy((QOSGraphObject *)vdev); 468 machine_stop(qts); 469 } 470 471 static void test_hotplug_1_reverse(void) 472 { 473 QTestState *qts; 474 QVirtioPCIDevice *vdev; 475 476 qts = machine_start(BASE_MACHINE 477 "-netdev user,id=hs0 " 478 "-netdev user,id=hs1 " 479 "-device virtio-net,bus=root1,id=primary0," 480 "failover_pair_id=standby0,netdev=hs1,mac="MAC_PRIMARY0" ", 481 2); 482 483 check_one_card(qts, false, "standby0", MAC_STANDBY0); 484 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 485 486 qtest_qmp_device_add(qts, "virtio-net", "standby0", 487 "{'bus': 'root0'," 488 "'failover': 'on'," 489 "'netdev': 'hs0'," 490 "'mac': '"MAC_STANDBY0"'}"); 491 492 check_one_card(qts, true, "standby0", MAC_STANDBY0); 493 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 494 495 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 496 497 check_one_card(qts, true, "standby0", MAC_STANDBY0); 498 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 499 500 qos_object_destroy((QOSGraphObject *)vdev); 501 machine_stop(qts); 502 } 503 504 static void test_hotplug_2(void) 505 { 506 QTestState *qts; 507 QVirtioPCIDevice *vdev; 508 509 qts = machine_start(BASE_MACHINE 510 "-netdev user,id=hs0 " 511 "-netdev user,id=hs1 ", 512 2); 513 514 check_one_card(qts, false, "standby0", MAC_STANDBY0); 515 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 516 517 qtest_qmp_device_add(qts, "virtio-net", "standby0", 518 "{'bus': 'root0'," 519 "'failover': 'on'," 520 "'netdev': 'hs0'," 521 "'mac': '"MAC_STANDBY0"'}"); 522 523 check_one_card(qts, true, "standby0", MAC_STANDBY0); 524 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 525 526 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 527 528 check_one_card(qts, true, "standby0", MAC_STANDBY0); 529 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 530 531 qtest_qmp_device_add(qts, "virtio-net", "primary0", 532 "{'bus': 'root1'," 533 "'failover_pair_id': 'standby0'," 534 "'netdev': 'hs1'," 535 "'mac': '"MAC_PRIMARY0"'}"); 536 537 check_one_card(qts, true, "standby0", MAC_STANDBY0); 538 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 539 540 qos_object_destroy((QOSGraphObject *)vdev); 541 machine_stop(qts); 542 } 543 544 static void test_hotplug_2_reverse(void) 545 { 546 QTestState *qts; 547 QVirtioPCIDevice *vdev; 548 549 qts = machine_start(BASE_MACHINE 550 "-netdev user,id=hs0 " 551 "-netdev user,id=hs1 ", 552 2); 553 554 check_one_card(qts, false, "standby0", MAC_STANDBY0); 555 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 556 557 qtest_qmp_device_add(qts, "virtio-net", "primary0", 558 "{'bus': 'root1'," 559 "'failover_pair_id': 'standby0'," 560 "'netdev': 'hs1'," 561 "'mac': '"MAC_PRIMARY0"'}"); 562 563 check_one_card(qts, false, "standby0", MAC_STANDBY0); 564 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 565 566 qtest_qmp_device_add(qts, "virtio-net", "standby0", 567 "{'bus': 'root0'," 568 "'failover': 'on'," 569 "'netdev': 'hs0'," 570 "'rombar': 0," 571 "'romfile': ''," 572 "'mac': '"MAC_STANDBY0"'}"); 573 574 /* 575 * XXX: sounds like a bug: 576 * The primary should be hidden until the virtio-net driver 577 * negotiates the VIRTIO_NET_F_STANDBY feature by start_virtio_net() 578 */ 579 check_one_card(qts, true, "standby0", MAC_STANDBY0); 580 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 581 582 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 583 584 check_one_card(qts, true, "standby0", MAC_STANDBY0); 585 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 586 587 qos_object_destroy((QOSGraphObject *)vdev); 588 machine_stop(qts); 589 } 590 591 #ifndef _WIN32 592 static QDict *migrate_status(QTestState *qts) 593 { 594 QDict *resp, *ret; 595 596 resp = qtest_qmp(qts, "{ 'execute': 'query-migrate' }"); 597 g_assert(qdict_haskey(resp, "return")); 598 599 ret = qdict_get_qdict(resp, "return"); 600 g_assert(qdict_haskey(ret, "status")); 601 qobject_ref(ret); 602 qobject_unref(resp); 603 604 return ret; 605 } 606 607 static QDict *get_unplug_primary_event(QTestState *qts) 608 { 609 QDict *resp; 610 QDict *data; 611 612 resp = qtest_qmp_eventwait_ref(qts, "UNPLUG_PRIMARY"); 613 g_assert(qdict_haskey(resp, "data")); 614 615 data = qdict_get_qdict(resp, "data"); 616 g_assert(qdict_haskey(data, "device-id")); 617 qobject_ref(data); 618 qobject_unref(resp); 619 620 return data; 621 } 622 623 static void test_migrate_out(gconstpointer opaque) 624 { 625 QTestState *qts; 626 QDict *resp, *args, *ret; 627 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 628 const gchar *status; 629 QVirtioPCIDevice *vdev; 630 631 qts = machine_start(BASE_MACHINE 632 "-netdev user,id=hs0 " 633 "-netdev user,id=hs1 ", 634 2); 635 636 check_one_card(qts, false, "standby0", MAC_STANDBY0); 637 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 638 639 qtest_qmp_device_add(qts, "virtio-net", "standby0", 640 "{'bus': 'root0'," 641 "'failover': 'on'," 642 "'netdev': 'hs0'," 643 "'mac': '"MAC_STANDBY0"'}"); 644 645 check_one_card(qts, true, "standby0", MAC_STANDBY0); 646 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 647 648 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 649 650 check_one_card(qts, true, "standby0", MAC_STANDBY0); 651 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 652 653 qtest_qmp_device_add(qts, "virtio-net", "primary0", 654 "{'bus': 'root1'," 655 "'failover_pair_id': 'standby0'," 656 "'netdev': 'hs1'," 657 "'rombar': 0," 658 "'romfile': ''," 659 "'mac': '"MAC_PRIMARY0"'}"); 660 661 check_one_card(qts, true, "standby0", MAC_STANDBY0); 662 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 663 664 args = qdict_from_jsonf_nofail("{}"); 665 g_assert_nonnull(args); 666 qdict_put_str(args, "uri", uri); 667 668 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 669 g_assert(qdict_haskey(resp, "return")); 670 qobject_unref(resp); 671 672 /* the event is sent when QEMU asks the OS to unplug the card */ 673 resp = get_unplug_primary_event(qts); 674 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 675 qobject_unref(resp); 676 677 /* wait the end of the migration setup phase */ 678 while (true) { 679 ret = migrate_status(qts); 680 681 status = qdict_get_str(ret, "status"); 682 if (strcmp(status, "wait-unplug") == 0) { 683 qobject_unref(ret); 684 break; 685 } 686 687 /* The migration must not start if the card is not ejected */ 688 g_assert_cmpstr(status, !=, "active"); 689 g_assert_cmpstr(status, !=, "completed"); 690 g_assert_cmpstr(status, !=, "failed"); 691 g_assert_cmpstr(status, !=, "cancelling"); 692 g_assert_cmpstr(status, !=, "cancelled"); 693 694 qobject_unref(ret); 695 } 696 697 if (g_test_slow()) { 698 /* check we stay in wait-unplug while the card is not ejected */ 699 for (int i = 0; i < 5; i++) { 700 sleep(1); 701 ret = migrate_status(qts); 702 status = qdict_get_str(ret, "status"); 703 g_assert_cmpstr(status, ==, "wait-unplug"); 704 qobject_unref(ret); 705 } 706 } 707 708 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 709 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 710 711 while (true) { 712 ret = migrate_status(qts); 713 714 status = qdict_get_str(ret, "status"); 715 if (strcmp(status, "completed") == 0) { 716 qobject_unref(ret); 717 break; 718 } 719 g_assert_cmpstr(status, !=, "failed"); 720 g_assert_cmpstr(status, !=, "cancelling"); 721 g_assert_cmpstr(status, !=, "cancelled"); 722 qobject_unref(ret); 723 } 724 725 qtest_qmp_eventwait(qts, "STOP"); 726 727 /* 728 * in fact, the card is ejected from the point of view of kernel 729 * but not really from QEMU to be able to hotplug it back if 730 * migration fails. So we can't check that: 731 * check_one_card(qts, true, "standby0", MAC_STANDBY0); 732 * check_one_card(qts, false, "primary0", MAC_PRIMARY0); 733 */ 734 735 qos_object_destroy((QOSGraphObject *)vdev); 736 machine_stop(qts); 737 } 738 739 static QDict *get_migration_event(QTestState *qts) 740 { 741 QDict *resp; 742 QDict *data; 743 744 resp = qtest_qmp_eventwait_ref(qts, "MIGRATION"); 745 g_assert(qdict_haskey(resp, "data")); 746 747 data = qdict_get_qdict(resp, "data"); 748 g_assert(qdict_haskey(data, "status")); 749 qobject_ref(data); 750 qobject_unref(resp); 751 752 return data; 753 } 754 755 static void test_migrate_in(gconstpointer opaque) 756 { 757 QTestState *qts; 758 QDict *resp, *args, *ret; 759 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 760 761 qts = machine_start(BASE_MACHINE 762 "-netdev user,id=hs0 " 763 "-netdev user,id=hs1 " 764 "-incoming defer ", 765 2); 766 767 check_one_card(qts, false, "standby0", MAC_STANDBY0); 768 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 769 770 qtest_qmp_device_add(qts, "virtio-net", "standby0", 771 "{'bus': 'root0'," 772 "'failover': 'on'," 773 "'netdev': 'hs0'," 774 "'mac': '"MAC_STANDBY0"'}"); 775 776 check_one_card(qts, true, "standby0", MAC_STANDBY0); 777 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 778 779 qtest_qmp_device_add(qts, "virtio-net", "primary0", 780 "{'bus': 'root1'," 781 "'failover_pair_id': 'standby0'," 782 "'netdev': 'hs1'," 783 "'rombar': 0," 784 "'romfile': ''," 785 "'mac': '"MAC_PRIMARY0"'}"); 786 787 check_one_card(qts, true, "standby0", MAC_STANDBY0); 788 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 789 790 args = qdict_from_jsonf_nofail("{}"); 791 g_assert_nonnull(args); 792 qdict_put_str(args, "uri", uri); 793 794 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 795 args); 796 g_assert(qdict_haskey(resp, "return")); 797 qobject_unref(resp); 798 799 resp = get_migration_event(qts); 800 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 801 qobject_unref(resp); 802 803 resp = get_failover_negociated_event(qts); 804 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 805 qobject_unref(resp); 806 807 check_one_card(qts, true, "standby0", MAC_STANDBY0); 808 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 809 810 qtest_qmp_eventwait(qts, "RESUME"); 811 812 ret = migrate_status(qts); 813 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 814 qobject_unref(ret); 815 816 machine_stop(qts); 817 } 818 819 static void test_off_migrate_out(gconstpointer opaque) 820 { 821 QTestState *qts; 822 QDict *resp, *args, *ret; 823 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 824 const gchar *status; 825 QVirtioPCIDevice *vdev; 826 827 qts = machine_start(BASE_MACHINE 828 "-netdev user,id=hs0 " 829 "-netdev user,id=hs1 ", 830 2); 831 832 check_one_card(qts, false, "standby0", MAC_STANDBY0); 833 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 834 835 qtest_qmp_device_add(qts, "virtio-net", "standby0", 836 "{'bus': 'root0'," 837 "'failover': 'off'," 838 "'netdev': 'hs0'," 839 "'mac': '"MAC_STANDBY0"'}"); 840 841 check_one_card(qts, true, "standby0", MAC_STANDBY0); 842 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 843 844 qtest_qmp_device_add(qts, "virtio-net", "primary0", 845 "{'bus': 'root1'," 846 "'failover_pair_id': 'standby0'," 847 "'netdev': 'hs1'," 848 "'rombar': 0," 849 "'romfile': ''," 850 "'mac': '"MAC_PRIMARY0"'}"); 851 852 check_one_card(qts, true, "standby0", MAC_STANDBY0); 853 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 854 855 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 856 857 check_one_card(qts, true, "standby0", MAC_STANDBY0); 858 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 859 860 args = qdict_from_jsonf_nofail("{}"); 861 g_assert_nonnull(args); 862 qdict_put_str(args, "uri", uri); 863 864 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 865 g_assert(qdict_haskey(resp, "return")); 866 qobject_unref(resp); 867 868 while (true) { 869 ret = migrate_status(qts); 870 871 status = qdict_get_str(ret, "status"); 872 if (strcmp(status, "completed") == 0) { 873 qobject_unref(ret); 874 break; 875 } 876 g_assert_cmpstr(status, !=, "failed"); 877 g_assert_cmpstr(status, !=, "cancelling"); 878 g_assert_cmpstr(status, !=, "cancelled"); 879 qobject_unref(ret); 880 } 881 882 qtest_qmp_eventwait(qts, "STOP"); 883 884 qos_object_destroy((QOSGraphObject *)vdev); 885 machine_stop(qts); 886 } 887 888 static void test_off_migrate_in(gconstpointer opaque) 889 { 890 QTestState *qts; 891 QDict *resp, *args, *ret; 892 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 893 894 qts = machine_start(BASE_MACHINE 895 "-netdev user,id=hs0 " 896 "-netdev user,id=hs1 " 897 "-incoming defer ", 898 2); 899 900 check_one_card(qts, false, "standby0", MAC_STANDBY0); 901 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 902 903 qtest_qmp_device_add(qts, "virtio-net", "standby0", 904 "{'bus': 'root0'," 905 "'failover': 'off'," 906 "'netdev': 'hs0'," 907 "'mac': '"MAC_STANDBY0"'}"); 908 909 check_one_card(qts, true, "standby0", MAC_STANDBY0); 910 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 911 912 qtest_qmp_device_add(qts, "virtio-net", "primary0", 913 "{'bus': 'root1'," 914 "'failover_pair_id': 'standby0'," 915 "'netdev': 'hs1'," 916 "'rombar': 0," 917 "'romfile': ''," 918 "'mac': '"MAC_PRIMARY0"'}"); 919 920 check_one_card(qts, true, "standby0", MAC_STANDBY0); 921 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 922 923 args = qdict_from_jsonf_nofail("{}"); 924 g_assert_nonnull(args); 925 qdict_put_str(args, "uri", uri); 926 927 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 928 args); 929 g_assert(qdict_haskey(resp, "return")); 930 qobject_unref(resp); 931 932 resp = get_migration_event(qts); 933 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 934 qobject_unref(resp); 935 936 check_one_card(qts, true, "standby0", MAC_STANDBY0); 937 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 938 939 qtest_qmp_eventwait(qts, "RESUME"); 940 941 ret = migrate_status(qts); 942 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 943 qobject_unref(ret); 944 945 machine_stop(qts); 946 } 947 948 static void test_guest_off_migrate_out(gconstpointer opaque) 949 { 950 QTestState *qts; 951 QDict *resp, *args, *ret; 952 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 953 const gchar *status; 954 QVirtioPCIDevice *vdev; 955 uint64_t features; 956 957 qts = machine_start(BASE_MACHINE 958 "-netdev user,id=hs0 " 959 "-netdev user,id=hs1 ", 960 2); 961 962 check_one_card(qts, false, "standby0", MAC_STANDBY0); 963 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 964 965 qtest_qmp_device_add(qts, "virtio-net", "standby0", 966 "{'bus': 'root0'," 967 "'failover': 'on'," 968 "'netdev': 'hs0'," 969 "'mac': '"MAC_STANDBY0"'}"); 970 971 check_one_card(qts, true, "standby0", MAC_STANDBY0); 972 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 973 974 qtest_qmp_device_add(qts, "virtio-net", "primary0", 975 "{'bus': 'root1'," 976 "'failover_pair_id': 'standby0'," 977 "'netdev': 'hs1'," 978 "'rombar': 0," 979 "'romfile': ''," 980 "'mac': '"MAC_PRIMARY0"'}"); 981 982 check_one_card(qts, true, "standby0", MAC_STANDBY0); 983 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 984 985 features = ~(QVIRTIO_F_BAD_FEATURE | 986 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 987 (1ull << VIRTIO_RING_F_EVENT_IDX) | 988 (1ull << VIRTIO_NET_F_STANDBY)); 989 990 vdev = start_virtio_net_internal(qts, 1, 0, &features); 991 992 check_one_card(qts, true, "standby0", MAC_STANDBY0); 993 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 994 995 args = qdict_from_jsonf_nofail("{}"); 996 g_assert_nonnull(args); 997 qdict_put_str(args, "uri", uri); 998 999 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1000 g_assert(qdict_haskey(resp, "return")); 1001 qobject_unref(resp); 1002 1003 while (true) { 1004 ret = migrate_status(qts); 1005 1006 status = qdict_get_str(ret, "status"); 1007 if (strcmp(status, "completed") == 0) { 1008 qobject_unref(ret); 1009 break; 1010 } 1011 g_assert_cmpstr(status, !=, "failed"); 1012 g_assert_cmpstr(status, !=, "cancelling"); 1013 g_assert_cmpstr(status, !=, "cancelled"); 1014 qobject_unref(ret); 1015 } 1016 1017 qtest_qmp_eventwait(qts, "STOP"); 1018 1019 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1020 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1021 1022 qos_object_destroy((QOSGraphObject *)vdev); 1023 machine_stop(qts); 1024 } 1025 1026 static void test_guest_off_migrate_in(gconstpointer opaque) 1027 { 1028 QTestState *qts; 1029 QDict *resp, *args, *ret; 1030 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1031 1032 qts = machine_start(BASE_MACHINE 1033 "-netdev user,id=hs0 " 1034 "-netdev user,id=hs1 " 1035 "-incoming defer ", 1036 2); 1037 1038 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1039 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1040 1041 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1042 "{'bus': 'root0'," 1043 "'failover': 'on'," 1044 "'netdev': 'hs0'," 1045 "'mac': '"MAC_STANDBY0"'}"); 1046 1047 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1048 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1049 1050 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1051 "{'bus': 'root1'," 1052 "'failover_pair_id': 'standby0'," 1053 "'netdev': 'hs1'," 1054 "'rombar': 0," 1055 "'romfile': ''," 1056 "'mac': '"MAC_PRIMARY0"'}"); 1057 1058 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1059 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1060 1061 args = qdict_from_jsonf_nofail("{}"); 1062 g_assert_nonnull(args); 1063 qdict_put_str(args, "uri", uri); 1064 1065 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 1066 args); 1067 g_assert(qdict_haskey(resp, "return")); 1068 qobject_unref(resp); 1069 1070 resp = get_migration_event(qts); 1071 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 1072 qobject_unref(resp); 1073 1074 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1075 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1076 1077 qtest_qmp_eventwait(qts, "RESUME"); 1078 1079 ret = migrate_status(qts); 1080 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1081 qobject_unref(ret); 1082 1083 machine_stop(qts); 1084 } 1085 1086 static void test_migrate_guest_off_abort(gconstpointer opaque) 1087 { 1088 QTestState *qts; 1089 QDict *resp, *args, *ret; 1090 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1091 const gchar *status; 1092 QVirtioPCIDevice *vdev; 1093 uint64_t features; 1094 1095 qts = machine_start(BASE_MACHINE 1096 "-netdev user,id=hs0 " 1097 "-netdev user,id=hs1 ", 1098 2); 1099 1100 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1101 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1102 1103 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1104 "{'bus': 'root0'," 1105 "'failover': 'on'," 1106 "'netdev': 'hs0'," 1107 "'mac': '"MAC_STANDBY0"'}"); 1108 1109 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1110 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1111 1112 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1113 "{'bus': 'root1'," 1114 "'failover_pair_id': 'standby0'," 1115 "'netdev': 'hs1'," 1116 "'rombar': 0," 1117 "'romfile': ''," 1118 "'mac': '"MAC_PRIMARY0"'}"); 1119 1120 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1121 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1122 1123 features = ~(QVIRTIO_F_BAD_FEATURE | 1124 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 1125 (1ull << VIRTIO_RING_F_EVENT_IDX) | 1126 (1ull << VIRTIO_NET_F_STANDBY)); 1127 1128 vdev = start_virtio_net_internal(qts, 1, 0, &features); 1129 1130 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1131 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1132 1133 args = qdict_from_jsonf_nofail("{}"); 1134 g_assert_nonnull(args); 1135 qdict_put_str(args, "uri", uri); 1136 1137 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1138 g_assert(qdict_haskey(resp, "return")); 1139 qobject_unref(resp); 1140 1141 while (true) { 1142 ret = migrate_status(qts); 1143 1144 status = qdict_get_str(ret, "status"); 1145 if (strcmp(status, "completed") == 0) { 1146 g_test_skip("Failed to cancel the migration"); 1147 qobject_unref(ret); 1148 goto out; 1149 } 1150 if (strcmp(status, "active") == 0) { 1151 qobject_unref(ret); 1152 break; 1153 } 1154 g_assert_cmpstr(status, !=, "failed"); 1155 qobject_unref(ret); 1156 } 1157 1158 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1159 g_assert(qdict_haskey(resp, "return")); 1160 qobject_unref(resp); 1161 1162 while (true) { 1163 ret = migrate_status(qts); 1164 status = qdict_get_str(ret, "status"); 1165 if (strcmp(status, "completed") == 0) { 1166 g_test_skip("Failed to cancel the migration"); 1167 qobject_unref(ret); 1168 goto out; 1169 } 1170 if (strcmp(status, "cancelled") == 0) { 1171 qobject_unref(ret); 1172 break; 1173 } 1174 g_assert_cmpstr(status, !=, "failed"); 1175 g_assert_cmpstr(status, !=, "active"); 1176 qobject_unref(ret); 1177 } 1178 1179 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1180 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1181 1182 out: 1183 qos_object_destroy((QOSGraphObject *)vdev); 1184 machine_stop(qts); 1185 } 1186 1187 static void test_migrate_abort_wait_unplug(gconstpointer opaque) 1188 { 1189 QTestState *qts; 1190 QDict *resp, *args, *ret; 1191 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1192 const gchar *status; 1193 QVirtioPCIDevice *vdev; 1194 1195 qts = machine_start(BASE_MACHINE 1196 "-netdev user,id=hs0 " 1197 "-netdev user,id=hs1 ", 1198 2); 1199 1200 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1201 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1202 1203 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1204 "{'bus': 'root0'," 1205 "'failover': 'on'," 1206 "'netdev': 'hs0'," 1207 "'mac': '"MAC_STANDBY0"'}"); 1208 1209 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1210 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1211 1212 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1213 1214 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1215 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1216 1217 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1218 "{'bus': 'root1'," 1219 "'failover_pair_id': 'standby0'," 1220 "'netdev': 'hs1'," 1221 "'rombar': 0," 1222 "'romfile': ''," 1223 "'mac': '"MAC_PRIMARY0"'}"); 1224 1225 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1226 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1227 1228 args = qdict_from_jsonf_nofail("{}"); 1229 g_assert_nonnull(args); 1230 qdict_put_str(args, "uri", uri); 1231 1232 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1233 g_assert(qdict_haskey(resp, "return")); 1234 qobject_unref(resp); 1235 1236 /* the event is sent when QEMU asks the OS to unplug the card */ 1237 resp = get_unplug_primary_event(qts); 1238 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1239 qobject_unref(resp); 1240 1241 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1242 g_assert(qdict_haskey(resp, "return")); 1243 qobject_unref(resp); 1244 1245 /* migration has been cancelled while the unplug was in progress */ 1246 1247 /* while the card is not ejected, we must be in "cancelling" state */ 1248 ret = migrate_status(qts); 1249 1250 status = qdict_get_str(ret, "status"); 1251 g_assert_cmpstr(status, ==, "cancelling"); 1252 qobject_unref(ret); 1253 1254 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1255 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1256 1257 while (true) { 1258 ret = migrate_status(qts); 1259 1260 status = qdict_get_str(ret, "status"); 1261 if (strcmp(status, "cancelled") == 0) { 1262 qobject_unref(ret); 1263 break; 1264 } 1265 g_assert_cmpstr(status, ==, "cancelling"); 1266 qobject_unref(ret); 1267 } 1268 1269 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1270 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1271 1272 qos_object_destroy((QOSGraphObject *)vdev); 1273 machine_stop(qts); 1274 } 1275 1276 static void test_migrate_abort_active(gconstpointer opaque) 1277 { 1278 QTestState *qts; 1279 QDict *resp, *args, *ret; 1280 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1281 const gchar *status; 1282 QVirtioPCIDevice *vdev; 1283 1284 qts = machine_start(BASE_MACHINE 1285 "-netdev user,id=hs0 " 1286 "-netdev user,id=hs1 ", 1287 2); 1288 1289 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1290 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1291 1292 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1293 "{'bus': 'root0'," 1294 "'failover': 'on'," 1295 "'netdev': 'hs0'," 1296 "'mac': '"MAC_STANDBY0"'}"); 1297 1298 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1299 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1300 1301 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1302 1303 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1304 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1305 1306 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1307 "{'bus': 'root1'," 1308 "'failover_pair_id': 'standby0'," 1309 "'netdev': 'hs1'," 1310 "'rombar': 0," 1311 "'romfile': ''," 1312 "'mac': '"MAC_PRIMARY0"'}"); 1313 1314 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1315 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1316 1317 args = qdict_from_jsonf_nofail("{}"); 1318 g_assert_nonnull(args); 1319 qdict_put_str(args, "uri", uri); 1320 1321 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1322 g_assert(qdict_haskey(resp, "return")); 1323 qobject_unref(resp); 1324 1325 /* the event is sent when QEMU asks the OS to unplug the card */ 1326 resp = get_unplug_primary_event(qts); 1327 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1328 qobject_unref(resp); 1329 1330 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1331 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1332 1333 while (true) { 1334 ret = migrate_status(qts); 1335 1336 status = qdict_get_str(ret, "status"); 1337 g_assert_cmpstr(status, !=, "failed"); 1338 if (strcmp(status, "wait-unplug") != 0) { 1339 qobject_unref(ret); 1340 break; 1341 } 1342 qobject_unref(ret); 1343 } 1344 1345 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1346 g_assert(qdict_haskey(resp, "return")); 1347 qobject_unref(resp); 1348 1349 while (true) { 1350 ret = migrate_status(qts); 1351 1352 status = qdict_get_str(ret, "status"); 1353 if (strcmp(status, "completed") == 0) { 1354 g_test_skip("Failed to cancel the migration"); 1355 qobject_unref(ret); 1356 goto out; 1357 } 1358 if (strcmp(status, "cancelled") == 0) { 1359 qobject_unref(ret); 1360 break; 1361 } 1362 g_assert_cmpstr(status, !=, "failed"); 1363 g_assert_cmpstr(status, !=, "active"); 1364 qobject_unref(ret); 1365 } 1366 1367 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1368 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1369 1370 out: 1371 qos_object_destroy((QOSGraphObject *)vdev); 1372 machine_stop(qts); 1373 } 1374 1375 static void test_migrate_off_abort(gconstpointer opaque) 1376 { 1377 QTestState *qts; 1378 QDict *resp, *args, *ret; 1379 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1380 const gchar *status; 1381 QVirtioPCIDevice *vdev; 1382 1383 qts = machine_start(BASE_MACHINE 1384 "-netdev user,id=hs0 " 1385 "-netdev user,id=hs1 ", 1386 2); 1387 1388 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1389 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1390 1391 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1392 "{'bus': 'root0'," 1393 "'failover': 'off'," 1394 "'netdev': 'hs0'," 1395 "'mac': '"MAC_STANDBY0"'}"); 1396 1397 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1398 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1399 1400 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 1401 1402 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1403 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1404 1405 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1406 "{'bus': 'root1'," 1407 "'failover_pair_id': 'standby0'," 1408 "'netdev': 'hs1'," 1409 "'rombar': 0," 1410 "'romfile': ''," 1411 "'mac': '"MAC_PRIMARY0"'}"); 1412 1413 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1414 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1415 1416 args = qdict_from_jsonf_nofail("{}"); 1417 g_assert_nonnull(args); 1418 qdict_put_str(args, "uri", uri); 1419 1420 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1421 g_assert(qdict_haskey(resp, "return")); 1422 qobject_unref(resp); 1423 1424 while (true) { 1425 ret = migrate_status(qts); 1426 1427 status = qdict_get_str(ret, "status"); 1428 if (strcmp(status, "active") == 0) { 1429 qobject_unref(ret); 1430 break; 1431 } 1432 g_assert_cmpstr(status, !=, "failed"); 1433 qobject_unref(ret); 1434 } 1435 1436 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1437 g_assert(qdict_haskey(resp, "return")); 1438 qobject_unref(resp); 1439 1440 while (true) { 1441 ret = migrate_status(qts); 1442 1443 status = qdict_get_str(ret, "status"); 1444 if (strcmp(status, "completed") == 0) { 1445 g_test_skip("Failed to cancel the migration"); 1446 qobject_unref(ret); 1447 goto out; 1448 } 1449 if (strcmp(status, "cancelled") == 0) { 1450 qobject_unref(ret); 1451 break; 1452 } 1453 g_assert_cmpstr(status, !=, "failed"); 1454 g_assert_cmpstr(status, !=, "active"); 1455 qobject_unref(ret); 1456 } 1457 1458 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1459 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1460 1461 out: 1462 qos_object_destroy((QOSGraphObject *)vdev); 1463 machine_stop(qts); 1464 } 1465 1466 static void test_migrate_abort_timeout(gconstpointer opaque) 1467 { 1468 QTestState *qts; 1469 QDict *resp, *args, *ret; 1470 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1471 const gchar *status; 1472 int total; 1473 QVirtioPCIDevice *vdev; 1474 1475 qts = machine_start(BASE_MACHINE 1476 "-netdev user,id=hs0 " 1477 "-netdev user,id=hs1 ", 1478 2); 1479 1480 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1481 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1482 1483 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1484 "{'bus': 'root0'," 1485 "'failover': 'on'," 1486 "'netdev': 'hs0'," 1487 "'mac': '"MAC_STANDBY0"'}"); 1488 1489 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1490 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1491 1492 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1493 1494 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1495 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1496 1497 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1498 "{'bus': 'root1'," 1499 "'failover_pair_id': 'standby0'," 1500 "'netdev': 'hs1'," 1501 "'rombar': 0," 1502 "'romfile': ''," 1503 "'mac': '"MAC_PRIMARY0"'}"); 1504 1505 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1506 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1507 1508 args = qdict_from_jsonf_nofail("{}"); 1509 g_assert_nonnull(args); 1510 qdict_put_str(args, "uri", uri); 1511 1512 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1513 g_assert(qdict_haskey(resp, "return")); 1514 qobject_unref(resp); 1515 1516 /* the event is sent when QEMU asks the OS to unplug the card */ 1517 resp = get_unplug_primary_event(qts); 1518 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1519 qobject_unref(resp); 1520 1521 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1522 g_assert(qdict_haskey(resp, "return")); 1523 qobject_unref(resp); 1524 1525 /* migration has been cancelled while the unplug was in progress */ 1526 1527 /* while the card is not ejected, we must be in "cancelling" state */ 1528 1529 total = 0; 1530 while (true) { 1531 ret = migrate_status(qts); 1532 1533 status = qdict_get_str(ret, "status"); 1534 if (strcmp(status, "cancelled") == 0) { 1535 qobject_unref(ret); 1536 break; 1537 } 1538 g_assert_cmpstr(status, ==, "cancelling"); 1539 g_assert(qdict_haskey(ret, "total-time")); 1540 total = qdict_get_int(ret, "total-time"); 1541 qobject_unref(ret); 1542 } 1543 1544 /* 1545 * migration timeout in this case is 30 seconds 1546 * check we exit on the timeout (ms) 1547 */ 1548 g_assert_cmpint(total, >, 30000); 1549 1550 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1551 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1552 1553 qos_object_destroy((QOSGraphObject *)vdev); 1554 machine_stop(qts); 1555 } 1556 1557 static void test_multi_out(gconstpointer opaque) 1558 { 1559 QTestState *qts; 1560 QDict *resp, *args, *ret; 1561 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1562 const gchar *status, *expected; 1563 QVirtioPCIDevice *vdev0, *vdev1; 1564 1565 qts = machine_start(BASE_MACHINE 1566 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1567 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1568 "-netdev user,id=hs0 " 1569 "-netdev user,id=hs1 " 1570 "-netdev user,id=hs2 " 1571 "-netdev user,id=hs3 ", 1572 4); 1573 1574 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1575 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1576 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1577 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1578 1579 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1580 "{'bus': 'root0'," 1581 "'failover': 'on'," 1582 "'netdev': 'hs0'," 1583 "'mac': '"MAC_STANDBY0"'}"); 1584 1585 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1586 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1587 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1588 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1589 1590 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1591 "{'bus': 'root1'," 1592 "'failover_pair_id': 'standby0'," 1593 "'netdev': 'hs1'," 1594 "'rombar': 0," 1595 "'romfile': ''," 1596 "'mac': '"MAC_PRIMARY0"'}"); 1597 1598 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1599 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1600 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1601 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1602 1603 vdev0 = start_virtio_net(qts, 1, 0, "standby0", true); 1604 1605 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1606 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1607 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1608 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1609 1610 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1611 "{'bus': 'root2'," 1612 "'failover': 'on'," 1613 "'netdev': 'hs2'," 1614 "'mac': '"MAC_STANDBY1"'}"); 1615 1616 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1617 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1618 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1619 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1620 1621 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1622 "{'bus': 'root3'," 1623 "'failover_pair_id': 'standby1'," 1624 "'netdev': 'hs3'," 1625 "'rombar': 0," 1626 "'romfile': ''," 1627 "'mac': '"MAC_PRIMARY1"'}"); 1628 1629 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1630 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1631 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1632 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1633 1634 vdev1 = start_virtio_net(qts, 3, 0, "standby1", true); 1635 1636 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1637 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1638 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1639 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1640 1641 args = qdict_from_jsonf_nofail("{}"); 1642 g_assert_nonnull(args); 1643 qdict_put_str(args, "uri", uri); 1644 1645 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1646 g_assert(qdict_haskey(resp, "return")); 1647 qobject_unref(resp); 1648 1649 /* the event is sent when QEMU asks the OS to unplug the card */ 1650 resp = get_unplug_primary_event(qts); 1651 if (strcmp(qdict_get_str(resp, "device-id"), "primary0") == 0) { 1652 expected = "primary1"; 1653 } else if (strcmp(qdict_get_str(resp, "device-id"), "primary1") == 0) { 1654 expected = "primary0"; 1655 } else { 1656 g_assert_not_reached(); 1657 } 1658 qobject_unref(resp); 1659 1660 resp = get_unplug_primary_event(qts); 1661 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, expected); 1662 qobject_unref(resp); 1663 1664 /* wait the end of the migration setup phase */ 1665 while (true) { 1666 ret = migrate_status(qts); 1667 1668 status = qdict_get_str(ret, "status"); 1669 if (strcmp(status, "wait-unplug") == 0) { 1670 qobject_unref(ret); 1671 break; 1672 } 1673 1674 /* The migration must not start if the card is not ejected */ 1675 g_assert_cmpstr(status, !=, "active"); 1676 g_assert_cmpstr(status, !=, "completed"); 1677 g_assert_cmpstr(status, !=, "failed"); 1678 g_assert_cmpstr(status, !=, "cancelling"); 1679 g_assert_cmpstr(status, !=, "cancelled"); 1680 1681 qobject_unref(ret); 1682 } 1683 1684 /* OS unplugs primary1, but we must wait the second */ 1685 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1686 1687 ret = migrate_status(qts); 1688 status = qdict_get_str(ret, "status"); 1689 g_assert_cmpstr(status, ==, "wait-unplug"); 1690 qobject_unref(ret); 1691 1692 if (g_test_slow()) { 1693 /* check we stay in wait-unplug while the card is not ejected */ 1694 for (int i = 0; i < 5; i++) { 1695 sleep(1); 1696 ret = migrate_status(qts); 1697 status = qdict_get_str(ret, "status"); 1698 g_assert_cmpstr(status, ==, "wait-unplug"); 1699 qobject_unref(ret); 1700 } 1701 } 1702 1703 /* OS unplugs primary0, QEMU can move from wait-unplug state */ 1704 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_SEL_BASE, 2); 1705 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1706 1707 while (true) { 1708 ret = migrate_status(qts); 1709 1710 status = qdict_get_str(ret, "status"); 1711 if (strcmp(status, "completed") == 0) { 1712 qobject_unref(ret); 1713 break; 1714 } 1715 g_assert_cmpstr(status, !=, "failed"); 1716 g_assert_cmpstr(status, !=, "cancelling"); 1717 g_assert_cmpstr(status, !=, "cancelled"); 1718 qobject_unref(ret); 1719 } 1720 1721 qtest_qmp_eventwait(qts, "STOP"); 1722 1723 qos_object_destroy((QOSGraphObject *)vdev0); 1724 qos_object_destroy((QOSGraphObject *)vdev1); 1725 machine_stop(qts); 1726 } 1727 1728 static void test_multi_in(gconstpointer opaque) 1729 { 1730 QTestState *qts; 1731 QDict *resp, *args, *ret; 1732 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1733 1734 qts = machine_start(BASE_MACHINE 1735 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1736 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1737 "-netdev user,id=hs0 " 1738 "-netdev user,id=hs1 " 1739 "-netdev user,id=hs2 " 1740 "-netdev user,id=hs3 " 1741 "-incoming defer ", 1742 4); 1743 1744 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1745 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1746 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1747 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1748 1749 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1750 "{'bus': 'root0'," 1751 "'failover': 'on'," 1752 "'netdev': 'hs0'," 1753 "'mac': '"MAC_STANDBY0"'}"); 1754 1755 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1756 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1757 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1758 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1759 1760 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1761 "{'bus': 'root1'," 1762 "'failover_pair_id': 'standby0'," 1763 "'netdev': 'hs1'," 1764 "'rombar': 0," 1765 "'romfile': ''," 1766 "'mac': '"MAC_PRIMARY0"'}"); 1767 1768 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1769 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1770 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1771 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1772 1773 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1774 "{'bus': 'root2'," 1775 "'failover': 'on'," 1776 "'netdev': 'hs2'," 1777 "'mac': '"MAC_STANDBY1"'}"); 1778 1779 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1780 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1781 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1782 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1783 1784 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1785 "{'bus': 'root3'," 1786 "'failover_pair_id': 'standby1'," 1787 "'netdev': 'hs3'," 1788 "'rombar': 0," 1789 "'romfile': ''," 1790 "'mac': '"MAC_PRIMARY1"'}"); 1791 1792 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1793 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1794 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1795 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1796 1797 args = qdict_from_jsonf_nofail("{}"); 1798 g_assert_nonnull(args); 1799 qdict_put_str(args, "uri", uri); 1800 1801 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 1802 args); 1803 g_assert(qdict_haskey(resp, "return")); 1804 qobject_unref(resp); 1805 1806 resp = get_migration_event(qts); 1807 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 1808 qobject_unref(resp); 1809 1810 resp = get_failover_negociated_event(qts); 1811 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 1812 qobject_unref(resp); 1813 1814 resp = get_failover_negociated_event(qts); 1815 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby1"); 1816 qobject_unref(resp); 1817 1818 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1819 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1820 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1821 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1822 1823 qtest_qmp_eventwait(qts, "RESUME"); 1824 1825 ret = migrate_status(qts); 1826 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1827 qobject_unref(ret); 1828 1829 machine_stop(qts); 1830 } 1831 #endif /* _WIN32 */ 1832 1833 int main(int argc, char **argv) 1834 { 1835 gchar *tmpfile; 1836 int ret; 1837 1838 g_test_init(&argc, &argv, NULL); 1839 1840 ret = g_file_open_tmp("failover_test_migrate-XXXXXX", &tmpfile, NULL); 1841 g_assert_true(ret >= 0); 1842 close(ret); 1843 1844 /* parameters tests */ 1845 qtest_add_func("failover-virtio-net/params/error/id", test_error_id); 1846 qtest_add_func("failover-virtio-net/params/error/pcie", test_error_pcie); 1847 qtest_add_func("failover-virtio-net/params/on", test_on); 1848 qtest_add_func("failover-virtio-net/params/on_mismatch", 1849 test_on_mismatch); 1850 qtest_add_func("failover-virtio-net/params/off", test_off); 1851 qtest_add_func("failover-virtio-net/params/enabled", test_enabled); 1852 qtest_add_func("failover-virtio-net/params/guest_off", test_guest_off); 1853 1854 /* hotplug tests */ 1855 qtest_add_func("failover-virtio-net/hotplug/1", test_hotplug_1); 1856 qtest_add_func("failover-virtio-net/hotplug/1_reverse", 1857 test_hotplug_1_reverse); 1858 qtest_add_func("failover-virtio-net/hotplug/2", test_hotplug_2); 1859 qtest_add_func("failover-virtio-net/hotplug/2_reverse", 1860 test_hotplug_2_reverse); 1861 1862 #ifndef _WIN32 1863 /* 1864 * These migration tests cases use the exec migration protocol, 1865 * which is unsupported on Windows. 1866 */ 1867 qtest_add_data_func("failover-virtio-net/migrate/on/out", tmpfile, 1868 test_migrate_out); 1869 qtest_add_data_func("failover-virtio-net/migrate/on/in", tmpfile, 1870 test_migrate_in); 1871 qtest_add_data_func("failover-virtio-net/migrate/off/out", tmpfile, 1872 test_off_migrate_out); 1873 qtest_add_data_func("failover-virtio-net/migrate/off/in", tmpfile, 1874 test_off_migrate_in); 1875 qtest_add_data_func("failover-virtio-net/migrate/off/abort", tmpfile, 1876 test_migrate_off_abort); 1877 qtest_add_data_func("failover-virtio-net/migrate/guest_off/out", tmpfile, 1878 test_guest_off_migrate_out); 1879 qtest_add_data_func("failover-virtio-net/migrate/guest_off/in", tmpfile, 1880 test_guest_off_migrate_in); 1881 qtest_add_data_func("failover-virtio-net/migrate/guest_off/abort", tmpfile, 1882 test_migrate_guest_off_abort); 1883 qtest_add_data_func("failover-virtio-net/migrate/abort/wait-unplug", 1884 tmpfile, test_migrate_abort_wait_unplug); 1885 qtest_add_data_func("failover-virtio-net/migrate/abort/active", tmpfile, 1886 test_migrate_abort_active); 1887 if (g_test_slow()) { 1888 qtest_add_data_func("failover-virtio-net/migrate/abort/timeout", 1889 tmpfile, test_migrate_abort_timeout); 1890 } 1891 qtest_add_data_func("failover-virtio-net/migrate/multi/out", 1892 tmpfile, test_multi_out); 1893 qtest_add_data_func("failover-virtio-net/migrate/multi/in", 1894 tmpfile, test_multi_in); 1895 #endif /* _WIN32 */ 1896 1897 ret = g_test_run(); 1898 1899 unlink(tmpfile); 1900 g_free(tmpfile); 1901 1902 return ret; 1903 } 1904