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 static QDict *migrate_status(QTestState *qts) 592 { 593 QDict *resp, *ret; 594 595 resp = qtest_qmp(qts, "{ 'execute': 'query-migrate' }"); 596 g_assert(qdict_haskey(resp, "return")); 597 598 ret = qdict_get_qdict(resp, "return"); 599 g_assert(qdict_haskey(ret, "status")); 600 qobject_ref(ret); 601 qobject_unref(resp); 602 603 return ret; 604 } 605 606 static QDict *get_unplug_primary_event(QTestState *qts) 607 { 608 QDict *resp; 609 QDict *data; 610 611 resp = qtest_qmp_eventwait_ref(qts, "UNPLUG_PRIMARY"); 612 g_assert(qdict_haskey(resp, "data")); 613 614 data = qdict_get_qdict(resp, "data"); 615 g_assert(qdict_haskey(data, "device-id")); 616 qobject_ref(data); 617 qobject_unref(resp); 618 619 return data; 620 } 621 622 static void test_migrate_out(gconstpointer opaque) 623 { 624 QTestState *qts; 625 QDict *resp, *args, *ret; 626 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 627 const gchar *status; 628 QVirtioPCIDevice *vdev; 629 630 qts = machine_start(BASE_MACHINE 631 "-netdev user,id=hs0 " 632 "-netdev user,id=hs1 ", 633 2); 634 635 check_one_card(qts, false, "standby0", MAC_STANDBY0); 636 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 637 638 qtest_qmp_device_add(qts, "virtio-net", "standby0", 639 "{'bus': 'root0'," 640 "'failover': 'on'," 641 "'netdev': 'hs0'," 642 "'mac': '"MAC_STANDBY0"'}"); 643 644 check_one_card(qts, true, "standby0", MAC_STANDBY0); 645 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 646 647 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 648 649 check_one_card(qts, true, "standby0", MAC_STANDBY0); 650 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 651 652 qtest_qmp_device_add(qts, "virtio-net", "primary0", 653 "{'bus': 'root1'," 654 "'failover_pair_id': 'standby0'," 655 "'netdev': 'hs1'," 656 "'rombar': 0," 657 "'romfile': ''," 658 "'mac': '"MAC_PRIMARY0"'}"); 659 660 check_one_card(qts, true, "standby0", MAC_STANDBY0); 661 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 662 663 args = qdict_from_jsonf_nofail("{}"); 664 g_assert_nonnull(args); 665 qdict_put_str(args, "uri", uri); 666 667 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 668 g_assert(qdict_haskey(resp, "return")); 669 qobject_unref(resp); 670 671 /* the event is sent when QEMU asks the OS to unplug the card */ 672 resp = get_unplug_primary_event(qts); 673 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 674 qobject_unref(resp); 675 676 /* wait the end of the migration setup phase */ 677 while (true) { 678 ret = migrate_status(qts); 679 680 status = qdict_get_str(ret, "status"); 681 if (strcmp(status, "wait-unplug") == 0) { 682 qobject_unref(ret); 683 break; 684 } 685 686 /* The migration must not start if the card is not ejected */ 687 g_assert_cmpstr(status, !=, "active"); 688 g_assert_cmpstr(status, !=, "completed"); 689 g_assert_cmpstr(status, !=, "failed"); 690 g_assert_cmpstr(status, !=, "cancelling"); 691 g_assert_cmpstr(status, !=, "cancelled"); 692 693 qobject_unref(ret); 694 } 695 696 if (g_test_slow()) { 697 /* check we stay in wait-unplug while the card is not ejected */ 698 for (int i = 0; i < 5; i++) { 699 sleep(1); 700 ret = migrate_status(qts); 701 status = qdict_get_str(ret, "status"); 702 g_assert_cmpstr(status, ==, "wait-unplug"); 703 qobject_unref(ret); 704 } 705 } 706 707 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 708 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 709 710 while (true) { 711 ret = migrate_status(qts); 712 713 status = qdict_get_str(ret, "status"); 714 if (strcmp(status, "completed") == 0) { 715 qobject_unref(ret); 716 break; 717 } 718 g_assert_cmpstr(status, !=, "failed"); 719 g_assert_cmpstr(status, !=, "cancelling"); 720 g_assert_cmpstr(status, !=, "cancelled"); 721 qobject_unref(ret); 722 } 723 724 qtest_qmp_eventwait(qts, "STOP"); 725 726 /* 727 * in fact, the card is ejected from the point of view of kernel 728 * but not really from QEMU to be able to hotplug it back if 729 * migration fails. So we can't check that: 730 * check_one_card(qts, true, "standby0", MAC_STANDBY0); 731 * check_one_card(qts, false, "primary0", MAC_PRIMARY0); 732 */ 733 734 qos_object_destroy((QOSGraphObject *)vdev); 735 machine_stop(qts); 736 } 737 738 static QDict *get_migration_event(QTestState *qts) 739 { 740 QDict *resp; 741 QDict *data; 742 743 resp = qtest_qmp_eventwait_ref(qts, "MIGRATION"); 744 g_assert(qdict_haskey(resp, "data")); 745 746 data = qdict_get_qdict(resp, "data"); 747 g_assert(qdict_haskey(data, "status")); 748 qobject_ref(data); 749 qobject_unref(resp); 750 751 return data; 752 } 753 754 static void test_migrate_in(gconstpointer opaque) 755 { 756 QTestState *qts; 757 QDict *resp, *args, *ret; 758 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 759 760 qts = machine_start(BASE_MACHINE 761 "-netdev user,id=hs0 " 762 "-netdev user,id=hs1 " 763 "-incoming defer ", 764 2); 765 766 check_one_card(qts, false, "standby0", MAC_STANDBY0); 767 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 768 769 qtest_qmp_device_add(qts, "virtio-net", "standby0", 770 "{'bus': 'root0'," 771 "'failover': 'on'," 772 "'netdev': 'hs0'," 773 "'mac': '"MAC_STANDBY0"'}"); 774 775 check_one_card(qts, true, "standby0", MAC_STANDBY0); 776 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 777 778 qtest_qmp_device_add(qts, "virtio-net", "primary0", 779 "{'bus': 'root1'," 780 "'failover_pair_id': 'standby0'," 781 "'netdev': 'hs1'," 782 "'rombar': 0," 783 "'romfile': ''," 784 "'mac': '"MAC_PRIMARY0"'}"); 785 786 check_one_card(qts, true, "standby0", MAC_STANDBY0); 787 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 788 789 args = qdict_from_jsonf_nofail("{}"); 790 g_assert_nonnull(args); 791 qdict_put_str(args, "uri", uri); 792 793 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 794 args); 795 g_assert(qdict_haskey(resp, "return")); 796 qobject_unref(resp); 797 798 resp = get_migration_event(qts); 799 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 800 qobject_unref(resp); 801 802 resp = get_failover_negociated_event(qts); 803 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 804 qobject_unref(resp); 805 806 check_one_card(qts, true, "standby0", MAC_STANDBY0); 807 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 808 809 qtest_qmp_eventwait(qts, "RESUME"); 810 811 ret = migrate_status(qts); 812 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 813 qobject_unref(ret); 814 815 machine_stop(qts); 816 } 817 818 static void test_off_migrate_out(gconstpointer opaque) 819 { 820 QTestState *qts; 821 QDict *resp, *args, *ret; 822 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 823 const gchar *status; 824 QVirtioPCIDevice *vdev; 825 826 qts = machine_start(BASE_MACHINE 827 "-netdev user,id=hs0 " 828 "-netdev user,id=hs1 ", 829 2); 830 831 check_one_card(qts, false, "standby0", MAC_STANDBY0); 832 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 833 834 qtest_qmp_device_add(qts, "virtio-net", "standby0", 835 "{'bus': 'root0'," 836 "'failover': 'off'," 837 "'netdev': 'hs0'," 838 "'mac': '"MAC_STANDBY0"'}"); 839 840 check_one_card(qts, true, "standby0", MAC_STANDBY0); 841 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 842 843 qtest_qmp_device_add(qts, "virtio-net", "primary0", 844 "{'bus': 'root1'," 845 "'failover_pair_id': 'standby0'," 846 "'netdev': 'hs1'," 847 "'rombar': 0," 848 "'romfile': ''," 849 "'mac': '"MAC_PRIMARY0"'}"); 850 851 check_one_card(qts, true, "standby0", MAC_STANDBY0); 852 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 853 854 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 855 856 check_one_card(qts, true, "standby0", MAC_STANDBY0); 857 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 858 859 args = qdict_from_jsonf_nofail("{}"); 860 g_assert_nonnull(args); 861 qdict_put_str(args, "uri", uri); 862 863 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 864 g_assert(qdict_haskey(resp, "return")); 865 qobject_unref(resp); 866 867 while (true) { 868 ret = migrate_status(qts); 869 870 status = qdict_get_str(ret, "status"); 871 if (strcmp(status, "completed") == 0) { 872 qobject_unref(ret); 873 break; 874 } 875 g_assert_cmpstr(status, !=, "failed"); 876 g_assert_cmpstr(status, !=, "cancelling"); 877 g_assert_cmpstr(status, !=, "cancelled"); 878 qobject_unref(ret); 879 } 880 881 qtest_qmp_eventwait(qts, "STOP"); 882 883 qos_object_destroy((QOSGraphObject *)vdev); 884 machine_stop(qts); 885 } 886 887 static void test_off_migrate_in(gconstpointer opaque) 888 { 889 QTestState *qts; 890 QDict *resp, *args, *ret; 891 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 892 893 qts = machine_start(BASE_MACHINE 894 "-netdev user,id=hs0 " 895 "-netdev user,id=hs1 " 896 "-incoming defer ", 897 2); 898 899 check_one_card(qts, false, "standby0", MAC_STANDBY0); 900 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 901 902 qtest_qmp_device_add(qts, "virtio-net", "standby0", 903 "{'bus': 'root0'," 904 "'failover': 'off'," 905 "'netdev': 'hs0'," 906 "'mac': '"MAC_STANDBY0"'}"); 907 908 check_one_card(qts, true, "standby0", MAC_STANDBY0); 909 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 910 911 qtest_qmp_device_add(qts, "virtio-net", "primary0", 912 "{'bus': 'root1'," 913 "'failover_pair_id': 'standby0'," 914 "'netdev': 'hs1'," 915 "'rombar': 0," 916 "'romfile': ''," 917 "'mac': '"MAC_PRIMARY0"'}"); 918 919 check_one_card(qts, true, "standby0", MAC_STANDBY0); 920 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 921 922 args = qdict_from_jsonf_nofail("{}"); 923 g_assert_nonnull(args); 924 qdict_put_str(args, "uri", uri); 925 926 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 927 args); 928 g_assert(qdict_haskey(resp, "return")); 929 qobject_unref(resp); 930 931 resp = get_migration_event(qts); 932 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 933 qobject_unref(resp); 934 935 check_one_card(qts, true, "standby0", MAC_STANDBY0); 936 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 937 938 qtest_qmp_eventwait(qts, "RESUME"); 939 940 ret = migrate_status(qts); 941 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 942 qobject_unref(ret); 943 944 machine_stop(qts); 945 } 946 947 static void test_guest_off_migrate_out(gconstpointer opaque) 948 { 949 QTestState *qts; 950 QDict *resp, *args, *ret; 951 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 952 const gchar *status; 953 QVirtioPCIDevice *vdev; 954 uint64_t features; 955 956 qts = machine_start(BASE_MACHINE 957 "-netdev user,id=hs0 " 958 "-netdev user,id=hs1 ", 959 2); 960 961 check_one_card(qts, false, "standby0", MAC_STANDBY0); 962 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 963 964 qtest_qmp_device_add(qts, "virtio-net", "standby0", 965 "{'bus': 'root0'," 966 "'failover': 'on'," 967 "'netdev': 'hs0'," 968 "'mac': '"MAC_STANDBY0"'}"); 969 970 check_one_card(qts, true, "standby0", MAC_STANDBY0); 971 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 972 973 qtest_qmp_device_add(qts, "virtio-net", "primary0", 974 "{'bus': 'root1'," 975 "'failover_pair_id': 'standby0'," 976 "'netdev': 'hs1'," 977 "'rombar': 0," 978 "'romfile': ''," 979 "'mac': '"MAC_PRIMARY0"'}"); 980 981 check_one_card(qts, true, "standby0", MAC_STANDBY0); 982 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 983 984 features = ~(QVIRTIO_F_BAD_FEATURE | 985 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 986 (1ull << VIRTIO_RING_F_EVENT_IDX) | 987 (1ull << VIRTIO_NET_F_STANDBY)); 988 989 vdev = start_virtio_net_internal(qts, 1, 0, &features); 990 991 check_one_card(qts, true, "standby0", MAC_STANDBY0); 992 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 993 994 args = qdict_from_jsonf_nofail("{}"); 995 g_assert_nonnull(args); 996 qdict_put_str(args, "uri", uri); 997 998 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 999 g_assert(qdict_haskey(resp, "return")); 1000 qobject_unref(resp); 1001 1002 while (true) { 1003 ret = migrate_status(qts); 1004 1005 status = qdict_get_str(ret, "status"); 1006 if (strcmp(status, "completed") == 0) { 1007 qobject_unref(ret); 1008 break; 1009 } 1010 g_assert_cmpstr(status, !=, "failed"); 1011 g_assert_cmpstr(status, !=, "cancelling"); 1012 g_assert_cmpstr(status, !=, "cancelled"); 1013 qobject_unref(ret); 1014 } 1015 1016 qtest_qmp_eventwait(qts, "STOP"); 1017 1018 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1019 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1020 1021 qos_object_destroy((QOSGraphObject *)vdev); 1022 machine_stop(qts); 1023 } 1024 1025 static void test_guest_off_migrate_in(gconstpointer opaque) 1026 { 1027 QTestState *qts; 1028 QDict *resp, *args, *ret; 1029 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1030 1031 qts = machine_start(BASE_MACHINE 1032 "-netdev user,id=hs0 " 1033 "-netdev user,id=hs1 " 1034 "-incoming defer ", 1035 2); 1036 1037 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1038 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1039 1040 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1041 "{'bus': 'root0'," 1042 "'failover': 'on'," 1043 "'netdev': 'hs0'," 1044 "'mac': '"MAC_STANDBY0"'}"); 1045 1046 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1047 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1048 1049 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1050 "{'bus': 'root1'," 1051 "'failover_pair_id': 'standby0'," 1052 "'netdev': 'hs1'," 1053 "'rombar': 0," 1054 "'romfile': ''," 1055 "'mac': '"MAC_PRIMARY0"'}"); 1056 1057 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1058 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1059 1060 args = qdict_from_jsonf_nofail("{}"); 1061 g_assert_nonnull(args); 1062 qdict_put_str(args, "uri", uri); 1063 1064 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 1065 args); 1066 g_assert(qdict_haskey(resp, "return")); 1067 qobject_unref(resp); 1068 1069 resp = get_migration_event(qts); 1070 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 1071 qobject_unref(resp); 1072 1073 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1074 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1075 1076 qtest_qmp_eventwait(qts, "RESUME"); 1077 1078 ret = migrate_status(qts); 1079 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1080 qobject_unref(ret); 1081 1082 machine_stop(qts); 1083 } 1084 1085 static void test_migrate_guest_off_abort(gconstpointer opaque) 1086 { 1087 QTestState *qts; 1088 QDict *resp, *args, *ret; 1089 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1090 const gchar *status; 1091 QVirtioPCIDevice *vdev; 1092 uint64_t features; 1093 1094 qts = machine_start(BASE_MACHINE 1095 "-netdev user,id=hs0 " 1096 "-netdev user,id=hs1 ", 1097 2); 1098 1099 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1100 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1101 1102 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1103 "{'bus': 'root0'," 1104 "'failover': 'on'," 1105 "'netdev': 'hs0'," 1106 "'mac': '"MAC_STANDBY0"'}"); 1107 1108 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1109 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1110 1111 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1112 "{'bus': 'root1'," 1113 "'failover_pair_id': 'standby0'," 1114 "'netdev': 'hs1'," 1115 "'rombar': 0," 1116 "'romfile': ''," 1117 "'mac': '"MAC_PRIMARY0"'}"); 1118 1119 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1120 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1121 1122 features = ~(QVIRTIO_F_BAD_FEATURE | 1123 (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 1124 (1ull << VIRTIO_RING_F_EVENT_IDX) | 1125 (1ull << VIRTIO_NET_F_STANDBY)); 1126 1127 vdev = start_virtio_net_internal(qts, 1, 0, &features); 1128 1129 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1130 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1131 1132 args = qdict_from_jsonf_nofail("{}"); 1133 g_assert_nonnull(args); 1134 qdict_put_str(args, "uri", uri); 1135 1136 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1137 g_assert(qdict_haskey(resp, "return")); 1138 qobject_unref(resp); 1139 1140 while (true) { 1141 ret = migrate_status(qts); 1142 1143 status = qdict_get_str(ret, "status"); 1144 if (strcmp(status, "completed") == 0) { 1145 g_test_skip("Failed to cancel the migration"); 1146 qobject_unref(ret); 1147 goto out; 1148 } 1149 if (strcmp(status, "active") == 0) { 1150 qobject_unref(ret); 1151 break; 1152 } 1153 g_assert_cmpstr(status, !=, "failed"); 1154 qobject_unref(ret); 1155 } 1156 1157 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1158 g_assert(qdict_haskey(resp, "return")); 1159 qobject_unref(resp); 1160 1161 while (true) { 1162 ret = migrate_status(qts); 1163 status = qdict_get_str(ret, "status"); 1164 if (strcmp(status, "completed") == 0) { 1165 g_test_skip("Failed to cancel the migration"); 1166 qobject_unref(ret); 1167 goto out; 1168 } 1169 if (strcmp(status, "cancelled") == 0) { 1170 qobject_unref(ret); 1171 break; 1172 } 1173 g_assert_cmpstr(status, !=, "failed"); 1174 g_assert_cmpstr(status, !=, "active"); 1175 qobject_unref(ret); 1176 } 1177 1178 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1179 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1180 1181 out: 1182 qos_object_destroy((QOSGraphObject *)vdev); 1183 machine_stop(qts); 1184 } 1185 1186 static void test_migrate_abort_wait_unplug(gconstpointer opaque) 1187 { 1188 QTestState *qts; 1189 QDict *resp, *args, *ret; 1190 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1191 const gchar *status; 1192 QVirtioPCIDevice *vdev; 1193 1194 qts = machine_start(BASE_MACHINE 1195 "-netdev user,id=hs0 " 1196 "-netdev user,id=hs1 ", 1197 2); 1198 1199 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1200 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1201 1202 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1203 "{'bus': 'root0'," 1204 "'failover': 'on'," 1205 "'netdev': 'hs0'," 1206 "'mac': '"MAC_STANDBY0"'}"); 1207 1208 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1209 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1210 1211 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1212 1213 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1214 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1215 1216 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1217 "{'bus': 'root1'," 1218 "'failover_pair_id': 'standby0'," 1219 "'netdev': 'hs1'," 1220 "'rombar': 0," 1221 "'romfile': ''," 1222 "'mac': '"MAC_PRIMARY0"'}"); 1223 1224 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1225 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1226 1227 args = qdict_from_jsonf_nofail("{}"); 1228 g_assert_nonnull(args); 1229 qdict_put_str(args, "uri", uri); 1230 1231 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1232 g_assert(qdict_haskey(resp, "return")); 1233 qobject_unref(resp); 1234 1235 /* the event is sent when QEMU asks the OS to unplug the card */ 1236 resp = get_unplug_primary_event(qts); 1237 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1238 qobject_unref(resp); 1239 1240 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1241 g_assert(qdict_haskey(resp, "return")); 1242 qobject_unref(resp); 1243 1244 /* migration has been cancelled while the unplug was in progress */ 1245 1246 /* while the card is not ejected, we must be in "cancelling" state */ 1247 ret = migrate_status(qts); 1248 1249 status = qdict_get_str(ret, "status"); 1250 g_assert_cmpstr(status, ==, "cancelling"); 1251 qobject_unref(ret); 1252 1253 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1254 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1255 1256 while (true) { 1257 ret = migrate_status(qts); 1258 1259 status = qdict_get_str(ret, "status"); 1260 if (strcmp(status, "cancelled") == 0) { 1261 qobject_unref(ret); 1262 break; 1263 } 1264 g_assert_cmpstr(status, ==, "cancelling"); 1265 qobject_unref(ret); 1266 } 1267 1268 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1269 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1270 1271 qos_object_destroy((QOSGraphObject *)vdev); 1272 machine_stop(qts); 1273 } 1274 1275 static void test_migrate_abort_active(gconstpointer opaque) 1276 { 1277 QTestState *qts; 1278 QDict *resp, *args, *ret; 1279 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1280 const gchar *status; 1281 QVirtioPCIDevice *vdev; 1282 1283 qts = machine_start(BASE_MACHINE 1284 "-netdev user,id=hs0 " 1285 "-netdev user,id=hs1 ", 1286 2); 1287 1288 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1289 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1290 1291 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1292 "{'bus': 'root0'," 1293 "'failover': 'on'," 1294 "'netdev': 'hs0'," 1295 "'mac': '"MAC_STANDBY0"'}"); 1296 1297 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1298 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1299 1300 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1301 1302 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1303 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1304 1305 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1306 "{'bus': 'root1'," 1307 "'failover_pair_id': 'standby0'," 1308 "'netdev': 'hs1'," 1309 "'rombar': 0," 1310 "'romfile': ''," 1311 "'mac': '"MAC_PRIMARY0"'}"); 1312 1313 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1314 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1315 1316 args = qdict_from_jsonf_nofail("{}"); 1317 g_assert_nonnull(args); 1318 qdict_put_str(args, "uri", uri); 1319 1320 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1321 g_assert(qdict_haskey(resp, "return")); 1322 qobject_unref(resp); 1323 1324 /* the event is sent when QEMU asks the OS to unplug the card */ 1325 resp = get_unplug_primary_event(qts); 1326 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1327 qobject_unref(resp); 1328 1329 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1330 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1331 1332 while (true) { 1333 ret = migrate_status(qts); 1334 1335 status = qdict_get_str(ret, "status"); 1336 g_assert_cmpstr(status, !=, "failed"); 1337 if (strcmp(status, "wait-unplug") != 0) { 1338 qobject_unref(ret); 1339 break; 1340 } 1341 qobject_unref(ret); 1342 } 1343 1344 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1345 g_assert(qdict_haskey(resp, "return")); 1346 qobject_unref(resp); 1347 1348 while (true) { 1349 ret = migrate_status(qts); 1350 1351 status = qdict_get_str(ret, "status"); 1352 if (strcmp(status, "completed") == 0) { 1353 g_test_skip("Failed to cancel the migration"); 1354 qobject_unref(ret); 1355 goto out; 1356 } 1357 if (strcmp(status, "cancelled") == 0) { 1358 qobject_unref(ret); 1359 break; 1360 } 1361 g_assert_cmpstr(status, !=, "failed"); 1362 g_assert_cmpstr(status, !=, "active"); 1363 qobject_unref(ret); 1364 } 1365 1366 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1367 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1368 1369 out: 1370 qos_object_destroy((QOSGraphObject *)vdev); 1371 machine_stop(qts); 1372 } 1373 1374 static void test_migrate_off_abort(gconstpointer opaque) 1375 { 1376 QTestState *qts; 1377 QDict *resp, *args, *ret; 1378 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1379 const gchar *status; 1380 QVirtioPCIDevice *vdev; 1381 1382 qts = machine_start(BASE_MACHINE 1383 "-netdev user,id=hs0 " 1384 "-netdev user,id=hs1 ", 1385 2); 1386 1387 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1388 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1389 1390 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1391 "{'bus': 'root0'," 1392 "'failover': 'off'," 1393 "'netdev': 'hs0'," 1394 "'mac': '"MAC_STANDBY0"'}"); 1395 1396 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1397 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1398 1399 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 1400 1401 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1402 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1403 1404 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1405 "{'bus': 'root1'," 1406 "'failover_pair_id': 'standby0'," 1407 "'netdev': 'hs1'," 1408 "'rombar': 0," 1409 "'romfile': ''," 1410 "'mac': '"MAC_PRIMARY0"'}"); 1411 1412 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1413 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1414 1415 args = qdict_from_jsonf_nofail("{}"); 1416 g_assert_nonnull(args); 1417 qdict_put_str(args, "uri", uri); 1418 1419 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1420 g_assert(qdict_haskey(resp, "return")); 1421 qobject_unref(resp); 1422 1423 while (true) { 1424 ret = migrate_status(qts); 1425 1426 status = qdict_get_str(ret, "status"); 1427 if (strcmp(status, "active") == 0) { 1428 qobject_unref(ret); 1429 break; 1430 } 1431 g_assert_cmpstr(status, !=, "failed"); 1432 qobject_unref(ret); 1433 } 1434 1435 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1436 g_assert(qdict_haskey(resp, "return")); 1437 qobject_unref(resp); 1438 1439 while (true) { 1440 ret = migrate_status(qts); 1441 1442 status = qdict_get_str(ret, "status"); 1443 if (strcmp(status, "completed") == 0) { 1444 g_test_skip("Failed to cancel the migration"); 1445 qobject_unref(ret); 1446 goto out; 1447 } 1448 if (strcmp(status, "cancelled") == 0) { 1449 qobject_unref(ret); 1450 break; 1451 } 1452 g_assert_cmpstr(status, !=, "failed"); 1453 g_assert_cmpstr(status, !=, "active"); 1454 qobject_unref(ret); 1455 } 1456 1457 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1458 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1459 1460 out: 1461 qos_object_destroy((QOSGraphObject *)vdev); 1462 machine_stop(qts); 1463 } 1464 1465 static void test_migrate_abort_timeout(gconstpointer opaque) 1466 { 1467 QTestState *qts; 1468 QDict *resp, *args, *ret; 1469 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1470 const gchar *status; 1471 int total; 1472 QVirtioPCIDevice *vdev; 1473 1474 qts = machine_start(BASE_MACHINE 1475 "-netdev user,id=hs0 " 1476 "-netdev user,id=hs1 ", 1477 2); 1478 1479 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1480 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1481 1482 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1483 "{'bus': 'root0'," 1484 "'failover': 'on'," 1485 "'netdev': 'hs0'," 1486 "'mac': '"MAC_STANDBY0"'}"); 1487 1488 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1489 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1490 1491 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1492 1493 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1494 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1495 1496 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1497 "{'bus': 'root1'," 1498 "'failover_pair_id': 'standby0'," 1499 "'netdev': 'hs1'," 1500 "'rombar': 0," 1501 "'romfile': ''," 1502 "'mac': '"MAC_PRIMARY0"'}"); 1503 1504 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1505 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1506 1507 args = qdict_from_jsonf_nofail("{}"); 1508 g_assert_nonnull(args); 1509 qdict_put_str(args, "uri", uri); 1510 1511 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1512 g_assert(qdict_haskey(resp, "return")); 1513 qobject_unref(resp); 1514 1515 /* the event is sent when QEMU asks the OS to unplug the card */ 1516 resp = get_unplug_primary_event(qts); 1517 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1518 qobject_unref(resp); 1519 1520 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1521 g_assert(qdict_haskey(resp, "return")); 1522 qobject_unref(resp); 1523 1524 /* migration has been cancelled while the unplug was in progress */ 1525 1526 /* while the card is not ejected, we must be in "cancelling" state */ 1527 1528 total = 0; 1529 while (true) { 1530 ret = migrate_status(qts); 1531 1532 status = qdict_get_str(ret, "status"); 1533 if (strcmp(status, "cancelled") == 0) { 1534 qobject_unref(ret); 1535 break; 1536 } 1537 g_assert_cmpstr(status, ==, "cancelling"); 1538 g_assert(qdict_haskey(ret, "total-time")); 1539 total = qdict_get_int(ret, "total-time"); 1540 qobject_unref(ret); 1541 } 1542 1543 /* 1544 * migration timeout in this case is 30 seconds 1545 * check we exit on the timeout (ms) 1546 */ 1547 g_assert_cmpint(total, >, 30000); 1548 1549 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1550 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1551 1552 qos_object_destroy((QOSGraphObject *)vdev); 1553 machine_stop(qts); 1554 } 1555 1556 static void test_multi_out(gconstpointer opaque) 1557 { 1558 QTestState *qts; 1559 QDict *resp, *args, *ret; 1560 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1561 const gchar *status, *expected; 1562 QVirtioPCIDevice *vdev0, *vdev1; 1563 1564 qts = machine_start(BASE_MACHINE 1565 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1566 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1567 "-netdev user,id=hs0 " 1568 "-netdev user,id=hs1 " 1569 "-netdev user,id=hs2 " 1570 "-netdev user,id=hs3 ", 1571 4); 1572 1573 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1574 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1575 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1576 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1577 1578 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1579 "{'bus': 'root0'," 1580 "'failover': 'on'," 1581 "'netdev': 'hs0'," 1582 "'mac': '"MAC_STANDBY0"'}"); 1583 1584 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1585 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1586 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1587 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1588 1589 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1590 "{'bus': 'root1'," 1591 "'failover_pair_id': 'standby0'," 1592 "'netdev': 'hs1'," 1593 "'rombar': 0," 1594 "'romfile': ''," 1595 "'mac': '"MAC_PRIMARY0"'}"); 1596 1597 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1598 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1599 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1600 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1601 1602 vdev0 = start_virtio_net(qts, 1, 0, "standby0", true); 1603 1604 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1605 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1606 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1607 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1608 1609 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1610 "{'bus': 'root2'," 1611 "'failover': 'on'," 1612 "'netdev': 'hs2'," 1613 "'mac': '"MAC_STANDBY1"'}"); 1614 1615 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1616 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1617 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1618 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1619 1620 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1621 "{'bus': 'root3'," 1622 "'failover_pair_id': 'standby1'," 1623 "'netdev': 'hs3'," 1624 "'rombar': 0," 1625 "'romfile': ''," 1626 "'mac': '"MAC_PRIMARY1"'}"); 1627 1628 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1629 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1630 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1631 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1632 1633 vdev1 = start_virtio_net(qts, 3, 0, "standby1", true); 1634 1635 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1636 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1637 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1638 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1639 1640 args = qdict_from_jsonf_nofail("{}"); 1641 g_assert_nonnull(args); 1642 qdict_put_str(args, "uri", uri); 1643 1644 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1645 g_assert(qdict_haskey(resp, "return")); 1646 qobject_unref(resp); 1647 1648 /* the event is sent when QEMU asks the OS to unplug the card */ 1649 resp = get_unplug_primary_event(qts); 1650 if (strcmp(qdict_get_str(resp, "device-id"), "primary0") == 0) { 1651 expected = "primary1"; 1652 } else if (strcmp(qdict_get_str(resp, "device-id"), "primary1") == 0) { 1653 expected = "primary0"; 1654 } else { 1655 g_assert_not_reached(); 1656 } 1657 qobject_unref(resp); 1658 1659 resp = get_unplug_primary_event(qts); 1660 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, expected); 1661 qobject_unref(resp); 1662 1663 /* wait the end of the migration setup phase */ 1664 while (true) { 1665 ret = migrate_status(qts); 1666 1667 status = qdict_get_str(ret, "status"); 1668 if (strcmp(status, "wait-unplug") == 0) { 1669 qobject_unref(ret); 1670 break; 1671 } 1672 1673 /* The migration must not start if the card is not ejected */ 1674 g_assert_cmpstr(status, !=, "active"); 1675 g_assert_cmpstr(status, !=, "completed"); 1676 g_assert_cmpstr(status, !=, "failed"); 1677 g_assert_cmpstr(status, !=, "cancelling"); 1678 g_assert_cmpstr(status, !=, "cancelled"); 1679 1680 qobject_unref(ret); 1681 } 1682 1683 /* OS unplugs primary1, but we must wait the second */ 1684 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1685 1686 ret = migrate_status(qts); 1687 status = qdict_get_str(ret, "status"); 1688 g_assert_cmpstr(status, ==, "wait-unplug"); 1689 qobject_unref(ret); 1690 1691 if (g_test_slow()) { 1692 /* check we stay in wait-unplug while the card is not ejected */ 1693 for (int i = 0; i < 5; i++) { 1694 sleep(1); 1695 ret = migrate_status(qts); 1696 status = qdict_get_str(ret, "status"); 1697 g_assert_cmpstr(status, ==, "wait-unplug"); 1698 qobject_unref(ret); 1699 } 1700 } 1701 1702 /* OS unplugs primary0, QEMU can move from wait-unplug state */ 1703 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_SEL_BASE, 2); 1704 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1705 1706 while (true) { 1707 ret = migrate_status(qts); 1708 1709 status = qdict_get_str(ret, "status"); 1710 if (strcmp(status, "completed") == 0) { 1711 qobject_unref(ret); 1712 break; 1713 } 1714 g_assert_cmpstr(status, !=, "failed"); 1715 g_assert_cmpstr(status, !=, "cancelling"); 1716 g_assert_cmpstr(status, !=, "cancelled"); 1717 qobject_unref(ret); 1718 } 1719 1720 qtest_qmp_eventwait(qts, "STOP"); 1721 1722 qos_object_destroy((QOSGraphObject *)vdev0); 1723 qos_object_destroy((QOSGraphObject *)vdev1); 1724 machine_stop(qts); 1725 } 1726 1727 static void test_multi_in(gconstpointer opaque) 1728 { 1729 QTestState *qts; 1730 QDict *resp, *args, *ret; 1731 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1732 1733 qts = machine_start(BASE_MACHINE 1734 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1735 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1736 "-netdev user,id=hs0 " 1737 "-netdev user,id=hs1 " 1738 "-netdev user,id=hs2 " 1739 "-netdev user,id=hs3 " 1740 "-incoming defer ", 1741 4); 1742 1743 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1744 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1745 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1746 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1747 1748 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1749 "{'bus': 'root0'," 1750 "'failover': 'on'," 1751 "'netdev': 'hs0'," 1752 "'mac': '"MAC_STANDBY0"'}"); 1753 1754 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1755 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1756 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1757 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1758 1759 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1760 "{'bus': 'root1'," 1761 "'failover_pair_id': 'standby0'," 1762 "'netdev': 'hs1'," 1763 "'rombar': 0," 1764 "'romfile': ''," 1765 "'mac': '"MAC_PRIMARY0"'}"); 1766 1767 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1768 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1769 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1770 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1771 1772 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1773 "{'bus': 'root2'," 1774 "'failover': 'on'," 1775 "'netdev': 'hs2'," 1776 "'mac': '"MAC_STANDBY1"'}"); 1777 1778 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1779 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1780 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1781 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1782 1783 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1784 "{'bus': 'root3'," 1785 "'failover_pair_id': 'standby1'," 1786 "'netdev': 'hs3'," 1787 "'rombar': 0," 1788 "'romfile': ''," 1789 "'mac': '"MAC_PRIMARY1"'}"); 1790 1791 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1792 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1793 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1794 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1795 1796 args = qdict_from_jsonf_nofail("{}"); 1797 g_assert_nonnull(args); 1798 qdict_put_str(args, "uri", uri); 1799 1800 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 1801 args); 1802 g_assert(qdict_haskey(resp, "return")); 1803 qobject_unref(resp); 1804 1805 resp = get_migration_event(qts); 1806 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 1807 qobject_unref(resp); 1808 1809 resp = get_failover_negociated_event(qts); 1810 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 1811 qobject_unref(resp); 1812 1813 resp = get_failover_negociated_event(qts); 1814 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby1"); 1815 qobject_unref(resp); 1816 1817 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1818 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1819 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1820 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1821 1822 qtest_qmp_eventwait(qts, "RESUME"); 1823 1824 ret = migrate_status(qts); 1825 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1826 qobject_unref(ret); 1827 1828 machine_stop(qts); 1829 } 1830 1831 int main(int argc, char **argv) 1832 { 1833 gchar *tmpfile; 1834 int ret; 1835 1836 g_test_init(&argc, &argv, NULL); 1837 1838 ret = g_file_open_tmp("failover_test_migrate-XXXXXX", &tmpfile, NULL); 1839 g_assert_true(ret >= 0); 1840 close(ret); 1841 1842 /* parameters tests */ 1843 qtest_add_func("failover-virtio-net/params/error/id", test_error_id); 1844 qtest_add_func("failover-virtio-net/params/error/pcie", test_error_pcie); 1845 qtest_add_func("failover-virtio-net/params/on", test_on); 1846 qtest_add_func("failover-virtio-net/params/on_mismatch", 1847 test_on_mismatch); 1848 qtest_add_func("failover-virtio-net/params/off", test_off); 1849 qtest_add_func("failover-virtio-net/params/enabled", test_enabled); 1850 qtest_add_func("failover-virtio-net/params/guest_off", test_guest_off); 1851 1852 /* hotplug tests */ 1853 qtest_add_func("failover-virtio-net/hotplug/1", test_hotplug_1); 1854 qtest_add_func("failover-virtio-net/hotplug/1_reverse", 1855 test_hotplug_1_reverse); 1856 qtest_add_func("failover-virtio-net/hotplug/2", test_hotplug_2); 1857 qtest_add_func("failover-virtio-net/hotplug/2_reverse", 1858 test_hotplug_2_reverse); 1859 1860 /* migration tests */ 1861 qtest_add_data_func("failover-virtio-net/migrate/on/out", tmpfile, 1862 test_migrate_out); 1863 qtest_add_data_func("failover-virtio-net/migrate/on/in", tmpfile, 1864 test_migrate_in); 1865 qtest_add_data_func("failover-virtio-net/migrate/off/out", tmpfile, 1866 test_off_migrate_out); 1867 qtest_add_data_func("failover-virtio-net/migrate/off/in", tmpfile, 1868 test_off_migrate_in); 1869 qtest_add_data_func("failover-virtio-net/migrate/off/abort", tmpfile, 1870 test_migrate_off_abort); 1871 qtest_add_data_func("failover-virtio-net/migrate/guest_off/out", tmpfile, 1872 test_guest_off_migrate_out); 1873 qtest_add_data_func("failover-virtio-net/migrate/guest_off/in", tmpfile, 1874 test_guest_off_migrate_in); 1875 qtest_add_data_func("failover-virtio-net/migrate/guest_off/abort", tmpfile, 1876 test_migrate_guest_off_abort); 1877 qtest_add_data_func("failover-virtio-net/migrate/abort/wait-unplug", 1878 tmpfile, test_migrate_abort_wait_unplug); 1879 qtest_add_data_func("failover-virtio-net/migrate/abort/active", tmpfile, 1880 test_migrate_abort_active); 1881 if (g_test_slow()) { 1882 qtest_add_data_func("failover-virtio-net/migrate/abort/timeout", 1883 tmpfile, test_migrate_abort_timeout); 1884 } 1885 qtest_add_data_func("failover-virtio-net/migrate/multi/out", 1886 tmpfile, test_multi_out); 1887 qtest_add_data_func("failover-virtio-net/migrate/multi/in", 1888 tmpfile, test_multi_in); 1889 1890 ret = g_test_run(); 1891 1892 unlink(tmpfile); 1893 g_free(tmpfile); 1894 1895 return ret; 1896 } 1897