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