2 * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
3 * Copyright (C) 2014-2016 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "testutils.h"
26 # include <sys/types.h>
27 # include <sys/stat.h>
28 # include <sys/ioctl.h>
31 # include "virhostdev.h"
33 # define VIR_FROM_THIS VIR_FROM_NONE
35 VIR_LOG_INIT("tests.hostdevtest");
37 # define CHECK_LIST_COUNT(list, cnt, cb) \
40 if ((actualCount = cb(list)) != cnt) { \
41 virReportError(VIR_ERR_INTERNAL_ERROR, \
42 "Unexpected count of items in " #list ": %zu, " \
43 "expecting %zu", actualCount, (size_t) cnt); \
48 # define CHECK_PCI_LIST_COUNT(list, cnt) \
49 CHECK_LIST_COUNT(list, cnt, virPCIDeviceListCount)
51 # define TEST_STATE_DIR abs_builddir "/hostdevmgr"
52 static const char *drv_name
= "test_driver";
53 static const char *dom_name
= "test_domain";
54 static const unsigned char *uuid
=
55 (unsigned char *)("f92360b0-2541-8791-fb32-d1f838811541");
56 static int nhostdevs
= 3;
57 static virDomainHostdevDefPtr hostdevs
[] = {NULL
, NULL
, NULL
};
58 static virPCIDevicePtr dev
[] = {NULL
, NULL
, NULL
};
59 static virHostdevManagerPtr mgr
;
65 for (i
= 0; i
< nhostdevs
; i
++) {
66 virPCIDeviceFree(dev
[i
]);
67 virDomainHostdevDefFree(hostdevs
[i
]);
71 if (!getenv("LIBVIRT_SKIP_CLEANUP"))
72 virFileDeleteTree(mgr
->stateDir
);
74 virObjectUnref(mgr
->activePCIHostdevs
);
75 virObjectUnref(mgr
->activeUSBHostdevs
);
76 virObjectUnref(mgr
->inactivePCIHostdevs
);
77 virObjectUnref(mgr
->activeSCSIHostdevs
);
78 VIR_FREE(mgr
->stateDir
);
88 for (i
= 0; i
< nhostdevs
; i
++) {
89 virDomainHostdevSubsys subsys
;
90 hostdevs
[i
] = virDomainHostdevDefNew();
93 hostdevs
[i
]->mode
= VIR_DOMAIN_HOSTDEV_MODE_SUBSYS
;
94 subsys
.type
= VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI
;
95 subsys
.u
.pci
.addr
.domain
= 0;
96 subsys
.u
.pci
.addr
.bus
= 0;
97 subsys
.u
.pci
.addr
.slot
= i
+ 1;
98 subsys
.u
.pci
.addr
.function
= 0;
99 subsys
.u
.pci
.backend
= VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO
;
100 hostdevs
[i
]->source
.subsys
= subsys
;
103 for (i
= 0; i
< nhostdevs
; i
++) {
104 if (!(dev
[i
] = virPCIDeviceNew(0, 0, i
+ 1, 0)))
107 virPCIDeviceSetStubDriver(dev
[i
], VIR_PCI_STUB_DRIVER_VFIO
);
110 if (VIR_ALLOC(mgr
) < 0)
112 if ((mgr
->activePCIHostdevs
= virPCIDeviceListNew()) == NULL
)
114 if ((mgr
->activeUSBHostdevs
= virUSBDeviceListNew()) == NULL
)
116 if ((mgr
->inactivePCIHostdevs
= virPCIDeviceListNew()) == NULL
)
118 if ((mgr
->activeSCSIHostdevs
= virSCSIDeviceListNew()) == NULL
)
120 if (VIR_STRDUP(mgr
->stateDir
, TEST_STATE_DIR
) < 0)
122 if (virFileMakePath(mgr
->stateDir
) < 0)
133 testVirHostdevPreparePCIHostdevs_unmanaged(void)
136 size_t active_count
, inactive_count
, i
;
138 for (i
= 0; i
< nhostdevs
; i
++)
139 hostdevs
[i
]->managed
= false;
141 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
142 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
144 /* Test normal functionality */
145 VIR_DEBUG("Test 0 hostdevs");
146 if (virHostdevPreparePCIDevices(mgr
, drv_name
, dom_name
, uuid
,
149 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
150 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
152 /* Test unmanaged hostdevs */
153 VIR_DEBUG("Test >=1 unmanaged hostdevs");
154 if (virHostdevPreparePCIDevices(mgr
, drv_name
, dom_name
, uuid
,
155 hostdevs
, nhostdevs
, 0) < 0)
157 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
+ nhostdevs
);
158 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
- nhostdevs
);
161 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
162 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
163 VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again");
164 if (!virHostdevPreparePCIDevices(mgr
, drv_name
, dom_name
, uuid
,
167 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
168 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
170 VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again");
171 if (!virHostdevPreparePCIDevices(mgr
, drv_name
, "test_domain1", uuid
,
174 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
175 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
177 VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again");
178 if (!virHostdevPreparePCIDevices(mgr
, "test_driver1", dom_name
, uuid
,
181 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
182 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
192 testVirHostdevReAttachPCIHostdevs_unmanaged(void)
195 size_t active_count
, inactive_count
, i
;
197 for (i
= 0; i
< nhostdevs
; i
++) {
198 if (hostdevs
[i
]->managed
!= false) {
199 VIR_DEBUG("invalid test");
204 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
205 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
207 VIR_DEBUG("Test 0 hostdevs");
208 virHostdevReAttachPCIDevices(mgr
, drv_name
, dom_name
, NULL
, 0, NULL
);
209 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
210 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
212 VIR_DEBUG("Test >=1 unmanaged hostdevs");
213 virHostdevReAttachPCIDevices(mgr
, drv_name
, dom_name
,
214 hostdevs
, nhostdevs
, NULL
);
215 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
- nhostdevs
);
216 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
+ nhostdevs
);
226 testVirHostdevPreparePCIHostdevs_managed(bool mixed
)
229 size_t active_count
, inactive_count
, i
;
231 for (i
= 0; i
< nhostdevs
; i
++)
232 hostdevs
[i
]->managed
= true;
234 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
235 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
237 /* Test normal functionality */
238 VIR_DEBUG("Test >=1 hostdevs");
239 if (virHostdevPreparePCIDevices(mgr
, drv_name
, dom_name
, uuid
,
240 hostdevs
, nhostdevs
, 0) < 0)
242 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
+ nhostdevs
);
243 /* If testing a mixed roundtrip, devices are already in the inactive list
244 * before we start and are removed from it as soon as we attach them to
247 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
- nhostdevs
);
249 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
252 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
253 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
254 VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again");
255 if (!virHostdevPreparePCIDevices(mgr
, drv_name
, dom_name
, uuid
,
258 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
259 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
261 VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again");
262 if (!virHostdevPreparePCIDevices(mgr
, drv_name
, "test_domain1", uuid
,
265 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
266 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
268 VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again");
269 if (!virHostdevPreparePCIDevices(mgr
, "test_driver1", dom_name
, uuid
,
272 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
273 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
283 testVirHostdevReAttachPCIHostdevs_managed(bool mixed
)
286 size_t active_count
, inactive_count
, i
;
288 for (i
= 0; i
< nhostdevs
; i
++) {
289 if (hostdevs
[i
]->managed
!= true) {
290 VIR_DEBUG("invalid test");
295 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
296 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
298 VIR_DEBUG("Test 0 hostdevs");
299 virHostdevReAttachPCIDevices(mgr
, drv_name
, dom_name
, NULL
, 0, NULL
);
300 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
301 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
303 VIR_DEBUG("Test >=1 hostdevs");
304 virHostdevReAttachPCIDevices(mgr
, drv_name
, dom_name
,
305 hostdevs
, nhostdevs
, NULL
);
306 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
- nhostdevs
);
307 /* If testing a mixed roundtrip, devices are added back to the inactive
308 * list as soon as we detach from the guest */
310 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
+ nhostdevs
);
312 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
322 testVirHostdevDetachPCINodeDevice(void)
325 size_t active_count
, inactive_count
, i
;
327 for (i
= 0; i
< nhostdevs
; i
++) {
328 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
329 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
330 if (virHostdevPCINodeDeviceDetach(mgr
, dev
[i
]) < 0)
332 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
333 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
+ 1);
343 testVirHostdevResetPCINodeDevice(void)
346 size_t active_count
, inactive_count
, i
;
348 for (i
= 0; i
< nhostdevs
; i
++) {
349 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
350 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
351 if (virHostdevPCINodeDeviceReset(mgr
, dev
[i
]) < 0)
353 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
354 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
365 testVirHostdevReAttachPCINodeDevice(void)
368 size_t active_count
, inactive_count
, i
;
370 for (i
= 0; i
< nhostdevs
; i
++) {
371 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
372 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
373 if (virHostdevPCINodeDeviceReAttach(mgr
, dev
[i
]) < 0)
375 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
376 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
- 1);
387 testVirHostdevUpdateActivePCIHostdevs(void)
390 size_t active_count
, inactive_count
;
392 active_count
= virPCIDeviceListCount(mgr
->activePCIHostdevs
);
393 inactive_count
= virPCIDeviceListCount(mgr
->inactivePCIHostdevs
);
395 VIR_DEBUG("Test 0 hostdevs");
396 if (virHostdevUpdateActivePCIDevices(mgr
, NULL
, 0,
397 drv_name
, dom_name
) < 0)
399 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
);
400 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
402 VIR_DEBUG("Test >=1 hostdevs");
403 if (virHostdevUpdateActivePCIDevices(mgr
, hostdevs
, nhostdevs
,
404 drv_name
, dom_name
) < 0)
406 CHECK_PCI_LIST_COUNT(mgr
->activePCIHostdevs
, active_count
+ nhostdevs
);
407 CHECK_PCI_LIST_COUNT(mgr
->inactivePCIHostdevs
, inactive_count
);
416 * testVirHostdevRoundtripNoGuest:
419 * Perform a roundtrip without ever assigning devices to the guest.
421 * 1. Detach devices from the host
422 * 2. Reattach devices to the host
425 testVirHostdevRoundtripNoGuest(const void *opaque ATTRIBUTE_UNUSED
)
429 if (testVirHostdevDetachPCINodeDevice() < 0)
431 if (testVirHostdevReAttachPCINodeDevice() < 0)
441 * testVirHostdevRoundtripUnmanaged:
444 * Perform a roundtrip with unmanaged devices.
446 * 1. Detach devices from the host
447 * 2. Attach devices to the guest as unmanaged
448 * 3. Detach devices from the guest as unmanaged
449 * 4. Reattach devices to the host
452 testVirHostdevRoundtripUnmanaged(const void *opaque ATTRIBUTE_UNUSED
)
456 if (testVirHostdevDetachPCINodeDevice() < 0)
458 if (testVirHostdevPreparePCIHostdevs_unmanaged() < 0)
460 if (testVirHostdevReAttachPCIHostdevs_unmanaged() < 0)
462 if (testVirHostdevReAttachPCINodeDevice() < 0)
472 * testVirHostdevRoundtripManaged:
475 * Perform a roundtrip with managed devices.
477 * 1. Attach devices to the guest as managed
478 * 2. Detach devices from the guest as managed
481 testVirHostdevRoundtripManaged(const void *opaque ATTRIBUTE_UNUSED
)
485 if (testVirHostdevPreparePCIHostdevs_managed(false) < 0)
487 if (testVirHostdevReAttachPCIHostdevs_managed(false) < 0)
497 * testVirHostdevRoundtripMixed:
500 * Perform a roundtrip with managed devices but manually detach the devices
501 * from the host first.
503 * 1. Detach devices from the host
504 * 2. Attach devices to the guest as managed
505 * 3. Detach devices from the guest as managed
506 * 4. Reattach devices to the host
509 testVirHostdevRoundtripMixed(const void *opaque ATTRIBUTE_UNUSED
)
513 if (testVirHostdevDetachPCINodeDevice() < 0)
515 if (testVirHostdevPreparePCIHostdevs_managed(true) < 0)
517 if (testVirHostdevReAttachPCIHostdevs_managed(true) < 0)
519 if (testVirHostdevReAttachPCINodeDevice() < 0)
529 * testVirHostdevOther:
532 * Perform other operations on devices.
535 * 2. Update list of active devices
538 testVirHostdevOther(const void *opaque ATTRIBUTE_UNUSED
)
542 if (testVirHostdevResetPCINodeDevice() < 0)
544 if (testVirHostdevUpdateActivePCIHostdevs() < 0)
553 # define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX"
559 VIR_AUTOFREE(char *) fakerootdir
= NULL
;
561 if (VIR_STRDUP_QUIET(fakerootdir
, FAKEROOTDIRTEMPLATE
) < 0) {
562 fprintf(stderr
, "Out of memory\n");
566 if (!mkdtemp(fakerootdir
)) {
567 fprintf(stderr
, "Cannot create fakerootdir");
571 setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir
, 1);
573 # define DO_TEST(fnc) \
575 VIR_DEBUG("Testing: %s", #fnc); \
576 if (virTestRun(#fnc, fnc, NULL) < 0) \
581 fprintf(stderr
, "Init data structures failed.");
582 virFileDeleteTree(fakerootdir
);
586 DO_TEST(testVirHostdevRoundtripNoGuest
);
587 DO_TEST(testVirHostdevRoundtripUnmanaged
);
588 DO_TEST(testVirHostdevRoundtripManaged
);
589 DO_TEST(testVirHostdevRoundtripMixed
);
590 DO_TEST(testVirHostdevOther
);
594 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL
)
595 virFileDeleteTree(fakerootdir
);
597 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
600 VIR_TEST_MAIN_PRELOAD(mymain
, abs_builddir
"/.libs/virpcimock.so")