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 "libqos/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, "active") == 0) { 1145 qobject_unref(ret); 1146 break; 1147 } 1148 g_assert_cmpstr(status, !=, "failed"); 1149 qobject_unref(ret); 1150 } 1151 1152 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1153 g_assert(qdict_haskey(resp, "return")); 1154 qobject_unref(resp); 1155 1156 while (true) { 1157 ret = migrate_status(qts); 1158 1159 status = qdict_get_str(ret, "status"); 1160 if (strcmp(status, "cancelled") == 0) { 1161 qobject_unref(ret); 1162 break; 1163 } 1164 g_assert_cmpstr(status, !=, "failed"); 1165 g_assert_cmpstr(status, !=, "active"); 1166 qobject_unref(ret); 1167 } 1168 1169 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1170 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1171 1172 qos_object_destroy((QOSGraphObject *)vdev); 1173 machine_stop(qts); 1174 } 1175 1176 static void test_migrate_abort_wait_unplug(gconstpointer opaque) 1177 { 1178 QTestState *qts; 1179 QDict *resp, *args, *ret; 1180 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1181 const gchar *status; 1182 QVirtioPCIDevice *vdev; 1183 1184 qts = machine_start(BASE_MACHINE 1185 "-netdev user,id=hs0 " 1186 "-netdev user,id=hs1 ", 1187 2); 1188 1189 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1190 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1191 1192 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1193 "{'bus': 'root0'," 1194 "'failover': 'on'," 1195 "'netdev': 'hs0'," 1196 "'mac': '"MAC_STANDBY0"'}"); 1197 1198 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1199 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1200 1201 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1202 1203 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1204 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1205 1206 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1207 "{'bus': 'root1'," 1208 "'failover_pair_id': 'standby0'," 1209 "'netdev': 'hs1'," 1210 "'rombar': 0," 1211 "'romfile': ''," 1212 "'mac': '"MAC_PRIMARY0"'}"); 1213 1214 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1215 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1216 1217 args = qdict_from_jsonf_nofail("{}"); 1218 g_assert_nonnull(args); 1219 qdict_put_str(args, "uri", uri); 1220 1221 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1222 g_assert(qdict_haskey(resp, "return")); 1223 qobject_unref(resp); 1224 1225 /* the event is sent when QEMU asks the OS to unplug the card */ 1226 resp = get_unplug_primary_event(qts); 1227 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1228 qobject_unref(resp); 1229 1230 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1231 g_assert(qdict_haskey(resp, "return")); 1232 qobject_unref(resp); 1233 1234 /* migration has been cancelled while the unplug was in progress */ 1235 1236 /* while the card is not ejected, we must be in "cancelling" state */ 1237 ret = migrate_status(qts); 1238 1239 status = qdict_get_str(ret, "status"); 1240 g_assert_cmpstr(status, ==, "cancelling"); 1241 qobject_unref(ret); 1242 1243 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1244 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1245 1246 while (true) { 1247 ret = migrate_status(qts); 1248 1249 status = qdict_get_str(ret, "status"); 1250 if (strcmp(status, "cancelled") == 0) { 1251 qobject_unref(ret); 1252 break; 1253 } 1254 g_assert_cmpstr(status, !=, "failed"); 1255 g_assert_cmpstr(status, !=, "active"); 1256 qobject_unref(ret); 1257 } 1258 1259 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1260 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1261 1262 qos_object_destroy((QOSGraphObject *)vdev); 1263 machine_stop(qts); 1264 } 1265 1266 static void test_migrate_abort_active(gconstpointer opaque) 1267 { 1268 QTestState *qts; 1269 QDict *resp, *args, *ret; 1270 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1271 const gchar *status; 1272 QVirtioPCIDevice *vdev; 1273 1274 qts = machine_start(BASE_MACHINE 1275 "-netdev user,id=hs0 " 1276 "-netdev user,id=hs1 ", 1277 2); 1278 1279 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1280 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1281 1282 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1283 "{'bus': 'root0'," 1284 "'failover': 'on'," 1285 "'netdev': 'hs0'," 1286 "'mac': '"MAC_STANDBY0"'}"); 1287 1288 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1289 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1290 1291 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1292 1293 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1294 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1295 1296 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1297 "{'bus': 'root1'," 1298 "'failover_pair_id': 'standby0'," 1299 "'netdev': 'hs1'," 1300 "'rombar': 0," 1301 "'romfile': ''," 1302 "'mac': '"MAC_PRIMARY0"'}"); 1303 1304 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1305 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1306 1307 args = qdict_from_jsonf_nofail("{}"); 1308 g_assert_nonnull(args); 1309 qdict_put_str(args, "uri", uri); 1310 1311 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1312 g_assert(qdict_haskey(resp, "return")); 1313 qobject_unref(resp); 1314 1315 /* the event is sent when QEMU asks the OS to unplug the card */ 1316 resp = get_unplug_primary_event(qts); 1317 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1318 qobject_unref(resp); 1319 1320 /* OS unplugs the cards, QEMU can move from wait-unplug state */ 1321 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1322 1323 while (true) { 1324 ret = migrate_status(qts); 1325 1326 status = qdict_get_str(ret, "status"); 1327 if (strcmp(status, "wait-unplug") != 0) { 1328 qobject_unref(ret); 1329 break; 1330 } 1331 g_assert_cmpstr(status, !=, "failed"); 1332 qobject_unref(ret); 1333 } 1334 1335 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1336 g_assert(qdict_haskey(resp, "return")); 1337 qobject_unref(resp); 1338 1339 while (true) { 1340 ret = migrate_status(qts); 1341 1342 status = qdict_get_str(ret, "status"); 1343 if (strcmp(status, "cancelled") == 0) { 1344 qobject_unref(ret); 1345 break; 1346 } 1347 g_assert_cmpstr(status, !=, "failed"); 1348 g_assert_cmpstr(status, !=, "active"); 1349 qobject_unref(ret); 1350 } 1351 1352 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1353 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1354 1355 qos_object_destroy((QOSGraphObject *)vdev); 1356 machine_stop(qts); 1357 } 1358 1359 static void test_migrate_off_abort(gconstpointer opaque) 1360 { 1361 QTestState *qts; 1362 QDict *resp, *args, *ret; 1363 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1364 const gchar *status; 1365 QVirtioPCIDevice *vdev; 1366 1367 qts = machine_start(BASE_MACHINE 1368 "-netdev user,id=hs0 " 1369 "-netdev user,id=hs1 ", 1370 2); 1371 1372 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1373 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1374 1375 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1376 "{'bus': 'root0'," 1377 "'failover': 'off'," 1378 "'netdev': 'hs0'," 1379 "'mac': '"MAC_STANDBY0"'}"); 1380 1381 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1382 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1383 1384 vdev = start_virtio_net(qts, 1, 0, "standby0", false); 1385 1386 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1387 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1388 1389 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1390 "{'bus': 'root1'," 1391 "'failover_pair_id': 'standby0'," 1392 "'netdev': 'hs1'," 1393 "'rombar': 0," 1394 "'romfile': ''," 1395 "'mac': '"MAC_PRIMARY0"'}"); 1396 1397 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1398 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1399 1400 args = qdict_from_jsonf_nofail("{}"); 1401 g_assert_nonnull(args); 1402 qdict_put_str(args, "uri", uri); 1403 1404 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1405 g_assert(qdict_haskey(resp, "return")); 1406 qobject_unref(resp); 1407 1408 while (true) { 1409 ret = migrate_status(qts); 1410 1411 status = qdict_get_str(ret, "status"); 1412 if (strcmp(status, "active") == 0) { 1413 qobject_unref(ret); 1414 break; 1415 } 1416 g_assert_cmpstr(status, !=, "failed"); 1417 qobject_unref(ret); 1418 } 1419 1420 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 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, "cancelled") == 0) { 1429 qobject_unref(ret); 1430 break; 1431 } 1432 g_assert_cmpstr(status, !=, "failed"); 1433 g_assert_cmpstr(status, !=, "active"); 1434 qobject_unref(ret); 1435 } 1436 1437 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1438 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1439 1440 qos_object_destroy((QOSGraphObject *)vdev); 1441 machine_stop(qts); 1442 } 1443 1444 static void test_migrate_abort_timeout(gconstpointer opaque) 1445 { 1446 QTestState *qts; 1447 QDict *resp, *args, *ret; 1448 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1449 const gchar *status; 1450 int total; 1451 QVirtioPCIDevice *vdev; 1452 1453 qts = machine_start(BASE_MACHINE 1454 "-netdev user,id=hs0 " 1455 "-netdev user,id=hs1 ", 1456 2); 1457 1458 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1459 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1460 1461 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1462 "{'bus': 'root0'," 1463 "'failover': 'on'," 1464 "'netdev': 'hs0'," 1465 "'mac': '"MAC_STANDBY0"'}"); 1466 1467 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1468 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1469 1470 vdev = start_virtio_net(qts, 1, 0, "standby0", true); 1471 1472 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1473 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1474 1475 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1476 "{'bus': 'root1'," 1477 "'failover_pair_id': 'standby0'," 1478 "'netdev': 'hs1'," 1479 "'rombar': 0," 1480 "'romfile': ''," 1481 "'mac': '"MAC_PRIMARY0"'}"); 1482 1483 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1484 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1485 1486 args = qdict_from_jsonf_nofail("{}"); 1487 g_assert_nonnull(args); 1488 qdict_put_str(args, "uri", uri); 1489 1490 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1491 g_assert(qdict_haskey(resp, "return")); 1492 qobject_unref(resp); 1493 1494 /* the event is sent when QEMU asks the OS to unplug the card */ 1495 resp = get_unplug_primary_event(qts); 1496 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0"); 1497 qobject_unref(resp); 1498 1499 resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }"); 1500 g_assert(qdict_haskey(resp, "return")); 1501 qobject_unref(resp); 1502 1503 /* migration has been cancelled while the unplug was in progress */ 1504 1505 /* while the card is not ejected, we must be in "cancelling" state */ 1506 1507 total = 0; 1508 while (true) { 1509 ret = migrate_status(qts); 1510 1511 status = qdict_get_str(ret, "status"); 1512 if (strcmp(status, "cancelled") == 0) { 1513 qobject_unref(ret); 1514 break; 1515 } 1516 g_assert_cmpstr(status, ==, "cancelling"); 1517 g_assert(qdict_haskey(ret, "total-time")); 1518 total = qdict_get_int(ret, "total-time"); 1519 qobject_unref(ret); 1520 } 1521 1522 /* 1523 * migration timeout in this case is 30 seconds 1524 * check we exit on the timeout (ms) 1525 */ 1526 g_assert_cmpint(total, >, 30000); 1527 1528 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1529 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1530 1531 qos_object_destroy((QOSGraphObject *)vdev); 1532 machine_stop(qts); 1533 } 1534 1535 static void test_multi_out(gconstpointer opaque) 1536 { 1537 QTestState *qts; 1538 QDict *resp, *args, *ret; 1539 g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque); 1540 const gchar *status, *expected; 1541 QVirtioPCIDevice *vdev0, *vdev1; 1542 1543 qts = machine_start(BASE_MACHINE 1544 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1545 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1546 "-netdev user,id=hs0 " 1547 "-netdev user,id=hs1 " 1548 "-netdev user,id=hs2 " 1549 "-netdev user,id=hs3 ", 1550 4); 1551 1552 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1553 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1554 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1555 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1556 1557 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1558 "{'bus': 'root0'," 1559 "'failover': 'on'," 1560 "'netdev': 'hs0'," 1561 "'mac': '"MAC_STANDBY0"'}"); 1562 1563 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1564 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1565 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1566 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1567 1568 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1569 "{'bus': 'root1'," 1570 "'failover_pair_id': 'standby0'," 1571 "'netdev': 'hs1'," 1572 "'rombar': 0," 1573 "'romfile': ''," 1574 "'mac': '"MAC_PRIMARY0"'}"); 1575 1576 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1577 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1578 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1579 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1580 1581 vdev0 = start_virtio_net(qts, 1, 0, "standby0", true); 1582 1583 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1584 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1585 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1586 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1587 1588 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1589 "{'bus': 'root2'," 1590 "'failover': 'on'," 1591 "'netdev': 'hs2'," 1592 "'mac': '"MAC_STANDBY1"'}"); 1593 1594 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1595 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1596 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1597 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1598 1599 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1600 "{'bus': 'root3'," 1601 "'failover_pair_id': 'standby1'," 1602 "'netdev': 'hs3'," 1603 "'rombar': 0," 1604 "'romfile': ''," 1605 "'mac': '"MAC_PRIMARY1"'}"); 1606 1607 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1608 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1609 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1610 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1611 1612 vdev1 = start_virtio_net(qts, 3, 0, "standby1", true); 1613 1614 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1615 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1616 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1617 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1618 1619 args = qdict_from_jsonf_nofail("{}"); 1620 g_assert_nonnull(args); 1621 qdict_put_str(args, "uri", uri); 1622 1623 resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args); 1624 g_assert(qdict_haskey(resp, "return")); 1625 qobject_unref(resp); 1626 1627 /* the event is sent when QEMU asks the OS to unplug the card */ 1628 resp = get_unplug_primary_event(qts); 1629 if (strcmp(qdict_get_str(resp, "device-id"), "primary0") == 0) { 1630 expected = "primary1"; 1631 } else if (strcmp(qdict_get_str(resp, "device-id"), "primary1") == 0) { 1632 expected = "primary0"; 1633 } else { 1634 g_assert_not_reached(); 1635 } 1636 qobject_unref(resp); 1637 1638 resp = get_unplug_primary_event(qts); 1639 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, expected); 1640 qobject_unref(resp); 1641 1642 /* wait the end of the migration setup phase */ 1643 while (true) { 1644 ret = migrate_status(qts); 1645 1646 status = qdict_get_str(ret, "status"); 1647 if (strcmp(status, "wait-unplug") == 0) { 1648 qobject_unref(ret); 1649 break; 1650 } 1651 1652 /* The migration must not start if the card is not ejected */ 1653 g_assert_cmpstr(status, !=, "active"); 1654 g_assert_cmpstr(status, !=, "completed"); 1655 g_assert_cmpstr(status, !=, "failed"); 1656 g_assert_cmpstr(status, !=, "cancelling"); 1657 g_assert_cmpstr(status, !=, "cancelled"); 1658 1659 qobject_unref(ret); 1660 } 1661 1662 /* OS unplugs primary1, but we must wait the second */ 1663 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1664 1665 ret = migrate_status(qts); 1666 status = qdict_get_str(ret, "status"); 1667 g_assert_cmpstr(status, ==, "wait-unplug"); 1668 qobject_unref(ret); 1669 1670 if (g_test_slow()) { 1671 /* check we stay in wait-unplug while the card is not ejected */ 1672 for (int i = 0; i < 5; i++) { 1673 sleep(1); 1674 ret = migrate_status(qts); 1675 status = qdict_get_str(ret, "status"); 1676 g_assert_cmpstr(status, ==, "wait-unplug"); 1677 qobject_unref(ret); 1678 } 1679 } 1680 1681 /* OS unplugs primary0, QEMU can move from wait-unplug state */ 1682 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_SEL_BASE, 2); 1683 qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1); 1684 1685 while (true) { 1686 ret = migrate_status(qts); 1687 1688 status = qdict_get_str(ret, "status"); 1689 if (strcmp(status, "completed") == 0) { 1690 qobject_unref(ret); 1691 break; 1692 } 1693 g_assert_cmpstr(status, !=, "failed"); 1694 g_assert_cmpstr(status, !=, "cancelling"); 1695 g_assert_cmpstr(status, !=, "cancelled"); 1696 qobject_unref(ret); 1697 } 1698 1699 qtest_qmp_eventwait(qts, "STOP"); 1700 1701 qos_object_destroy((QOSGraphObject *)vdev0); 1702 qos_object_destroy((QOSGraphObject *)vdev1); 1703 machine_stop(qts); 1704 } 1705 1706 static void test_multi_in(gconstpointer opaque) 1707 { 1708 QTestState *qts; 1709 QDict *resp, *args, *ret; 1710 g_autofree gchar *uri = g_strdup_printf("exec: cat %s", (gchar *)opaque); 1711 1712 qts = machine_start(BASE_MACHINE 1713 "-device pcie-root-port,id=root2,addr=0x3,bus=pcie.0,chassis=3 " 1714 "-device pcie-root-port,id=root3,addr=0x4,bus=pcie.0,chassis=4 " 1715 "-netdev user,id=hs0 " 1716 "-netdev user,id=hs1 " 1717 "-netdev user,id=hs2 " 1718 "-netdev user,id=hs3 " 1719 "-incoming defer ", 1720 4); 1721 1722 check_one_card(qts, false, "standby0", MAC_STANDBY0); 1723 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1724 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1725 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1726 1727 qtest_qmp_device_add(qts, "virtio-net", "standby0", 1728 "{'bus': 'root0'," 1729 "'failover': 'on'," 1730 "'netdev': 'hs0'," 1731 "'mac': '"MAC_STANDBY0"'}"); 1732 1733 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1734 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1735 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1736 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1737 1738 qtest_qmp_device_add(qts, "virtio-net", "primary0", 1739 "{'bus': 'root1'," 1740 "'failover_pair_id': 'standby0'," 1741 "'netdev': 'hs1'," 1742 "'rombar': 0," 1743 "'romfile': ''," 1744 "'mac': '"MAC_PRIMARY0"'}"); 1745 1746 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1747 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1748 check_one_card(qts, false, "standby1", MAC_STANDBY1); 1749 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1750 1751 qtest_qmp_device_add(qts, "virtio-net", "standby1", 1752 "{'bus': 'root2'," 1753 "'failover': 'on'," 1754 "'netdev': 'hs2'," 1755 "'mac': '"MAC_STANDBY1"'}"); 1756 1757 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1758 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1759 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1760 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1761 1762 qtest_qmp_device_add(qts, "virtio-net", "primary1", 1763 "{'bus': 'root3'," 1764 "'failover_pair_id': 'standby1'," 1765 "'netdev': 'hs3'," 1766 "'rombar': 0," 1767 "'romfile': ''," 1768 "'mac': '"MAC_PRIMARY1"'}"); 1769 1770 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1771 check_one_card(qts, false, "primary0", MAC_PRIMARY0); 1772 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1773 check_one_card(qts, false, "primary1", MAC_PRIMARY1); 1774 1775 args = qdict_from_jsonf_nofail("{}"); 1776 g_assert_nonnull(args); 1777 qdict_put_str(args, "uri", uri); 1778 1779 resp = qtest_qmp(qts, "{ 'execute': 'migrate-incoming', 'arguments': %p}", 1780 args); 1781 g_assert(qdict_haskey(resp, "return")); 1782 qobject_unref(resp); 1783 1784 resp = get_migration_event(qts); 1785 g_assert_cmpstr(qdict_get_str(resp, "status"), ==, "setup"); 1786 qobject_unref(resp); 1787 1788 resp = get_failover_negociated_event(qts); 1789 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby0"); 1790 qobject_unref(resp); 1791 1792 resp = get_failover_negociated_event(qts); 1793 g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "standby1"); 1794 qobject_unref(resp); 1795 1796 check_one_card(qts, true, "standby0", MAC_STANDBY0); 1797 check_one_card(qts, true, "primary0", MAC_PRIMARY0); 1798 check_one_card(qts, true, "standby1", MAC_STANDBY1); 1799 check_one_card(qts, true, "primary1", MAC_PRIMARY1); 1800 1801 qtest_qmp_eventwait(qts, "RESUME"); 1802 1803 ret = migrate_status(qts); 1804 g_assert_cmpstr(qdict_get_str(ret, "status"), ==, "completed"); 1805 qobject_unref(ret); 1806 1807 machine_stop(qts); 1808 } 1809 1810 int main(int argc, char **argv) 1811 { 1812 gchar *tmpfile; 1813 int ret; 1814 1815 g_test_init(&argc, &argv, NULL); 1816 1817 ret = g_file_open_tmp("failover_test_migrate-XXXXXX", &tmpfile, NULL); 1818 g_assert_true(ret >= 0); 1819 close(ret); 1820 1821 /* parameters tests */ 1822 qtest_add_func("failover-virtio-net/params/error/id", test_error_id); 1823 qtest_add_func("failover-virtio-net/params/error/pcie", test_error_pcie); 1824 qtest_add_func("failover-virtio-net/params/on", test_on); 1825 qtest_add_func("failover-virtio-net/params/on_mismatch", 1826 test_on_mismatch); 1827 qtest_add_func("failover-virtio-net/params/off", test_off); 1828 qtest_add_func("failover-virtio-net/params/enabled", test_enabled); 1829 qtest_add_func("failover-virtio-net/params/guest_off", test_guest_off); 1830 1831 /* hotplug tests */ 1832 qtest_add_func("failover-virtio-net/hotplug/1", test_hotplug_1); 1833 qtest_add_func("failover-virtio-net/hotplug/1_reverse", 1834 test_hotplug_1_reverse); 1835 qtest_add_func("failover-virtio-net/hotplug/2", test_hotplug_2); 1836 qtest_add_func("failover-virtio-net/hotplug/2_reverse", 1837 test_hotplug_2_reverse); 1838 1839 /* migration tests */ 1840 qtest_add_data_func("failover-virtio-net/migrate/on/out", tmpfile, 1841 test_migrate_out); 1842 qtest_add_data_func("failover-virtio-net/migrate/on/in", tmpfile, 1843 test_migrate_in); 1844 qtest_add_data_func("failover-virtio-net/migrate/off/out", tmpfile, 1845 test_off_migrate_out); 1846 qtest_add_data_func("failover-virtio-net/migrate/off/in", tmpfile, 1847 test_off_migrate_in); 1848 qtest_add_data_func("failover-virtio-net/migrate/off/abort", tmpfile, 1849 test_migrate_off_abort); 1850 qtest_add_data_func("failover-virtio-net/migrate/guest_off/out", tmpfile, 1851 test_guest_off_migrate_out); 1852 qtest_add_data_func("failover-virtio-net/migrate/guest_off/in", tmpfile, 1853 test_guest_off_migrate_in); 1854 qtest_add_data_func("failover-virtio-net/migrate/guest_off/abort", tmpfile, 1855 test_migrate_guest_off_abort); 1856 qtest_add_data_func("failover-virtio-net/migrate/abort/wait-unplug", 1857 tmpfile, test_migrate_abort_wait_unplug); 1858 qtest_add_data_func("failover-virtio-net/migrate/abort/active", tmpfile, 1859 test_migrate_abort_active); 1860 if (g_test_slow()) { 1861 qtest_add_data_func("failover-virtio-net/migrate/abort/timeout", 1862 tmpfile, test_migrate_abort_timeout); 1863 } 1864 qtest_add_data_func("failover-virtio-net/migrate/multi/out", 1865 tmpfile, test_multi_out); 1866 qtest_add_data_func("failover-virtio-net/migrate/multi/in", 1867 tmpfile, test_multi_in); 1868 1869 ret = g_test_run(); 1870 1871 unlink(tmpfile); 1872 g_free(tmpfile); 1873 1874 return ret; 1875 } 1876