1 /*
2 * node_device_conf.c: config handling for node devices
3 *
4 * Copyright (C) 2009-2015 Red Hat, Inc.
5 * Copyright (C) 2008 Virtual Iron Software, Inc.
6 * Copyright (C) 2008 David F. Lively
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see
20 * <http://www.gnu.org/licenses/>.
21 */
22
23 #include <config.h>
24
25 #include <unistd.h>
26
27 #include "virerror.h"
28 #include "datatypes.h"
29 #include "viralloc.h"
30 #include "virstring.h"
31 #include "node_device_conf.h"
32 #include "device_conf.h"
33 #include "virxml.h"
34 #include "virbuffer.h"
35 #include "viruuid.h"
36 #include "virrandom.h"
37 #include "virlog.h"
38 #include "virfcp.h"
39 #include "virpcivpd.h"
40
41 #define VIR_FROM_THIS VIR_FROM_NODEDEV
42
43 VIR_LOG_INIT("conf.node_device_conf");
44
45 VIR_ENUM_IMPL(virNodeDevDevnode,
46 VIR_NODE_DEV_DEVNODE_LAST,
47 "dev",
48 "link",
49 );
50
51 VIR_ENUM_IMPL(virNodeDevCap,
52 VIR_NODE_DEV_CAP_LAST,
53 "system",
54 "pci",
55 "usb_device",
56 "usb",
57 "net",
58 "scsi_host",
59 "scsi_target",
60 "scsi",
61 "storage",
62 "fc_host",
63 "vports",
64 "scsi_generic",
65 "drm",
66 "mdev_types",
67 "mdev",
68 "ccw",
69 "css",
70 "vdpa",
71 "ap_card",
72 "ap_queue",
73 "ap_matrix",
74 "vpd",
75 );
76
77 VIR_ENUM_IMPL(virNodeDevNetCap,
78 VIR_NODE_DEV_CAP_NET_LAST,
79 "80203",
80 "80211",
81 );
82
83 VIR_ENUM_IMPL(virNodeDevDRM,
84 VIR_NODE_DEV_DRM_LAST,
85 "primary",
86 "control",
87 "render",
88 );
89
90 static int
virNodeDevCapsDefParseString(const char * xpath,xmlXPathContextPtr ctxt,char ** string)91 virNodeDevCapsDefParseString(const char *xpath,
92 xmlXPathContextPtr ctxt,
93 char **string)
94 {
95 char *s;
96
97 if (!(s = virXPathString(xpath, ctxt)))
98 return -1;
99
100 *string = s;
101 return 0;
102 }
103
104
105 void
virNodeDeviceDefFree(virNodeDeviceDef * def)106 virNodeDeviceDefFree(virNodeDeviceDef *def)
107 {
108 virNodeDevCapsDef *caps;
109
110 if (!def)
111 return;
112
113 g_free(def->name);
114 g_free(def->parent);
115 g_free(def->parent_wwnn);
116 g_free(def->parent_wwpn);
117 g_free(def->parent_fabric_wwn);
118 g_free(def->driver);
119 g_free(def->sysfs_path);
120 g_free(def->parent_sysfs_path);
121 g_free(def->devnode);
122 g_strfreev(def->devlinks);
123
124 caps = def->caps;
125 while (caps) {
126 virNodeDevCapsDef *next = caps->next;
127 virNodeDevCapsDefFree(caps);
128 caps = next;
129 }
130
131 g_free(def);
132 }
133
134
135 static void
virPCIELinkFormat(virBuffer * buf,virPCIELink * lnk,const char * attrib)136 virPCIELinkFormat(virBuffer *buf,
137 virPCIELink *lnk,
138 const char *attrib)
139 {
140 if (!lnk)
141 return;
142
143 virBufferAsprintf(buf, "<link validity='%s'", attrib);
144 if (lnk->port >= 0)
145 virBufferAsprintf(buf, " port='%d'", lnk->port);
146 if (lnk->speed)
147 virBufferAsprintf(buf, " speed='%s'",
148 virPCIELinkSpeedTypeToString(lnk->speed));
149 virBufferAsprintf(buf, " width='%d'", lnk->width);
150 virBufferAddLit(buf, "/>\n");
151 }
152
153
154 static void
virPCIEDeviceInfoFormat(virBuffer * buf,virPCIEDeviceInfo * info)155 virPCIEDeviceInfoFormat(virBuffer *buf,
156 virPCIEDeviceInfo *info)
157 {
158 if (!info->link_cap && !info->link_sta) {
159 virBufferAddLit(buf, "<pci-express/>\n");
160 return;
161 }
162
163 virBufferAddLit(buf, "<pci-express>\n");
164 virBufferAdjustIndent(buf, 2);
165
166 virPCIELinkFormat(buf, info->link_cap, "cap");
167 virPCIELinkFormat(buf, info->link_sta, "sta");
168
169 virBufferAdjustIndent(buf, -2);
170 virBufferAddLit(buf, "</pci-express>\n");
171 }
172
173
174 static void
virNodeDeviceCapSystemDefFormat(virBuffer * buf,const virNodeDevCapData * data)175 virNodeDeviceCapSystemDefFormat(virBuffer *buf,
176 const virNodeDevCapData *data)
177 {
178 char uuidstr[VIR_UUID_STRING_BUFLEN];
179
180 if (data->system.product_name)
181 virBufferEscapeString(buf, "<product>%s</product>\n",
182 data->system.product_name);
183 virBufferAddLit(buf, "<hardware>\n");
184 virBufferAdjustIndent(buf, 2);
185 if (data->system.hardware.vendor_name)
186 virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
187 data->system.hardware.vendor_name);
188 if (data->system.hardware.version)
189 virBufferEscapeString(buf, "<version>%s</version>\n",
190 data->system.hardware.version);
191 if (data->system.hardware.serial)
192 virBufferEscapeString(buf, "<serial>%s</serial>\n",
193 data->system.hardware.serial);
194 virUUIDFormat(data->system.hardware.uuid, uuidstr);
195 virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
196 virBufferAdjustIndent(buf, -2);
197 virBufferAddLit(buf, "</hardware>\n");
198
199 virBufferAddLit(buf, "<firmware>\n");
200 virBufferAdjustIndent(buf, 2);
201 if (data->system.firmware.vendor_name)
202 virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
203 data->system.firmware.vendor_name);
204 if (data->system.firmware.version)
205 virBufferEscapeString(buf, "<version>%s</version>\n",
206 data->system.firmware.version);
207 if (data->system.firmware.release_date)
208 virBufferEscapeString(buf, "<release_date>%s</release_date>\n",
209 data->system.firmware.release_date);
210 virBufferAdjustIndent(buf, -2);
211 virBufferAddLit(buf, "</firmware>\n");
212 }
213
214
215 static void
virNodeDeviceCapMdevTypesFormat(virBuffer * buf,virMediatedDeviceType ** mdev_types,const size_t nmdev_types)216 virNodeDeviceCapMdevTypesFormat(virBuffer *buf,
217 virMediatedDeviceType **mdev_types,
218 const size_t nmdev_types)
219 {
220 size_t i;
221
222 if (nmdev_types > 0) {
223 virBufferAddLit(buf, "<capability type='mdev_types'>\n");
224 virBufferAdjustIndent(buf, 2);
225 for (i = 0; i < nmdev_types; i++) {
226 virMediatedDeviceType *type = mdev_types[i];
227 virBufferEscapeString(buf, "<type id='%s'>\n", type->id);
228 virBufferAdjustIndent(buf, 2);
229 if (type->name)
230 virBufferEscapeString(buf, "<name>%s</name>\n",
231 type->name);
232 virBufferEscapeString(buf, "<deviceAPI>%s</deviceAPI>\n",
233 type->device_api);
234 virBufferAsprintf(buf,
235 "<availableInstances>%u</availableInstances>\n",
236 type->available_instances);
237 virBufferAdjustIndent(buf, -2);
238 virBufferAddLit(buf, "</type>\n");
239 }
240 virBufferAdjustIndent(buf, -2);
241 virBufferAddLit(buf, "</capability>\n");
242 }
243 }
244
245 static void
virNodeDeviceCapVPDFormatCustomVendorField(virPCIVPDResourceCustom * field,virBuffer * buf)246 virNodeDeviceCapVPDFormatCustomVendorField(virPCIVPDResourceCustom *field, virBuffer *buf)
247 {
248 if (field == NULL || field->value == NULL)
249 return;
250
251 virBufferAsprintf(buf, "<vendor_field index='%c'>%s</vendor_field>\n", field->idx,
252 field->value);
253 }
254
255 static void
virNodeDeviceCapVPDFormatCustomSystemField(virPCIVPDResourceCustom * field,virBuffer * buf)256 virNodeDeviceCapVPDFormatCustomSystemField(virPCIVPDResourceCustom *field, virBuffer *buf)
257 {
258 if (field == NULL || field->value == NULL)
259 return;
260
261 virBufferAsprintf(buf, "<system_field index='%c'>%s</system_field>\n", field->idx,
262 field->value);
263 }
264
265 static inline void
virNodeDeviceCapVPDFormatRegularField(virBuffer * buf,const char * keyword,const char * value)266 virNodeDeviceCapVPDFormatRegularField(virBuffer *buf, const char *keyword, const char *value)
267 {
268 if (keyword == NULL || value == NULL)
269 return;
270
271 virBufferAsprintf(buf, "<%s>%s</%s>\n", keyword, value, keyword);
272 }
273
274 static void
virNodeDeviceCapVPDFormat(virBuffer * buf,virPCIVPDResource * res)275 virNodeDeviceCapVPDFormat(virBuffer *buf, virPCIVPDResource *res)
276 {
277 if (res == NULL)
278 return;
279
280 virBufferAddLit(buf, "<capability type='vpd'>\n");
281 virBufferAdjustIndent(buf, 2);
282 virBufferEscapeString(buf, "<name>%s</name>\n", res->name);
283
284 if (res->ro != NULL) {
285 virBufferEscapeString(buf, "<fields access='%s'>\n", "readonly");
286
287 virBufferAdjustIndent(buf, 2);
288 virNodeDeviceCapVPDFormatRegularField(buf, "change_level", res->ro->change_level);
289 virNodeDeviceCapVPDFormatRegularField(buf, "manufacture_id", res->ro->manufacture_id);
290 virNodeDeviceCapVPDFormatRegularField(buf, "part_number", res->ro->part_number);
291 virNodeDeviceCapVPDFormatRegularField(buf, "serial_number", res->ro->serial_number);
292 g_ptr_array_foreach(res->ro->vendor_specific,
293 (GFunc)virNodeDeviceCapVPDFormatCustomVendorField, buf);
294 virBufferAdjustIndent(buf, -2);
295
296 virBufferAddLit(buf, "</fields>\n");
297 }
298
299 if (res->rw != NULL) {
300 virBufferEscapeString(buf, "<fields access='%s'>\n", "readwrite");
301
302 virBufferAdjustIndent(buf, 2);
303 virNodeDeviceCapVPDFormatRegularField(buf, "asset_tag", res->rw->asset_tag);
304 g_ptr_array_foreach(res->rw->vendor_specific,
305 (GFunc)virNodeDeviceCapVPDFormatCustomVendorField, buf);
306 g_ptr_array_foreach(res->rw->system_specific,
307 (GFunc)virNodeDeviceCapVPDFormatCustomSystemField, buf);
308 virBufferAdjustIndent(buf, -2);
309
310 virBufferAddLit(buf, "</fields>\n");
311 }
312
313 virBufferAdjustIndent(buf, -2);
314 virBufferAddLit(buf, "</capability>\n");
315 }
316
317 static void
virNodeDeviceCapPCIDefFormat(virBuffer * buf,const virNodeDevCapData * data)318 virNodeDeviceCapPCIDefFormat(virBuffer *buf,
319 const virNodeDevCapData *data)
320 {
321 size_t i;
322
323 if (data->pci_dev.klass >= 0)
324 virBufferAsprintf(buf, "<class>0x%.6x</class>\n", data->pci_dev.klass);
325 virBufferAsprintf(buf, "<domain>%d</domain>\n",
326 data->pci_dev.domain);
327 virBufferAsprintf(buf, "<bus>%d</bus>\n", data->pci_dev.bus);
328 virBufferAsprintf(buf, "<slot>%d</slot>\n",
329 data->pci_dev.slot);
330 virBufferAsprintf(buf, "<function>%d</function>\n",
331 data->pci_dev.function);
332 virBufferAsprintf(buf, "<product id='0x%04x'",
333 data->pci_dev.product);
334 if (data->pci_dev.product_name)
335 virBufferEscapeString(buf, ">%s</product>\n",
336 data->pci_dev.product_name);
337 else
338 virBufferAddLit(buf, "/>\n");
339 virBufferAsprintf(buf, "<vendor id='0x%04x'",
340 data->pci_dev.vendor);
341 if (data->pci_dev.vendor_name)
342 virBufferEscapeString(buf, ">%s</vendor>\n",
343 data->pci_dev.vendor_name);
344 else
345 virBufferAddLit(buf, "/>\n");
346 if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION) {
347 virBufferAddLit(buf, "<capability type='phys_function'>\n");
348 virBufferAdjustIndent(buf, 2);
349 virBufferAsprintf(buf,
350 "<address domain='0x%04x' bus='0x%02x' "
351 "slot='0x%02x' function='0x%d'/>\n",
352 data->pci_dev.physical_function->domain,
353 data->pci_dev.physical_function->bus,
354 data->pci_dev.physical_function->slot,
355 data->pci_dev.physical_function->function);
356 virBufferAdjustIndent(buf, -2);
357 virBufferAddLit(buf, "</capability>\n");
358 }
359 if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION) {
360 virBufferAddLit(buf, "<capability type='virt_functions'");
361 if (data->pci_dev.max_virtual_functions)
362 virBufferAsprintf(buf, " maxCount='%u'",
363 data->pci_dev.max_virtual_functions);
364 if (data->pci_dev.num_virtual_functions == 0) {
365 virBufferAddLit(buf, "/>\n");
366 } else {
367 virBufferAddLit(buf, ">\n");
368 virBufferAdjustIndent(buf, 2);
369 for (i = 0; i < data->pci_dev.num_virtual_functions; i++) {
370 virBufferAsprintf(buf,
371 "<address domain='0x%04x' bus='0x%02x' "
372 "slot='0x%02x' function='0x%d'/>\n",
373 data->pci_dev.virtual_functions[i]->domain,
374 data->pci_dev.virtual_functions[i]->bus,
375 data->pci_dev.virtual_functions[i]->slot,
376 data->pci_dev.virtual_functions[i]->function);
377 }
378 virBufferAdjustIndent(buf, -2);
379 virBufferAddLit(buf, "</capability>\n");
380 }
381 }
382 if (data->pci_dev.hdrType) {
383 virBufferAsprintf(buf, "<capability type='%s'/>\n",
384 virPCIHeaderTypeToString(data->pci_dev.hdrType));
385 }
386 if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) {
387 virNodeDeviceCapMdevTypesFormat(buf,
388 data->pci_dev.mdev_types,
389 data->pci_dev.nmdev_types);
390 }
391 if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_VPD) {
392 virNodeDeviceCapVPDFormat(buf, data->pci_dev.vpd);
393 }
394 if (data->pci_dev.nIommuGroupDevices) {
395 virBufferAsprintf(buf, "<iommuGroup number='%d'>\n",
396 data->pci_dev.iommuGroupNumber);
397 virBufferAdjustIndent(buf, 2);
398 for (i = 0; i < data->pci_dev.nIommuGroupDevices; i++) {
399 virBufferAsprintf(buf,
400 "<address domain='0x%04x' bus='0x%02x' "
401 "slot='0x%02x' function='0x%d'/>\n",
402 data->pci_dev.iommuGroupDevices[i]->domain,
403 data->pci_dev.iommuGroupDevices[i]->bus,
404 data->pci_dev.iommuGroupDevices[i]->slot,
405 data->pci_dev.iommuGroupDevices[i]->function);
406 }
407 virBufferAdjustIndent(buf, -2);
408 virBufferAddLit(buf, "</iommuGroup>\n");
409 }
410 if (data->pci_dev.numa_node >= 0)
411 virBufferAsprintf(buf, "<numa node='%d'/>\n",
412 data->pci_dev.numa_node);
413
414 if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCIE)
415 virPCIEDeviceInfoFormat(buf, data->pci_dev.pci_express);
416 }
417
418
419 static void
virNodeDeviceCapUSBDevDefFormat(virBuffer * buf,const virNodeDevCapData * data)420 virNodeDeviceCapUSBDevDefFormat(virBuffer *buf,
421 const virNodeDevCapData *data)
422 {
423 virBufferAsprintf(buf, "<bus>%d</bus>\n", data->usb_dev.bus);
424 virBufferAsprintf(buf, "<device>%d</device>\n",
425 data->usb_dev.device);
426 virBufferAsprintf(buf, "<product id='0x%04x'",
427 data->usb_dev.product);
428 if (data->usb_dev.product_name)
429 virBufferEscapeString(buf, ">%s</product>\n",
430 data->usb_dev.product_name);
431 else
432 virBufferAddLit(buf, " />\n");
433 virBufferAsprintf(buf, "<vendor id='0x%04x'",
434 data->usb_dev.vendor);
435 if (data->usb_dev.vendor_name)
436 virBufferEscapeString(buf, ">%s</vendor>\n",
437 data->usb_dev.vendor_name);
438 else
439 virBufferAddLit(buf, " />\n");
440 }
441
442
443 static void
virNodeDeviceCapUSBInterfaceDefFormat(virBuffer * buf,const virNodeDevCapData * data)444 virNodeDeviceCapUSBInterfaceDefFormat(virBuffer *buf,
445 const virNodeDevCapData *data)
446 {
447 virBufferAsprintf(buf, "<number>%d</number>\n",
448 data->usb_if.number);
449 virBufferAsprintf(buf, "<class>%d</class>\n",
450 data->usb_if.klass);
451 virBufferAsprintf(buf, "<subclass>%d</subclass>\n",
452 data->usb_if.subclass);
453 virBufferAsprintf(buf, "<protocol>%d</protocol>\n",
454 data->usb_if.protocol);
455 if (data->usb_if.description)
456 virBufferEscapeString(buf,
457 "<description>%s</description>\n",
458 data->usb_if.description);
459 }
460
461
462 static void
virNodeDeviceCapNetDefFormat(virBuffer * buf,const virNodeDevCapData * data)463 virNodeDeviceCapNetDefFormat(virBuffer *buf,
464 const virNodeDevCapData *data)
465 {
466 size_t i;
467
468 virBufferEscapeString(buf, "<interface>%s</interface>\n",
469 data->net.ifname);
470 if (data->net.address)
471 virBufferEscapeString(buf, "<address>%s</address>\n",
472 data->net.address);
473 virInterfaceLinkFormat(buf, &data->net.lnk);
474 if (data->net.features) {
475 for (i = 0; i < VIR_NET_DEV_FEAT_LAST; i++) {
476 if (virBitmapIsBitSet(data->net.features, i)) {
477 virBufferAsprintf(buf, "<feature name='%s'/>\n",
478 virNetDevFeatureTypeToString(i));
479 }
480 }
481 }
482 if (data->net.subtype != VIR_NODE_DEV_CAP_NET_LAST) {
483 const char *subtyp =
484 virNodeDevNetCapTypeToString(data->net.subtype);
485 virBufferEscapeString(buf, "<capability type='%s'/>\n",
486 subtyp);
487 }
488 }
489
490
491 static void
virNodeDeviceCapSCSIHostDefFormat(virBuffer * buf,const virNodeDevCapData * data)492 virNodeDeviceCapSCSIHostDefFormat(virBuffer *buf,
493 const virNodeDevCapData *data)
494 {
495 virBufferAsprintf(buf, "<host>%d</host>\n",
496 data->scsi_host.host);
497 if (data->scsi_host.unique_id != -1)
498 virBufferAsprintf(buf, "<unique_id>%d</unique_id>\n",
499 data->scsi_host.unique_id);
500 if (data->scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
501 virBufferAddLit(buf, "<capability type='fc_host'>\n");
502 virBufferAdjustIndent(buf, 2);
503 virBufferEscapeString(buf, "<wwnn>%s</wwnn>\n",
504 data->scsi_host.wwnn);
505 virBufferEscapeString(buf, "<wwpn>%s</wwpn>\n",
506 data->scsi_host.wwpn);
507 virBufferEscapeString(buf, "<fabric_wwn>%s</fabric_wwn>\n",
508 data->scsi_host.fabric_wwn);
509 virBufferAdjustIndent(buf, -2);
510 virBufferAddLit(buf, "</capability>\n");
511 }
512 if (data->scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS) {
513 virBufferAddLit(buf, "<capability type='vport_ops'>\n");
514 virBufferAdjustIndent(buf, 2);
515 virBufferAsprintf(buf, "<max_vports>%d</max_vports>\n",
516 data->scsi_host.max_vports);
517 virBufferAsprintf(buf, "<vports>%d</vports>\n",
518 data->scsi_host.vports);
519 virBufferAdjustIndent(buf, -2);
520 virBufferAddLit(buf, "</capability>\n");
521 }
522 }
523
524
525 static void
virNodeDeviceCapSCSIDefFormat(virBuffer * buf,const virNodeDevCapData * data)526 virNodeDeviceCapSCSIDefFormat(virBuffer *buf,
527 const virNodeDevCapData *data)
528 {
529 virBufferAsprintf(buf, "<host>%d</host>\n", data->scsi.host);
530 virBufferAsprintf(buf, "<bus>%d</bus>\n", data->scsi.bus);
531 virBufferAsprintf(buf, "<target>%d</target>\n",
532 data->scsi.target);
533 virBufferAsprintf(buf, "<lun>%d</lun>\n", data->scsi.lun);
534 if (data->scsi.type)
535 virBufferEscapeString(buf, "<type>%s</type>\n",
536 data->scsi.type);
537 }
538
539
540 static void
virNodeDeviceCapStorageDefFormat(virBuffer * buf,const virNodeDevCapData * data)541 virNodeDeviceCapStorageDefFormat(virBuffer *buf,
542 const virNodeDevCapData *data)
543 {
544 virBufferEscapeString(buf, "<block>%s</block>\n",
545 data->storage.block);
546 if (data->storage.bus)
547 virBufferEscapeString(buf, "<bus>%s</bus>\n",
548 data->storage.bus);
549 if (data->storage.drive_type)
550 virBufferEscapeString(buf, "<drive_type>%s</drive_type>\n",
551 data->storage.drive_type);
552 if (data->storage.model)
553 virBufferEscapeString(buf, "<model>%s</model>\n",
554 data->storage.model);
555 if (data->storage.vendor)
556 virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
557 data->storage.vendor);
558 if (data->storage.serial)
559 virBufferEscapeString(buf, "<serial>%s</serial>\n",
560 data->storage.serial);
561 if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_REMOVABLE) {
562 int avl = data->storage.flags &
563 VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
564 virBufferAddLit(buf, "<capability type='removable'>\n");
565 virBufferAdjustIndent(buf, 2);
566 virBufferAsprintf(buf, "<media_available>%d"
567 "</media_available>\n", avl ? 1 : 0);
568 virBufferAsprintf(buf, "<media_size>%llu</media_size>\n",
569 data->storage.removable_media_size);
570 if (data->storage.media_label)
571 virBufferEscapeString(buf,
572 "<media_label>%s</media_label>\n",
573 data->storage.media_label);
574 if (data->storage.logical_block_size > 0)
575 virBufferAsprintf(buf, "<logical_block_size>%llu"
576 "</logical_block_size>\n",
577 data->storage.logical_block_size);
578 if (data->storage.num_blocks > 0)
579 virBufferAsprintf(buf,
580 "<num_blocks>%llu</num_blocks>\n",
581 data->storage.num_blocks);
582 virBufferAdjustIndent(buf, -2);
583 virBufferAddLit(buf, "</capability>\n");
584 } else {
585 virBufferAsprintf(buf, "<size>%llu</size>\n",
586 data->storage.size);
587 if (data->storage.logical_block_size > 0)
588 virBufferAsprintf(buf, "<logical_block_size>%llu"
589 "</logical_block_size>\n",
590 data->storage.logical_block_size);
591 if (data->storage.num_blocks > 0)
592 virBufferAsprintf(buf, "<num_blocks>%llu</num_blocks>\n",
593 data->storage.num_blocks);
594 }
595 if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE)
596 virBufferAddLit(buf, "<capability type='hotpluggable'/>\n");
597 }
598
599 static void
virNodeDeviceCapMdevDefFormat(virBuffer * buf,const virNodeDevCapData * data)600 virNodeDeviceCapMdevDefFormat(virBuffer *buf,
601 const virNodeDevCapData *data)
602 {
603 size_t i;
604
605 virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.type);
606 virBufferEscapeString(buf, "<uuid>%s</uuid>\n", data->mdev.uuid);
607 virBufferAsprintf(buf, "<iommuGroup number='%u'/>\n",
608 data->mdev.iommuGroupNumber);
609
610 for (i = 0; i < data->mdev.nattributes; i++) {
611 virMediatedDeviceAttr *attr = data->mdev.attributes[i];
612 virBufferAsprintf(buf, "<attr name='%s' value='%s'/>\n",
613 attr->name, attr->value);
614 }
615 }
616
617 static void
virNodeDeviceCapVDPADefFormat(virBuffer * buf,const virNodeDevCapData * data)618 virNodeDeviceCapVDPADefFormat(virBuffer *buf,
619 const virNodeDevCapData *data)
620 {
621 virBufferEscapeString(buf, "<chardev>%s</chardev>\n", data->vdpa.chardev);
622 }
623
624
625 static void
virNodeDeviceCapCCWDefFormat(virBuffer * buf,const virNodeDevCapData * data)626 virNodeDeviceCapCCWDefFormat(virBuffer *buf,
627 const virNodeDevCapData *data)
628 {
629 virBufferAsprintf(buf, "<cssid>0x%x</cssid>\n",
630 data->ccw_dev.cssid);
631 virBufferAsprintf(buf, "<ssid>0x%x</ssid>\n",
632 data->ccw_dev.ssid);
633 virBufferAsprintf(buf, "<devno>0x%04x</devno>\n",
634 data->ccw_dev.devno);
635 if (data->ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV)
636 virNodeDeviceCapMdevTypesFormat(buf,
637 data->ccw_dev.mdev_types,
638 data->ccw_dev.nmdev_types);
639 }
640
641
642 char *
virNodeDeviceDefFormat(const virNodeDeviceDef * def)643 virNodeDeviceDefFormat(const virNodeDeviceDef *def)
644 {
645 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
646 virNodeDevCapsDef *caps;
647 size_t i = 0;
648
649 virBufferAddLit(&buf, "<device>\n");
650 virBufferAdjustIndent(&buf, 2);
651 virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
652 virBufferEscapeString(&buf, "<path>%s</path>\n", def->sysfs_path);
653 if (def->devnode)
654 virBufferEscapeString(&buf, "<devnode type='dev'>%s</devnode>\n",
655 def->devnode);
656 if (def->devlinks) {
657 for (i = 0; def->devlinks[i]; i++)
658 virBufferEscapeString(&buf, "<devnode type='link'>%s</devnode>\n",
659 def->devlinks[i]);
660 }
661 if (def->parent)
662 virBufferEscapeString(&buf, "<parent>%s</parent>\n", def->parent);
663 if (def->driver) {
664 virBufferAddLit(&buf, "<driver>\n");
665 virBufferAdjustIndent(&buf, 2);
666 virBufferEscapeString(&buf, "<name>%s</name>\n", def->driver);
667 virBufferAdjustIndent(&buf, -2);
668 virBufferAddLit(&buf, "</driver>\n");
669 }
670
671 for (caps = def->caps; caps; caps = caps->next) {
672 virNodeDevCapData *data = &caps->data;
673
674 virBufferAsprintf(&buf, "<capability type='%s'>\n",
675 virNodeDevCapTypeToString(caps->data.type));
676 virBufferAdjustIndent(&buf, 2);
677 switch (caps->data.type) {
678 case VIR_NODE_DEV_CAP_SYSTEM:
679 virNodeDeviceCapSystemDefFormat(&buf, data);
680 break;
681 case VIR_NODE_DEV_CAP_PCI_DEV:
682 virNodeDeviceCapPCIDefFormat(&buf, data);
683 break;
684 case VIR_NODE_DEV_CAP_USB_DEV:
685 virNodeDeviceCapUSBDevDefFormat(&buf, data);
686 break;
687 case VIR_NODE_DEV_CAP_USB_INTERFACE:
688 virNodeDeviceCapUSBInterfaceDefFormat(&buf, data);
689 break;
690 case VIR_NODE_DEV_CAP_NET:
691 virNodeDeviceCapNetDefFormat(&buf, data);
692 break;
693 case VIR_NODE_DEV_CAP_SCSI_HOST:
694 virNodeDeviceCapSCSIHostDefFormat(&buf, data);
695 break;
696 case VIR_NODE_DEV_CAP_SCSI_TARGET:
697 virBufferEscapeString(&buf, "<target>%s</target>\n",
698 data->scsi_target.name);
699 if (data->scsi_target.flags & VIR_NODE_DEV_CAP_FLAG_FC_RPORT) {
700 virBufferAddLit(&buf, "<capability type='fc_remote_port'>\n");
701 virBufferAdjustIndent(&buf, 2);
702 virBufferAsprintf(&buf, "<rport>%s</rport>\n",
703 data->scsi_target.rport);
704 virBufferAsprintf(&buf, "<wwpn>%s</wwpn>\n",
705 data->scsi_target.wwpn);
706 virBufferAdjustIndent(&buf, -2);
707 virBufferAddLit(&buf, "</capability>\n");
708 }
709 break;
710 case VIR_NODE_DEV_CAP_SCSI:
711 virNodeDeviceCapSCSIDefFormat(&buf, data);
712 break;
713 case VIR_NODE_DEV_CAP_STORAGE:
714 virNodeDeviceCapStorageDefFormat(&buf, data);
715 break;
716 case VIR_NODE_DEV_CAP_SCSI_GENERIC:
717 virBufferEscapeString(&buf, "<char>%s</char>\n",
718 data->sg.path);
719 break;
720 case VIR_NODE_DEV_CAP_DRM:
721 virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
722 break;
723 case VIR_NODE_DEV_CAP_MDEV:
724 virNodeDeviceCapMdevDefFormat(&buf, data);
725 break;
726 case VIR_NODE_DEV_CAP_CCW_DEV:
727 case VIR_NODE_DEV_CAP_CSS_DEV:
728 virNodeDeviceCapCCWDefFormat(&buf, data);
729 break;
730 case VIR_NODE_DEV_CAP_VDPA:
731 virNodeDeviceCapVDPADefFormat(&buf, data);
732 break;
733 case VIR_NODE_DEV_CAP_AP_CARD:
734 virBufferAsprintf(&buf, "<ap-adapter>0x%02x</ap-adapter>\n",
735 data->ap_card.ap_adapter);
736 break;
737 case VIR_NODE_DEV_CAP_AP_QUEUE:
738 virBufferAsprintf(&buf, "<ap-adapter>0x%02x</ap-adapter>\n",
739 data->ap_queue.ap_adapter);
740 virBufferAsprintf(&buf, "<ap-domain>0x%04x</ap-domain>\n",
741 data->ap_queue.ap_domain);
742 break;
743 case VIR_NODE_DEV_CAP_AP_MATRIX:
744 if (data->ap_matrix.flags & VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV)
745 virNodeDeviceCapMdevTypesFormat(&buf,
746 data->ap_matrix.mdev_types,
747 data->ap_matrix.nmdev_types);
748
749 case VIR_NODE_DEV_CAP_MDEV_TYPES:
750 case VIR_NODE_DEV_CAP_FC_HOST:
751 case VIR_NODE_DEV_CAP_VPORTS:
752 case VIR_NODE_DEV_CAP_VPD:
753 case VIR_NODE_DEV_CAP_LAST:
754 break;
755 }
756
757 virBufferAdjustIndent(&buf, -2);
758 virBufferAddLit(&buf, "</capability>\n");
759 }
760
761 virBufferAdjustIndent(&buf, -2);
762 virBufferAddLit(&buf, "</device>\n");
763
764 return virBufferContentAndReset(&buf);
765 }
766
767
768 /**
769 * virNodeDevCapsDefParseIntOptional:
770 * @xpath: XPath to evaluate
771 * @ctxt: Context
772 * @value: Where to store parsed value
773 * @def: Node device which is parsed
774 * @invalid_error_fmt: error message to print on invalid format
775 *
776 * Returns: -1 on error (invalid int format under @xpath)
777 * 0 if @xpath was not found (@value is untouched)
778 * 1 on success
779 */
780 static int
virNodeDevCapsDefParseIntOptional(const char * xpath,xmlXPathContextPtr ctxt,int * value,virNodeDeviceDef * def,const char * invalid_error_fmt)781 virNodeDevCapsDefParseIntOptional(const char *xpath,
782 xmlXPathContextPtr ctxt,
783 int *value,
784 virNodeDeviceDef *def,
785 const char *invalid_error_fmt)
786 {
787 int ret;
788 int val;
789
790 ret = virXPathInt(xpath, ctxt, &val);
791 if (ret < -1) {
792 virReportError(VIR_ERR_INTERNAL_ERROR,
793 invalid_error_fmt,
794 def->name);
795 return -1;
796 } else if (ret == -1) {
797 return 0;
798 }
799 *value = val;
800 return 1;
801 }
802
803
804 static int
virNodeDevCapsDefParseULong(const char * xpath,xmlXPathContextPtr ctxt,unsigned * value,virNodeDeviceDef * def,const char * missing_error_fmt,const char * invalid_error_fmt)805 virNodeDevCapsDefParseULong(const char *xpath,
806 xmlXPathContextPtr ctxt,
807 unsigned *value,
808 virNodeDeviceDef *def,
809 const char *missing_error_fmt,
810 const char *invalid_error_fmt)
811 {
812 int ret;
813 unsigned long val;
814
815 ret = virXPathULong(xpath, ctxt, &val);
816 if (ret < 0) {
817 virReportError(VIR_ERR_INTERNAL_ERROR,
818 ret == -1 ? missing_error_fmt : invalid_error_fmt,
819 def->name);
820 return -1;
821 }
822
823 *value = val;
824 return 0;
825 }
826
827
828 static int
virNodeDevCapsDefParseULongLong(const char * xpath,xmlXPathContextPtr ctxt,unsigned long long * value,virNodeDeviceDef * def,const char * missing_error_fmt,const char * invalid_error_fmt)829 virNodeDevCapsDefParseULongLong(const char *xpath,
830 xmlXPathContextPtr ctxt,
831 unsigned long long *value,
832 virNodeDeviceDef *def,
833 const char *missing_error_fmt,
834 const char *invalid_error_fmt)
835 {
836 int ret;
837 unsigned long long val;
838
839 ret = virXPathULongLong(xpath, ctxt, &val);
840 if (ret < 0) {
841 virReportError(VIR_ERR_INTERNAL_ERROR,
842 ret == -1 ? missing_error_fmt : invalid_error_fmt,
843 def->name);
844 return -1;
845 }
846
847 *value = val;
848 return 0;
849 }
850
851
852 static int
virNodeDevCapDRMParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapDRM * drm)853 virNodeDevCapDRMParseXML(xmlXPathContextPtr ctxt,
854 virNodeDeviceDef *def,
855 xmlNodePtr node,
856 virNodeDevCapDRM *drm)
857 {
858 VIR_XPATH_NODE_AUTORESTORE(ctxt)
859 int val;
860 g_autofree char *type = NULL;
861
862 ctxt->node = node;
863
864 type = virXPathString("string(./type[1])", ctxt);
865
866 if ((val = virNodeDevDRMTypeFromString(type)) < 0) {
867 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
868 _("unknown drm type '%s' for '%s'"), type, def->name);
869 return -1;
870 }
871 drm->type = val;
872
873 return 0;
874 }
875
876
877 static int
virNodeDevCapMdevTypesParseXML(xmlXPathContextPtr ctxt,virMediatedDeviceType *** mdev_types,size_t * nmdev_types)878 virNodeDevCapMdevTypesParseXML(xmlXPathContextPtr ctxt,
879 virMediatedDeviceType ***mdev_types,
880 size_t *nmdev_types)
881 {
882 int ret = -1;
883 xmlNodePtr orignode = NULL;
884 g_autofree xmlNodePtr *nodes = NULL;
885 int ntypes = -1;
886 virMediatedDeviceType *type = NULL;
887 size_t i;
888
889 if ((ntypes = virXPathNodeSet("./type", ctxt, &nodes)) < 0)
890 goto cleanup;
891
892 if (nmdev_types == 0) {
893 virReportError(VIR_ERR_XML_ERROR, "%s",
894 _("missing <type> element in <capability> element"));
895 goto cleanup;
896 }
897
898 orignode = ctxt->node;
899 for (i = 0; i < ntypes; i++) {
900 ctxt->node = nodes[i];
901
902 type = g_new0(virMediatedDeviceType, 1);
903
904 if (!(type->id = virXPathString("string(./@id[1])", ctxt))) {
905 virReportError(VIR_ERR_XML_ERROR, "%s",
906 _("missing 'id' attribute for mediated device's "
907 "<type> element"));
908 goto cleanup;
909 }
910
911 if (!(type->device_api = virXPathString("string(./deviceAPI[1])", ctxt))) {
912 virReportError(VIR_ERR_XML_ERROR,
913 _("missing device API for mediated device type '%s'"),
914 type->id);
915 goto cleanup;
916 }
917
918 if (virXPathUInt("number(./availableInstances)", ctxt,
919 &type->available_instances) < 0) {
920 virReportError(VIR_ERR_XML_ERROR,
921 _("missing number of available instances for "
922 "mediated device type '%s'"),
923 type->id);
924 goto cleanup;
925 }
926
927 type->name = virXPathString("string(./name)", ctxt);
928
929 VIR_APPEND_ELEMENT(*mdev_types, *nmdev_types, type);
930 }
931
932 ret = 0;
933 cleanup:
934 virMediatedDeviceTypeFree(type);
935 ctxt->node = orignode;
936 return ret;
937 }
938
939 static int
virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt,virPCIVPDResource * res,bool readOnly)940 virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt, virPCIVPDResource *res, bool readOnly)
941 {
942 int nfields = -1;
943 g_autofree xmlNodePtr *nodes = NULL;
944 size_t i = 0;
945
946 if ((nfields = virXPathNodeSet("./vendor_field[@index]", ctxt, &nodes)) < 0) {
947 virReportError(VIR_ERR_XML_ERROR, "%s",
948 _("failed to evaluate <vendor_field> elements"));
949 return -1;
950 }
951 for (i = 0; i < nfields; i++) {
952 g_autofree char *value = NULL;
953 g_autofree char *index = NULL;
954 VIR_XPATH_NODE_AUTORESTORE(ctxt)
955 g_autofree char *keyword = NULL;
956
957 ctxt->node = nodes[i];
958 if (!(index = virXPathString("string(./@index[1])", ctxt)) ||
959 strlen(index) > 1) {
960 virReportError(VIR_ERR_XML_ERROR, "%s",
961 _("<vendor_field> evaluation has failed"));
962 continue;
963 }
964 if (!(value = virXPathString("string(./text())", ctxt))) {
965 virReportError(VIR_ERR_XML_ERROR, "%s",
966 _("<vendor_field> value evaluation has failed"));
967 continue;
968 }
969 keyword = g_strdup_printf("V%c", index[0]);
970 virPCIVPDResourceUpdateKeyword(res, readOnly, keyword, value);
971 }
972 VIR_FREE(nodes);
973
974 if (!readOnly) {
975 if ((nfields = virXPathNodeSet("./system_field[@index]", ctxt, &nodes)) < 0) {
976 virReportError(VIR_ERR_XML_ERROR, "%s",
977 _("failed to evaluate <system_field> elements"));
978 return -1;
979 }
980 for (i = 0; i < nfields; i++) {
981 g_autofree char *value = NULL;
982 g_autofree char *index = NULL;
983 g_autofree char *keyword = NULL;
984 VIR_XPATH_NODE_AUTORESTORE(ctxt);
985
986 ctxt->node = nodes[i];
987 if (!(index = virXPathString("string(./@index[1])", ctxt)) ||
988 strlen(index) > 1) {
989 virReportError(VIR_ERR_XML_ERROR, "%s",
990 _("<system_field> evaluation has failed"));
991 continue;
992 }
993 if (!(value = virXPathString("string(./text())", ctxt))) {
994 virReportError(VIR_ERR_XML_ERROR, "%s",
995 _("<system_field> value evaluation has failed"));
996 continue;
997 }
998 keyword = g_strdup_printf("Y%c", index[0]);
999 virPCIVPDResourceUpdateKeyword(res, readOnly, keyword, value);
1000 }
1001 }
1002
1003 return 0;
1004 }
1005
1006 static int
virNodeDeviceCapVPDParseReadOnlyFields(xmlXPathContextPtr ctxt,virPCIVPDResource * res)1007 virNodeDeviceCapVPDParseReadOnlyFields(xmlXPathContextPtr ctxt, virPCIVPDResource *res)
1008 {
1009 const char *keywords[] = {"change_level", "manufacture_id",
1010 "serial_number", "part_number", NULL};
1011 size_t i = 0;
1012
1013 if (res == NULL)
1014 return -1;
1015
1016 res->ro = virPCIVPDResourceRONew();
1017
1018 while (keywords[i]) {
1019 g_autofree char *expression = g_strdup_printf("string(./%s)", keywords[i]);
1020 g_autofree char *result = virXPathString(expression, ctxt);
1021
1022 virPCIVPDResourceUpdateKeyword(res, true, keywords[i], result);
1023 ++i;
1024 }
1025 if (virNodeDeviceCapVPDParseCustomFields(ctxt, res, true) < 0)
1026 return -1;
1027
1028 return 0;
1029 }
1030
1031 static int
virNodeDeviceCapVPDParseReadWriteFields(xmlXPathContextPtr ctxt,virPCIVPDResource * res)1032 virNodeDeviceCapVPDParseReadWriteFields(xmlXPathContextPtr ctxt, virPCIVPDResource *res)
1033 {
1034 g_autofree char *assetTag = virXPathString("string(./asset_tag)", ctxt);
1035 res->rw = virPCIVPDResourceRWNew();
1036 virPCIVPDResourceUpdateKeyword(res, false, "asset_tag", assetTag);
1037 if (virNodeDeviceCapVPDParseCustomFields(ctxt, res, false) < 0)
1038 return -1;
1039
1040 return 0;
1041 }
1042
1043 static int
virNodeDeviceCapVPDParseXML(xmlXPathContextPtr ctxt,virPCIVPDResource ** res)1044 virNodeDeviceCapVPDParseXML(xmlXPathContextPtr ctxt, virPCIVPDResource **res)
1045 {
1046 g_autofree xmlNodePtr *nodes = NULL;
1047 int nfields = -1;
1048 size_t i = 0;
1049 g_autoptr(virPCIVPDResource) newres = g_new0(virPCIVPDResource, 1);
1050
1051 if (res == NULL)
1052 return -1;
1053
1054 if (!(newres->name = virXPathString("string(./name)", ctxt))) {
1055 virReportError(VIR_ERR_XML_ERROR, "%s",
1056 _("Could not read a device name from the <name> element"));
1057 return -1;
1058 }
1059
1060 if ((nfields = virXPathNodeSet("./fields[@access]", ctxt, &nodes)) < 0) {
1061 virReportError(VIR_ERR_XML_ERROR, "%s",
1062 _("no VPD <fields> elements with an access type attribute found"));
1063 return -1;
1064 }
1065
1066 for (i = 0; i < nfields; i++) {
1067 g_autofree char *access = NULL;
1068 VIR_XPATH_NODE_AUTORESTORE(ctxt);
1069
1070 ctxt->node = nodes[i];
1071 if (!(access = virXPathString("string(./@access[1])", ctxt))) {
1072 virReportError(VIR_ERR_XML_ERROR, "%s",
1073 _("VPD fields access type parsing has failed"));
1074 return -1;
1075 }
1076
1077 if (STREQ(access, "readonly")) {
1078 if (virNodeDeviceCapVPDParseReadOnlyFields(ctxt, newres) < 0) {
1079 virReportError(VIR_ERR_XML_ERROR,
1080 _("Could not parse %s VPD resource fields"), access);
1081 return -1;
1082 }
1083 } else if (STREQ(access, "readwrite")) {
1084 if (virNodeDeviceCapVPDParseReadWriteFields(ctxt, newres) < 0) {
1085 virReportError(VIR_ERR_XML_ERROR,
1086 _("Could not parse %s VPD resource fields"), access);
1087 return -1;
1088 }
1089 } else {
1090 virReportError(VIR_ERR_XML_ERROR, _("Unsupported VPD field access type specified %s"),
1091 access);
1092 return -1;
1093 }
1094 }
1095
1096 /* Replace the existing VPD representation if there is one already. */
1097 if (*res != NULL)
1098 virPCIVPDResourceFree(*res);
1099
1100 *res = g_steal_pointer(&newres);
1101 return 0;
1102 }
1103
1104 static int
virNodeDevAPMatrixCapabilityParseXML(xmlXPathContextPtr ctxt,xmlNodePtr node,virNodeDevCapAPMatrix * apm_dev)1105 virNodeDevAPMatrixCapabilityParseXML(xmlXPathContextPtr ctxt,
1106 xmlNodePtr node,
1107 virNodeDevCapAPMatrix *apm_dev)
1108 {
1109 g_autofree char *type = virXMLPropString(node, "type");
1110 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1111
1112 ctxt->node = node;
1113
1114 if (!type) {
1115 virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
1116 return -1;
1117 }
1118
1119 if (STREQ(type, "mdev_types")) {
1120 if (virNodeDevCapMdevTypesParseXML(ctxt,
1121 &apm_dev->mdev_types,
1122 &apm_dev->nmdev_types) < 0)
1123 return -1;
1124 apm_dev->flags |= VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV;
1125 }
1126
1127 return 0;
1128 }
1129
1130
1131 static int
virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,xmlNodePtr node,virNodeDevCapCCW * ccw_dev)1132 virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
1133 xmlNodePtr node,
1134 virNodeDevCapCCW *ccw_dev)
1135 {
1136 g_autofree char *type = virXMLPropString(node, "type");
1137 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1138
1139 ctxt->node = node;
1140
1141 if (!type) {
1142 virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
1143 return -1;
1144 }
1145
1146 if (STREQ(type, "mdev_types")) {
1147 if (virNodeDevCapMdevTypesParseXML(ctxt,
1148 &ccw_dev->mdev_types,
1149 &ccw_dev->nmdev_types) < 0)
1150 return -1;
1151 ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
1152 }
1153
1154 return 0;
1155 }
1156
1157
1158 static int
virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapCCW * ccw_dev)1159 virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
1160 virNodeDeviceDef *def,
1161 xmlNodePtr node,
1162 virNodeDevCapCCW *ccw_dev)
1163 {
1164 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1165 g_autofree xmlNodePtr *nodes = NULL;
1166 int n = 0;
1167 size_t i = 0;
1168 g_autofree char *cssid = NULL;
1169 g_autofree char *ssid = NULL;
1170 g_autofree char *devno = NULL;
1171
1172 ctxt->node = node;
1173
1174 if (!(cssid = virXPathString("string(./cssid[1])", ctxt))) {
1175 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1176 _("missing cssid value for '%s'"), def->name);
1177 return -1;
1178 }
1179
1180 if (virStrToLong_uip(cssid, NULL, 0, &ccw_dev->cssid) < 0) {
1181 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1182 _("invalid cssid value '%s' for '%s'"),
1183 cssid, def->name);
1184 return -1;
1185 }
1186
1187 if (!(ssid = virXPathString("string(./ssid[1])", ctxt))) {
1188 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1189 _("missing ssid value for '%s'"), def->name);
1190 return -1;
1191 }
1192
1193 if (virStrToLong_uip(ssid, NULL, 0, &ccw_dev->ssid) < 0) {
1194 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1195 _("invalid ssid value '%s' for '%s'"),
1196 cssid, def->name);
1197 return -1;
1198 }
1199
1200 if (!(devno = virXPathString("string(./devno[1])", ctxt))) {
1201 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1202 _("missing devno value for '%s'"), def->name);
1203 return -1;
1204 }
1205
1206 if (virStrToLong_uip(devno, NULL, 16, &ccw_dev->devno) < 0) {
1207 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1208 _("invalid devno value '%s' for '%s'"),
1209 devno, def->name);
1210 return -1;
1211 }
1212
1213 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
1214 return -1;
1215
1216 for (i = 0; i < n; i++) {
1217 if (virNodeDevCSSCapabilityParseXML(ctxt, nodes[i], ccw_dev) < 0)
1218 return -1;
1219 }
1220
1221 return 0;
1222 }
1223
1224
1225 static int
virNodeDevCapAPAdapterParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,unsigned int * ap_adapter)1226 virNodeDevCapAPAdapterParseXML(xmlXPathContextPtr ctxt,
1227 virNodeDeviceDef *def,
1228 unsigned int *ap_adapter)
1229 {
1230 g_autofree char *adapter = NULL;
1231
1232 if (!(adapter = virXPathString("string(./ap-adapter[1])", ctxt))) {
1233 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1234 _("missing ap-adapter value for '%s'"), def->name);
1235 return -1;
1236 }
1237
1238 if (virStrToLong_uip(adapter, NULL, 0, ap_adapter) < 0) {
1239 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1240 _("invalid ap-adapter value '%s' for '%s'"),
1241 adapter, def->name);
1242 return -1;
1243 }
1244
1245 return 0;
1246 }
1247
1248
1249 static int
virNodeDevCapAPCardParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapAPCard * ap_card)1250 virNodeDevCapAPCardParseXML(xmlXPathContextPtr ctxt,
1251 virNodeDeviceDef *def,
1252 xmlNodePtr node,
1253 virNodeDevCapAPCard *ap_card)
1254 {
1255 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1256 ctxt->node = node;
1257
1258 return virNodeDevCapAPAdapterParseXML(ctxt, def, &ap_card->ap_adapter);
1259 }
1260
1261
1262 static int
virNodeDevCapAPQueueParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapAPQueue * ap_queue)1263 virNodeDevCapAPQueueParseXML(xmlXPathContextPtr ctxt,
1264 virNodeDeviceDef *def,
1265 xmlNodePtr node,
1266 virNodeDevCapAPQueue *ap_queue)
1267 {
1268 int ret = -1;
1269 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1270 g_autofree char *dom = NULL;
1271
1272 ctxt->node = node;
1273
1274 ret = virNodeDevCapAPAdapterParseXML(ctxt, def, &ap_queue->ap_adapter);
1275
1276 if (ret < 0)
1277 return ret;
1278
1279 if (!(dom = virXPathString("string(./ap-domain[1])", ctxt))) {
1280 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1281 _("missing ap-domain value for '%s'"), def->name);
1282 return -1;
1283 }
1284
1285 if (virStrToLong_uip(dom, NULL, 0, &ap_queue->ap_domain) < 0) {
1286 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1287 _("invalid ap-domain value '%s' for '%s'"),
1288 dom, def->name);
1289 return -1;
1290 }
1291
1292 if (ap_queue->ap_domain > 255) {
1293 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1294 _("ap-domain value '%s' is out of range for '%s'"),
1295 dom, def->name);
1296 return -1;
1297 }
1298
1299 return 0;
1300 }
1301
1302
1303 static int
virNodeDevCapAPMatrixParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def G_GNUC_UNUSED,xmlNodePtr node,virNodeDevCapAPMatrix * ap_matrix)1304 virNodeDevCapAPMatrixParseXML(xmlXPathContextPtr ctxt,
1305 virNodeDeviceDef *def G_GNUC_UNUSED,
1306 xmlNodePtr node,
1307 virNodeDevCapAPMatrix *ap_matrix)
1308 {
1309 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1310 g_autofree xmlNodePtr *nodes = NULL;
1311 int n = 0;
1312 size_t i = 0;
1313
1314 ctxt->node = node;
1315
1316 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
1317 return -1;
1318
1319 for (i = 0; i < n; i++) {
1320 if (virNodeDevAPMatrixCapabilityParseXML(ctxt, nodes[i], ap_matrix) < 0)
1321 return -1;
1322 }
1323
1324 return 0;
1325 }
1326
1327
1328 static int
virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapStorage * storage)1329 virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,
1330 virNodeDeviceDef *def,
1331 xmlNodePtr node,
1332 virNodeDevCapStorage *storage)
1333 {
1334 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1335 g_autofree xmlNodePtr *nodes = NULL;
1336 size_t i;
1337 int n;
1338 unsigned long long val;
1339
1340 ctxt->node = node;
1341
1342 storage->block = virXPathString("string(./block[1])", ctxt);
1343 if (!storage->block) {
1344 virReportError(VIR_ERR_INTERNAL_ERROR,
1345 _("no block device path supplied for '%s'"),
1346 def->name);
1347 return -1;
1348 }
1349
1350 storage->bus = virXPathString("string(./bus[1])", ctxt);
1351 storage->drive_type = virXPathString("string(./drive_type[1])", ctxt);
1352 storage->model = virXPathString("string(./model[1])", ctxt);
1353 storage->vendor = virXPathString("string(./vendor[1])", ctxt);
1354 storage->serial = virXPathString("string(./serial[1])", ctxt);
1355
1356 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
1357 return -1;
1358
1359 for (i = 0; i < n; i++) {
1360 g_autofree char *type = virXMLPropString(nodes[i], "type");
1361
1362 if (!type) {
1363 virReportError(VIR_ERR_INTERNAL_ERROR,
1364 _("missing storage capability type for '%s'"),
1365 def->name);
1366 return -1;
1367 }
1368
1369 if (STREQ(type, "hotpluggable")) {
1370 storage->flags |= VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE;
1371 } else if (STREQ(type, "removable")) {
1372 xmlNodePtr orignode2;
1373
1374 storage->flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;
1375
1376 orignode2 = ctxt->node;
1377 ctxt->node = nodes[i];
1378
1379 if (virXPathBoolean("count(./media_available[. = '1']) > 0", ctxt))
1380 storage->flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
1381
1382 storage->media_label = virXPathString("string(./media_label[1])", ctxt);
1383
1384 val = 0;
1385 if (virNodeDevCapsDefParseULongLong("number(./media_size[1])", ctxt, &val, def,
1386 _("no removable media size supplied for '%s'"),
1387 _("invalid removable media size supplied for '%s'")) < 0) {
1388 return -1;
1389 }
1390 storage->removable_media_size = val;
1391
1392 ctxt->node = orignode2;
1393 } else {
1394 virReportError(VIR_ERR_INTERNAL_ERROR,
1395 _("unknown storage capability type '%s' for '%s'"),
1396 type, def->name);
1397 return -1;
1398 }
1399 }
1400
1401 if (!(storage->flags & VIR_NODE_DEV_CAP_STORAGE_REMOVABLE)) {
1402 val = 0;
1403 if (virNodeDevCapsDefParseULongLong("number(./size[1])", ctxt, &val, def,
1404 _("no size supplied for '%s'"),
1405 _("invalid size supplied for '%s'")) < 0)
1406 return -1;
1407 storage->size = val;
1408 }
1409
1410 return 0;
1411 }
1412
1413
1414 static int
virNodeDevCapSCSIParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapSCSI * scsi)1415 virNodeDevCapSCSIParseXML(xmlXPathContextPtr ctxt,
1416 virNodeDeviceDef *def,
1417 xmlNodePtr node,
1418 virNodeDevCapSCSI *scsi)
1419 {
1420 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1421
1422 ctxt->node = node;
1423
1424 if (virNodeDevCapsDefParseULong("number(./host[1])", ctxt,
1425 &scsi->host, def,
1426 _("no SCSI host ID supplied for '%s'"),
1427 _("invalid SCSI host ID supplied for '%s'")) < 0)
1428 return -1;
1429
1430 if (virNodeDevCapsDefParseULong("number(./bus[1])", ctxt,
1431 &scsi->bus, def,
1432 _("no SCSI bus ID supplied for '%s'"),
1433 _("invalid SCSI bus ID supplied for '%s'")) < 0)
1434 return -1;
1435
1436 if (virNodeDevCapsDefParseULong("number(./target[1])", ctxt,
1437 &scsi->target, def,
1438 _("no SCSI target ID supplied for '%s'"),
1439 _("invalid SCSI target ID supplied for '%s'")) < 0)
1440 return -1;
1441
1442 if (virNodeDevCapsDefParseULong("number(./lun[1])", ctxt,
1443 &scsi->lun, def,
1444 _("no SCSI LUN ID supplied for '%s'"),
1445 _("invalid SCSI LUN ID supplied for '%s'")) < 0)
1446 return -1;
1447
1448 scsi->type = virXPathString("string(./type[1])", ctxt);
1449
1450 return 0;
1451 }
1452
1453
1454 static int
virNodeDevCapSCSITargetParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapSCSITarget * scsi_target)1455 virNodeDevCapSCSITargetParseXML(xmlXPathContextPtr ctxt,
1456 virNodeDeviceDef *def,
1457 xmlNodePtr node,
1458 virNodeDevCapSCSITarget *scsi_target)
1459 {
1460 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1461 g_autofree xmlNodePtr *nodes = NULL;
1462 int n = 0;
1463 size_t i;
1464
1465 ctxt->node = node;
1466
1467 scsi_target->name = virXPathString("string(./target[1])", ctxt);
1468 if (!scsi_target->name) {
1469 virReportError(VIR_ERR_INTERNAL_ERROR,
1470 _("no target name supplied for '%s'"),
1471 def->name);
1472 return -1;
1473 }
1474
1475 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
1476 return -1;
1477
1478 for (i = 0; i < n; ++i) {
1479 g_autofree char *type = NULL;
1480 type = virXMLPropString(nodes[i], "type");
1481
1482 if (!type) {
1483 virReportError(VIR_ERR_INTERNAL_ERROR,
1484 _("missing type for SCSI target capability for '%s'"),
1485 def->name);
1486 return -1;
1487 }
1488
1489 if (STREQ(type, "fc_remote_port")) {
1490 scsi_target->flags |= VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
1491
1492 ctxt->node = nodes[i];
1493
1494 if (virNodeDevCapsDefParseString("string(./rport[1])",
1495 ctxt,
1496 &scsi_target->rport) < 0) {
1497 virReportError(VIR_ERR_INTERNAL_ERROR,
1498 _("missing rport name for '%s'"), def->name);
1499 return -1;
1500 }
1501
1502 if (virNodeDevCapsDefParseString("string(./wwpn[1])",
1503 ctxt, &scsi_target->wwpn) < 0) {
1504 virReportError(VIR_ERR_INTERNAL_ERROR,
1505 _("missing wwpn identifier for '%s'"),
1506 def->name);
1507 return -1;
1508 }
1509 } else {
1510 virReportError(VIR_ERR_INTERNAL_ERROR,
1511 _("unknown SCSI target capability type '%s' for '%s'"),
1512 type, def->name);
1513 return -1;
1514 }
1515 }
1516
1517 return 0;
1518 }
1519
1520
1521 static int
virNodeDevCapSCSIHostParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapSCSIHost * scsi_host,int create,const char * virt_type)1522 virNodeDevCapSCSIHostParseXML(xmlXPathContextPtr ctxt,
1523 virNodeDeviceDef *def,
1524 xmlNodePtr node,
1525 virNodeDevCapSCSIHost *scsi_host,
1526 int create,
1527 const char *virt_type)
1528 {
1529 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1530 g_autofree xmlNodePtr *nodes = NULL;
1531 int n = 0;
1532 size_t i;
1533
1534 ctxt->node = node;
1535
1536 if (create == EXISTING_DEVICE) {
1537 if (virNodeDevCapsDefParseULong("number(./host[1])", ctxt,
1538 &scsi_host->host, def,
1539 _("no SCSI host ID supplied for '%s'"),
1540 _("invalid SCSI host ID supplied for '%s'")) < 0) {
1541 return -1;
1542 }
1543 /* Optional unique_id value */
1544 scsi_host->unique_id = -1;
1545 if (virNodeDevCapsDefParseIntOptional("number(./unique_id[1])", ctxt,
1546 &scsi_host->unique_id, def,
1547 _("invalid unique_id supplied for '%s'")) < 0) {
1548 return -1;
1549 }
1550 }
1551
1552 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
1553 return -1;
1554
1555 for (i = 0; i < n; i++) {
1556 g_autofree char *type = NULL;
1557 type = virXMLPropString(nodes[i], "type");
1558
1559 if (!type) {
1560 virReportError(VIR_ERR_INTERNAL_ERROR,
1561 _("missing SCSI host capability type for '%s'"),
1562 def->name);
1563 return -1;
1564 }
1565
1566 if (STREQ(type, "vport_ops")) {
1567
1568 scsi_host->flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS;
1569
1570 } else if (STREQ(type, "fc_host")) {
1571 scsi_host->flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST;
1572
1573 ctxt->node = nodes[i];
1574
1575 if (virNodeDevCapsDefParseString("string(./wwnn[1])",
1576 ctxt,
1577 &scsi_host->wwnn) < 0) {
1578 if (virRandomGenerateWWN(&scsi_host->wwnn, virt_type) < 0) {
1579 virReportError(VIR_ERR_INTERNAL_ERROR,
1580 _("no WWNN supplied for '%s', and "
1581 "auto-generation failed"),
1582 def->name);
1583 return -1;
1584 }
1585 }
1586
1587 if (virNodeDevCapsDefParseString("string(./wwpn[1])",
1588 ctxt,
1589 &scsi_host->wwpn) < 0) {
1590 if (virRandomGenerateWWN(&scsi_host->wwpn, virt_type) < 0) {
1591 virReportError(VIR_ERR_INTERNAL_ERROR,
1592 _("no WWPN supplied for '%s', and "
1593 "auto-generation failed"),
1594 def->name);
1595 return -1;
1596 }
1597 }
1598
1599 if (virNodeDevCapsDefParseString("string(./fabric_wwn[1])",
1600 ctxt,
1601 &scsi_host->fabric_wwn) < 0)
1602 VIR_DEBUG("No fabric_wwn defined for '%s'", def->name);
1603
1604 } else {
1605 virReportError(VIR_ERR_INTERNAL_ERROR,
1606 _("unknown SCSI host capability type '%s' for '%s'"),
1607 type, def->name);
1608 return -1;
1609 }
1610 }
1611
1612 return 0;
1613 }
1614
1615
1616 static int
virNodeDevCapNetParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapNet * net)1617 virNodeDevCapNetParseXML(xmlXPathContextPtr ctxt,
1618 virNodeDeviceDef *def,
1619 xmlNodePtr node,
1620 virNodeDevCapNet *net)
1621 {
1622 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1623 xmlNodePtr lnk;
1624 size_t i = -1;
1625 int n = -1;
1626 g_autofree char *type = NULL;
1627 g_autofree xmlNodePtr *nodes = NULL;
1628
1629 ctxt->node = node;
1630
1631 net->ifname = virXPathString("string(./interface[1])", ctxt);
1632 if (!net->ifname) {
1633 virReportError(VIR_ERR_INTERNAL_ERROR,
1634 _("no network interface supplied for '%s'"),
1635 def->name);
1636 return -1;
1637 }
1638
1639 net->address = virXPathString("string(./address[1])", ctxt);
1640
1641 if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0)
1642 return -1;
1643
1644 if (n > 0)
1645 net->features = virBitmapNew(VIR_NET_DEV_FEAT_LAST);
1646
1647 for (i = 0; i < n; i++) {
1648 g_autofree char *tmp = NULL;
1649 int val;
1650 if (!(tmp = virXMLPropString(nodes[i], "name"))) {
1651 virReportError(VIR_ERR_XML_ERROR, "%s",
1652 _("missing network device feature name"));
1653 return -1;
1654 }
1655
1656 if ((val = virNetDevFeatureTypeFromString(tmp)) < 0) {
1657 virReportError(VIR_ERR_XML_ERROR,
1658 _("unknown network device feature '%s'"),
1659 tmp);
1660 return -1;
1661 }
1662 ignore_value(virBitmapSetBit(net->features, val));
1663 }
1664
1665 net->subtype = VIR_NODE_DEV_CAP_NET_LAST;
1666
1667 type = virXPathString("string(./capability/@type)", ctxt);
1668 if (type) {
1669 int val = virNodeDevNetCapTypeFromString(type);
1670 if (val < 0) {
1671 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1672 _("invalid network type supplied for '%s'"),
1673 def->name);
1674 return -1;
1675 }
1676 net->subtype = val;
1677 }
1678
1679 lnk = virXPathNode("./link", ctxt);
1680 if (lnk && virInterfaceLinkParseXML(lnk, &net->lnk) < 0)
1681 return -1;
1682
1683 return 0;
1684 }
1685
1686
1687 static int
virNodeDevCapUSBInterfaceParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapUSBIf * usb_if)1688 virNodeDevCapUSBInterfaceParseXML(xmlXPathContextPtr ctxt,
1689 virNodeDeviceDef *def,
1690 xmlNodePtr node,
1691 virNodeDevCapUSBIf *usb_if)
1692 {
1693 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1694
1695 ctxt->node = node;
1696
1697 if (virNodeDevCapsDefParseULong("number(./number[1])", ctxt,
1698 &usb_if->number, def,
1699 _("no USB interface number supplied for '%s'"),
1700 _("invalid USB interface number supplied for '%s'")) < 0)
1701 return -1;
1702
1703 if (virNodeDevCapsDefParseULong("number(./class[1])", ctxt,
1704 &usb_if->klass, def,
1705 _("no USB interface class supplied for '%s'"),
1706 _("invalid USB interface class supplied for '%s'")) < 0)
1707 return -1;
1708
1709 if (virNodeDevCapsDefParseULong("number(./subclass[1])", ctxt,
1710 &usb_if->subclass, def,
1711 _("no USB interface subclass supplied for '%s'"),
1712 _("invalid USB interface subclass supplied for '%s'")) < 0)
1713 return -1;
1714
1715 if (virNodeDevCapsDefParseULong("number(./protocol[1])", ctxt,
1716 &usb_if->protocol, def,
1717 _("no USB interface protocol supplied for '%s'"),
1718 _("invalid USB interface protocol supplied for '%s'")) < 0)
1719 return -1;
1720
1721 usb_if->description = virXPathString("string(./description[1])", ctxt);
1722
1723 return 0;
1724 }
1725
1726
1727 static int
virNodeDevCapsDefParseHexId(const char * xpath,xmlXPathContextPtr ctxt,unsigned * value,virNodeDeviceDef * def,const char * missing_error_fmt,const char * invalid_error_fmt)1728 virNodeDevCapsDefParseHexId(const char *xpath,
1729 xmlXPathContextPtr ctxt,
1730 unsigned *value,
1731 virNodeDeviceDef *def,
1732 const char *missing_error_fmt,
1733 const char *invalid_error_fmt)
1734 {
1735 int ret;
1736 unsigned long val;
1737
1738 ret = virXPathULongHex(xpath, ctxt, &val);
1739 if (ret < 0) {
1740 virReportError(VIR_ERR_INTERNAL_ERROR,
1741 ret == -1 ? missing_error_fmt : invalid_error_fmt,
1742 def->name);
1743 return -1;
1744 }
1745
1746 *value = val;
1747 return 0;
1748 }
1749
1750
1751 static int
virNodeDevCapUSBDevParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapUSBDev * usb_dev)1752 virNodeDevCapUSBDevParseXML(xmlXPathContextPtr ctxt,
1753 virNodeDeviceDef *def,
1754 xmlNodePtr node,
1755 virNodeDevCapUSBDev *usb_dev)
1756 {
1757 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1758
1759 ctxt->node = node;
1760
1761 if (virNodeDevCapsDefParseULong("number(./bus[1])", ctxt,
1762 &usb_dev->bus, def,
1763 _("no USB bus number supplied for '%s'"),
1764 _("invalid USB bus number supplied for '%s'")) < 0)
1765 return -1;
1766
1767 if (virNodeDevCapsDefParseULong("number(./device[1])", ctxt,
1768 &usb_dev->device, def,
1769 _("no USB device number supplied for '%s'"),
1770 _("invalid USB device number supplied for '%s'")) < 0)
1771 return -1;
1772
1773 if (virNodeDevCapsDefParseHexId("string(./vendor[1]/@id)", ctxt,
1774 &usb_dev->vendor, def,
1775 _("no USB vendor ID supplied for '%s'"),
1776 _("invalid USB vendor ID supplied for '%s'")) < 0)
1777 return -1;
1778
1779 if (virNodeDevCapsDefParseHexId("string(./product[1]/@id)", ctxt,
1780 &usb_dev->product, def,
1781 _("no USB product ID supplied for '%s'"),
1782 _("invalid USB product ID supplied for '%s'")) < 0)
1783 return -1;
1784
1785 usb_dev->vendor_name = virXPathString("string(./vendor[1])", ctxt);
1786 usb_dev->product_name = virXPathString("string(./product[1])", ctxt);
1787
1788 return 0;
1789 }
1790
1791
1792 static int
virNodeDevCapPCIDevIommuGroupParseXML(xmlXPathContextPtr ctxt,xmlNodePtr iommuGroupNode,virNodeDevCapPCIDev * pci_dev)1793 virNodeDevCapPCIDevIommuGroupParseXML(xmlXPathContextPtr ctxt,
1794 xmlNodePtr iommuGroupNode,
1795 virNodeDevCapPCIDev *pci_dev)
1796 {
1797 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1798 g_autofree xmlNodePtr *addrNodes = NULL;
1799 int nAddrNodes;
1800 size_t i;
1801
1802 ctxt->node = iommuGroupNode;
1803
1804 if (virXMLPropUInt(iommuGroupNode, "number", 10, VIR_XML_PROP_REQUIRED,
1805 &pci_dev->iommuGroupNumber) < 0)
1806 return -1;
1807
1808 if ((nAddrNodes = virXPathNodeSet("./address", ctxt, &addrNodes)) < 0)
1809 return -1;
1810
1811 for (i = 0; i < nAddrNodes; i++) {
1812 g_autoptr(virPCIDeviceAddress) pciAddr = g_new0(virPCIDeviceAddress, 1);
1813
1814 if (virPCIDeviceAddressParseXML(addrNodes[i], pciAddr) < 0)
1815 return -1;
1816 VIR_APPEND_ELEMENT(pci_dev->iommuGroupDevices,
1817 pci_dev->nIommuGroupDevices,
1818 pciAddr);
1819 }
1820
1821 return 0;
1822 }
1823
1824
1825 static int
virPCIEDeviceInfoLinkParseXML(xmlNodePtr linkNode,virPCIELink * lnk)1826 virPCIEDeviceInfoLinkParseXML(xmlNodePtr linkNode,
1827 virPCIELink *lnk)
1828 {
1829 if (virXMLPropUInt(linkNode, "width", 0, VIR_XML_PROP_REQUIRED, &lnk->width) < 0)
1830 return -1;
1831
1832 if (virXMLPropEnum(linkNode, "speed", virPCIELinkSpeedTypeFromString,
1833 VIR_XML_PROP_NONE, &lnk->speed) < 0)
1834 return -1;
1835
1836 if (virXMLPropInt(linkNode, "port", 10, VIR_XML_PROP_NONE, &lnk->port, -1) < 0)
1837 return -1;
1838
1839 return 0;
1840 }
1841
1842
1843 static int
virPCIEDeviceInfoParseXML(xmlXPathContextPtr ctxt,xmlNodePtr pciExpressNode,virPCIEDeviceInfo * pci_express)1844 virPCIEDeviceInfoParseXML(xmlXPathContextPtr ctxt,
1845 xmlNodePtr pciExpressNode,
1846 virPCIEDeviceInfo *pci_express)
1847 {
1848 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1849 xmlNodePtr lnk;
1850
1851 ctxt->node = pciExpressNode;
1852
1853 if ((lnk = virXPathNode("./link[@validity='cap']", ctxt))) {
1854 pci_express->link_cap = g_new0(virPCIELink, 1);
1855
1856 if (virPCIEDeviceInfoLinkParseXML(lnk, pci_express->link_cap) < 0)
1857 return -1;
1858 }
1859
1860 if ((lnk = virXPathNode("./link[@validity='sta']", ctxt))) {
1861 pci_express->link_sta = g_new0(virPCIELink, 1);
1862
1863 if (virPCIEDeviceInfoLinkParseXML(lnk, pci_express->link_sta) < 0)
1864 return -1;
1865 }
1866
1867 return 0;
1868 }
1869
1870
1871 static int
virNodeDevPCICapSRIOVPhysicalParseXML(xmlXPathContextPtr ctxt,virNodeDevCapPCIDev * pci_dev)1872 virNodeDevPCICapSRIOVPhysicalParseXML(xmlXPathContextPtr ctxt,
1873 virNodeDevCapPCIDev *pci_dev)
1874 {
1875 xmlNodePtr address = virXPathNode("./address[1]", ctxt);
1876
1877 pci_dev->physical_function = g_new0(virPCIDeviceAddress, 1);
1878
1879 if (!address) {
1880 virReportError(VIR_ERR_XML_ERROR, "%s",
1881 _("Missing address in 'phys_function' capability"));
1882 return -1;
1883 }
1884
1885 if (virPCIDeviceAddressParseXML(address,
1886 pci_dev->physical_function) < 0)
1887 return -1;
1888
1889 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
1890
1891 return 0;
1892 }
1893
1894
1895 static int
virNodeDevPCICapSRIOVVirtualParseXML(xmlXPathContextPtr ctxt,virNodeDevCapPCIDev * pci_dev)1896 virNodeDevPCICapSRIOVVirtualParseXML(xmlXPathContextPtr ctxt,
1897 virNodeDevCapPCIDev *pci_dev)
1898 {
1899 g_autofree xmlNodePtr *addresses = NULL;
1900 int naddresses = virXPathNodeSet("./address", ctxt, &addresses);
1901 g_autofree char *maxFuncsStr = virXPathString("string(./@maxCount)", ctxt);
1902 size_t i;
1903
1904 if (naddresses < 0)
1905 return -1;
1906
1907 if (maxFuncsStr &&
1908 virStrToLong_uip(maxFuncsStr, NULL, 10,
1909 &pci_dev->max_virtual_functions) < 0) {
1910 virReportError(VIR_ERR_XML_ERROR, "%s",
1911 _("Malformed 'maxCount' parameter"));
1912 return -1;
1913 }
1914
1915 pci_dev->virtual_functions = g_new0(virPCIDeviceAddress *, naddresses);
1916
1917 for (i = 0; i < naddresses; i++) {
1918 g_autoptr(virPCIDeviceAddress) addr = NULL;
1919
1920 addr = g_new0(virPCIDeviceAddress, 1);
1921
1922 if (virPCIDeviceAddressParseXML(addresses[i], addr) < 0)
1923 return -1;
1924
1925 VIR_APPEND_ELEMENT(pci_dev->virtual_functions,
1926 pci_dev->num_virtual_functions,
1927 addr);
1928 }
1929
1930 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
1931 return 0;
1932 }
1933
1934
1935 static int
virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,xmlNodePtr node,virNodeDevCapPCIDev * pci_dev)1936 virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,
1937 xmlNodePtr node,
1938 virNodeDevCapPCIDev *pci_dev)
1939 {
1940 g_autofree char *type = virXMLPropString(node, "type");
1941 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1942
1943 ctxt->node = node;
1944
1945 if (!type) {
1946 virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
1947 return -1;
1948 }
1949
1950 if (STREQ(type, "phys_function") &&
1951 virNodeDevPCICapSRIOVPhysicalParseXML(ctxt, pci_dev) < 0) {
1952 return -1;
1953 } else if (STREQ(type, "virt_functions") &&
1954 virNodeDevPCICapSRIOVVirtualParseXML(ctxt, pci_dev) < 0) {
1955 return -1;
1956 } else if (STREQ(type, "mdev_types")) {
1957 if (virNodeDevCapMdevTypesParseXML(ctxt,
1958 &pci_dev->mdev_types,
1959 &pci_dev->nmdev_types) < 0)
1960 return -1;
1961 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
1962 } else if (STREQ(type, "vpd")) {
1963 if (virNodeDeviceCapVPDParseXML(ctxt, &pci_dev->vpd) < 0)
1964 return -1;
1965 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VPD;
1966 } else {
1967 int hdrType = virPCIHeaderTypeFromString(type);
1968
1969 if (hdrType > 0 && !pci_dev->hdrType)
1970 pci_dev->hdrType = hdrType;
1971 }
1972
1973 return 0;
1974 }
1975
1976
1977 static int
virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapPCIDev * pci_dev)1978 virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
1979 virNodeDeviceDef *def,
1980 xmlNodePtr node,
1981 virNodeDevCapPCIDev *pci_dev)
1982 {
1983 VIR_XPATH_NODE_AUTORESTORE(ctxt)
1984 xmlNodePtr iommuGroupNode;
1985 xmlNodePtr pciExpress;
1986 g_autofree xmlNodePtr *nodes = NULL;
1987 int n = 0;
1988 int ret = -1;
1989 virPCIEDeviceInfo *pci_express = NULL;
1990 g_autofree char *tmp = NULL;
1991 size_t i = 0;
1992
1993 ctxt->node = node;
1994
1995 if ((tmp = virXPathString("string(./class[1])", ctxt))) {
1996 if (virStrToLong_i(tmp, NULL, 16, &pci_dev->klass) < 0 ||
1997 pci_dev->klass > 0xffffff) {
1998 virReportError(VIR_ERR_INTERNAL_ERROR,
1999 _("invalid PCI class supplied for '%s'"), def->name);
2000 goto out;
2001 }
2002 } else {
2003 pci_dev->klass = -1;
2004 }
2005
2006 if (virNodeDevCapsDefParseULong("number(./domain[1])", ctxt,
2007 &pci_dev->domain, def,
2008 _("no PCI domain ID supplied for '%s'"),
2009 _("invalid PCI domain ID supplied for '%s'")) < 0)
2010 goto out;
2011
2012 if (virNodeDevCapsDefParseULong("number(./bus[1])", ctxt,
2013 &pci_dev->bus, def,
2014 _("no PCI bus ID supplied for '%s'"),
2015 _("invalid PCI bus ID supplied for '%s'")) < 0)
2016 goto out;
2017
2018 if (virNodeDevCapsDefParseULong("number(./slot[1])", ctxt,
2019 &pci_dev->slot, def,
2020 _("no PCI slot ID supplied for '%s'"),
2021 _("invalid PCI slot ID supplied for '%s'")) < 0)
2022 goto out;
2023
2024 if (virNodeDevCapsDefParseULong("number(./function[1])", ctxt,
2025 &pci_dev->function, def,
2026 _("no PCI function ID supplied for '%s'"),
2027 _("invalid PCI function ID supplied for '%s'")) < 0)
2028 goto out;
2029
2030 if (virNodeDevCapsDefParseHexId("string(./vendor[1]/@id)", ctxt,
2031 &pci_dev->vendor, def,
2032 _("no PCI vendor ID supplied for '%s'"),
2033 _("invalid PCI vendor ID supplied for '%s'")) < 0)
2034 goto out;
2035
2036 if (virNodeDevCapsDefParseHexId("string(./product[1]/@id)", ctxt,
2037 &pci_dev->product, def,
2038 _("no PCI product ID supplied for '%s'"),
2039 _("invalid PCI product ID supplied for '%s'")) < 0)
2040 goto out;
2041
2042 pci_dev->vendor_name = virXPathString("string(./vendor[1])", ctxt);
2043 pci_dev->product_name = virXPathString("string(./product[1])", ctxt);
2044
2045 if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
2046 goto out;
2047
2048 for (i = 0; i < n; i++) {
2049 if (virNodeDevPCICapabilityParseXML(ctxt, nodes[i], pci_dev) < 0)
2050 goto out;
2051 }
2052
2053 if ((iommuGroupNode = virXPathNode("./iommuGroup[1]", ctxt))) {
2054 if (virNodeDevCapPCIDevIommuGroupParseXML(ctxt, iommuGroupNode,
2055 pci_dev) < 0) {
2056 goto out;
2057 }
2058 }
2059
2060 /* The default value is -1 since zero is valid NUMA node number */
2061 pci_dev->numa_node = -1;
2062 if (virNodeDevCapsDefParseIntOptional("number(./numa[1]/@node)", ctxt,
2063 &pci_dev->numa_node, def,
2064 _("invalid NUMA node ID supplied for '%s'")) < 0)
2065 goto out;
2066
2067 if ((pciExpress = virXPathNode("./pci-express[1]", ctxt))) {
2068 pci_express = g_new0(virPCIEDeviceInfo, 1);
2069
2070 if (virPCIEDeviceInfoParseXML(ctxt, pciExpress, pci_express) < 0)
2071 goto out;
2072
2073 pci_dev->pci_express = g_steal_pointer(&pci_express);
2074 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCIE;
2075 }
2076
2077 ret = 0;
2078 out:
2079 virPCIEDeviceInfoFree(pci_express);
2080 return ret;
2081 }
2082
2083
2084 static int
virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapSystem * syscap)2085 virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,
2086 virNodeDeviceDef *def,
2087 xmlNodePtr node,
2088 virNodeDevCapSystem *syscap)
2089 {
2090 virNodeDevCapSystemHardware *hardware = &syscap->hardware;
2091 virNodeDevCapSystemFirmware *firmware = &syscap->firmware;
2092 VIR_XPATH_NODE_AUTORESTORE(ctxt)
2093 g_autofree char *tmp = NULL;
2094
2095 ctxt->node = node;
2096
2097 syscap->product_name = virXPathString("string(./product[1])", ctxt);
2098
2099 hardware->vendor_name = virXPathString("string(./hardware/vendor[1])", ctxt);
2100 hardware->version = virXPathString("string(./hardware/version[1])", ctxt);
2101 hardware->serial = virXPathString("string(./hardware/serial[1])", ctxt);
2102
2103 tmp = virXPathString("string(./hardware/uuid[1])", ctxt);
2104 if (!tmp) {
2105 virReportError(VIR_ERR_INTERNAL_ERROR,
2106 _("no system UUID supplied for '%s'"), def->name);
2107 return -1;
2108 }
2109
2110 if (virUUIDParse(tmp, hardware->uuid) < 0) {
2111 virReportError(VIR_ERR_INTERNAL_ERROR,
2112 _("malformed uuid element for '%s'"), def->name);
2113 return -1;
2114 }
2115
2116 firmware->vendor_name = virXPathString("string(./firmware/vendor[1])", ctxt);
2117 firmware->version = virXPathString("string(./firmware/version[1])", ctxt);
2118 firmware->release_date = virXPathString("string(./firmware/release_date[1])", ctxt);
2119
2120 return 0;
2121 }
2122
2123 static int
virNodeDevCapMdevAttributeParseXML(xmlXPathContextPtr ctxt,xmlNodePtr node,virNodeDevCapMdev * mdev)2124 virNodeDevCapMdevAttributeParseXML(xmlXPathContextPtr ctxt,
2125 xmlNodePtr node,
2126 virNodeDevCapMdev *mdev)
2127 {
2128 VIR_XPATH_NODE_AUTORESTORE(ctxt)
2129 g_autoptr(virMediatedDeviceAttr) attr = virMediatedDeviceAttrNew();
2130
2131 ctxt->node = node;
2132 attr->name = virXPathString("string(./@name)", ctxt);
2133 attr->value = virXPathString("string(./@value)", ctxt);
2134 if (!attr->name || !attr->value) {
2135 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2136 _("mdev attribute missing name or value"));
2137 return -1;
2138 }
2139
2140 VIR_APPEND_ELEMENT(mdev->attributes, mdev->nattributes, attr);
2141
2142 return 0;
2143 }
2144
2145 static int
virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,virNodeDevCapMdev * mdev)2146 virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
2147 virNodeDeviceDef *def,
2148 xmlNodePtr node,
2149 virNodeDevCapMdev *mdev)
2150 {
2151 VIR_XPATH_NODE_AUTORESTORE(ctxt)
2152 int nattrs = 0;
2153 g_autofree xmlNodePtr *attrs = NULL;
2154 size_t i;
2155 g_autofree char *uuidstr = NULL;
2156
2157 ctxt->node = node;
2158
2159 if (!(mdev->type = virXPathString("string(./type[1]/@id)", ctxt))) {
2160 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2161 _("missing type id attribute for '%s'"), def->name);
2162 return -1;
2163 }
2164
2165 if ((uuidstr = virXPathString("string(./uuid[1])", ctxt))) {
2166 unsigned char uuidbuf[VIR_UUID_BUFLEN];
2167 /* make sure that the provided uuid is valid */
2168 if (virUUIDParse(uuidstr, uuidbuf) < 0) {
2169 virReportError(VIR_ERR_INTERNAL_ERROR,
2170 _("Invalid uuid '%s' for new mdev device"), uuidstr);
2171 return -1;
2172 }
2173 mdev->uuid = g_new0(char, VIR_UUID_STRING_BUFLEN);
2174 virUUIDFormat(uuidbuf, mdev->uuid);
2175 }
2176
2177 /* 'iommuGroup' is optional, only report an error if the supplied value is
2178 * invalid (-2), not if it's missing (-1) */
2179 if (virXPathUInt("number(./iommuGroup[1]/@number)",
2180 ctxt, &mdev->iommuGroupNumber) < -1) {
2181 virReportError(VIR_ERR_INTERNAL_ERROR,
2182 _("invalid iommuGroup number attribute for '%s'"),
2183 def->name);
2184 return -1;
2185 }
2186
2187 if ((nattrs = virXPathNodeSet("./attr", ctxt, &attrs)) < 0)
2188 return -1;
2189
2190 for (i = 0; i < nattrs; i++)
2191 virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], mdev);
2192
2193 return 0;
2194 }
2195
2196
2197 static virNodeDevCapsDef *
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,virNodeDeviceDef * def,xmlNodePtr node,int create,const char * virt_type)2198 virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
2199 virNodeDeviceDef *def,
2200 xmlNodePtr node,
2201 int create,
2202 const char *virt_type)
2203 {
2204 g_autoptr(virNodeDevCapsDef) caps = g_new0(virNodeDevCapsDef, 1);
2205 int ret = -1;
2206
2207 if (virXMLPropEnum(node, "type", virNodeDevCapTypeFromString,
2208 VIR_XML_PROP_REQUIRED, &caps->data.type) < 0)
2209 return NULL;
2210
2211 switch (caps->data.type) {
2212 case VIR_NODE_DEV_CAP_SYSTEM:
2213 ret = virNodeDevCapSystemParseXML(ctxt, def, node, &caps->data.system);
2214 break;
2215 case VIR_NODE_DEV_CAP_PCI_DEV:
2216 ret = virNodeDevCapPCIDevParseXML(ctxt, def, node, &caps->data.pci_dev);
2217 break;
2218 case VIR_NODE_DEV_CAP_USB_DEV:
2219 ret = virNodeDevCapUSBDevParseXML(ctxt, def, node, &caps->data.usb_dev);
2220 break;
2221 case VIR_NODE_DEV_CAP_USB_INTERFACE:
2222 ret = virNodeDevCapUSBInterfaceParseXML(ctxt, def, node,
2223 &caps->data.usb_if);
2224 break;
2225 case VIR_NODE_DEV_CAP_NET:
2226 ret = virNodeDevCapNetParseXML(ctxt, def, node, &caps->data.net);
2227 break;
2228 case VIR_NODE_DEV_CAP_SCSI_HOST:
2229 ret = virNodeDevCapSCSIHostParseXML(ctxt, def, node,
2230 &caps->data.scsi_host,
2231 create,
2232 virt_type);
2233 break;
2234 case VIR_NODE_DEV_CAP_SCSI_TARGET:
2235 ret = virNodeDevCapSCSITargetParseXML(ctxt, def, node,
2236 &caps->data.scsi_target);
2237 break;
2238 case VIR_NODE_DEV_CAP_SCSI:
2239 ret = virNodeDevCapSCSIParseXML(ctxt, def, node, &caps->data.scsi);
2240 break;
2241 case VIR_NODE_DEV_CAP_STORAGE:
2242 ret = virNodeDevCapStorageParseXML(ctxt, def, node,
2243 &caps->data.storage);
2244 break;
2245 case VIR_NODE_DEV_CAP_DRM:
2246 ret = virNodeDevCapDRMParseXML(ctxt, def, node, &caps->data.drm);
2247 break;
2248 case VIR_NODE_DEV_CAP_MDEV:
2249 ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev);
2250 break;
2251 case VIR_NODE_DEV_CAP_CCW_DEV:
2252 case VIR_NODE_DEV_CAP_CSS_DEV:
2253 ret = virNodeDevCapCCWParseXML(ctxt, def, node, &caps->data.ccw_dev);
2254 break;
2255 case VIR_NODE_DEV_CAP_AP_CARD:
2256 ret = virNodeDevCapAPCardParseXML(ctxt, def, node,
2257 &caps->data.ap_card);
2258 break;
2259 case VIR_NODE_DEV_CAP_AP_QUEUE:
2260 ret = virNodeDevCapAPQueueParseXML(ctxt, def, node,
2261 &caps->data.ap_queue);
2262 break;
2263 case VIR_NODE_DEV_CAP_AP_MATRIX:
2264 ret = virNodeDevCapAPMatrixParseXML(ctxt, def, node,
2265 &caps->data.ap_matrix);
2266 break;
2267 case VIR_NODE_DEV_CAP_MDEV_TYPES:
2268 case VIR_NODE_DEV_CAP_FC_HOST:
2269 case VIR_NODE_DEV_CAP_VPORTS:
2270 case VIR_NODE_DEV_CAP_SCSI_GENERIC:
2271 case VIR_NODE_DEV_CAP_VDPA:
2272 case VIR_NODE_DEV_CAP_VPD:
2273 case VIR_NODE_DEV_CAP_LAST:
2274 virReportError(VIR_ERR_INTERNAL_ERROR,
2275 _("unknown capability type '%d' for '%s'"),
2276 caps->data.type, def->name);
2277 ret = -1;
2278 break;
2279 }
2280
2281 if (ret < 0)
2282 return NULL;
2283
2284 return g_steal_pointer(&caps);
2285 }
2286
2287
2288 static virNodeDeviceDef *
virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt,int create,const char * virt_type)2289 virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt,
2290 int create,
2291 const char *virt_type)
2292 {
2293 g_autoptr(virNodeDeviceDef) def = g_new0(virNodeDeviceDef, 1);
2294 virNodeDevCapsDef **next_cap;
2295 g_autofree xmlNodePtr *devnode = NULL;
2296 g_autofree xmlNodePtr *capability = NULL;
2297 int n, m;
2298 size_t i;
2299
2300 /* Extract device name */
2301 if (create == EXISTING_DEVICE) {
2302 def->name = virXPathString("string(./name[1])", ctxt);
2303
2304 if (!def->name) {
2305 virReportError(VIR_ERR_NO_NAME, NULL);
2306 return NULL;
2307 }
2308 } else {
2309 def->name = g_strdup("new device");
2310 }
2311
2312 def->sysfs_path = virXPathString("string(./path[1])", ctxt);
2313
2314 /* Parse devnodes */
2315 if ((n = virXPathNodeSet("./devnode", ctxt, &devnode)) < 0)
2316 return NULL;
2317
2318 def->devlinks = g_new0(char *, n + 1);
2319
2320 for (i = 0, m = 0; i < n; i++) {
2321 xmlNodePtr node = devnode[i];
2322 virNodeDevDevnodeType val;
2323
2324 if (virXMLPropEnum(node, "type", virNodeDevDevnodeTypeFromString,
2325 VIR_XML_PROP_REQUIRED, &val) < 0)
2326 return NULL;
2327
2328 switch (val) {
2329 case VIR_NODE_DEV_DEVNODE_DEV:
2330 if (!(def->devnode = virXMLNodeContentString(node)))
2331 return NULL;
2332 break;
2333 case VIR_NODE_DEV_DEVNODE_LINK:
2334 if (!(def->devlinks[m++] = virXMLNodeContentString(node)))
2335 return NULL;
2336 break;
2337 case VIR_NODE_DEV_DEVNODE_LAST:
2338 break;
2339 }
2340 }
2341
2342 /* Extract device parent, if any */
2343 def->parent = virXPathString("string(./parent[1])", ctxt);
2344 def->parent_wwnn = virXPathString("string(./parent[1]/@wwnn)", ctxt);
2345 def->parent_wwpn = virXPathString("string(./parent[1]/@wwpn)", ctxt);
2346 if (def->parent_wwnn && !def->parent_wwpn) {
2347 virReportError(VIR_ERR_XML_ERROR,
2348 _("when providing parent wwnn='%s', the "
2349 "wwpn must also be provided"),
2350 def->parent_wwnn);
2351 return NULL;
2352 }
2353
2354 if (!def->parent_wwnn && def->parent_wwpn) {
2355 virReportError(VIR_ERR_XML_ERROR,
2356 _("when providing parent wwpn='%s', the "
2357 "wwnn must also be provided"),
2358 def->parent_wwpn);
2359 return NULL;
2360 }
2361 def->parent_fabric_wwn = virXPathString("string(./parent[1]/@fabric_wwn)",
2362 ctxt);
2363
2364 /* Parse device capabilities */
2365 if ((n = virXPathNodeSet("./capability", ctxt, &capability)) < 0)
2366 return NULL;
2367
2368 if (n == 0) {
2369 virReportError(VIR_ERR_INTERNAL_ERROR,
2370 _("no device capabilities for '%s'"),
2371 def->name);
2372 return NULL;
2373 }
2374
2375 next_cap = &def->caps;
2376 for (i = 0; i < n; i++) {
2377 *next_cap = virNodeDevCapsDefParseXML(ctxt, def,
2378 capability[i],
2379 create,
2380 virt_type);
2381 if (!*next_cap)
2382 return NULL;
2383
2384 next_cap = &(*next_cap)->next;
2385 }
2386
2387 return g_steal_pointer(&def);
2388 }
2389
2390
2391 virNodeDeviceDef *
virNodeDeviceDefParseNode(xmlDocPtr xml,xmlNodePtr root,int create,const char * virt_type)2392 virNodeDeviceDefParseNode(xmlDocPtr xml,
2393 xmlNodePtr root,
2394 int create,
2395 const char *virt_type)
2396 {
2397 g_autoptr(xmlXPathContext) ctxt = NULL;
2398
2399 if (!virXMLNodeNameEqual(root, "device")) {
2400 virReportError(VIR_ERR_XML_ERROR,
2401 _("unexpected root element <%s> "
2402 "expecting <device>"),
2403 root->name);
2404 return NULL;
2405 }
2406
2407 if (!(ctxt = virXMLXPathContextNew(xml)))
2408 return NULL;
2409
2410 ctxt->node = root;
2411 return virNodeDeviceDefParseXML(ctxt, create, virt_type);
2412 }
2413
2414
2415 static virNodeDeviceDef *
virNodeDeviceDefParse(const char * str,const char * filename,int create,const char * virt_type,virNodeDeviceDefParserCallbacks * parserCallbacks,void * opaque)2416 virNodeDeviceDefParse(const char *str,
2417 const char *filename,
2418 int create,
2419 const char *virt_type,
2420 virNodeDeviceDefParserCallbacks *parserCallbacks,
2421 void *opaque)
2422 {
2423 g_autoptr(xmlDoc) xml = NULL;
2424 g_autoptr(virNodeDeviceDef) def = NULL;
2425
2426 if (!(xml = virXMLParse(filename, str, _("(node_device_definition)"), NULL, false)) ||
2427 !(def = virNodeDeviceDefParseNode(xml, xmlDocGetRootElement(xml),
2428 create, virt_type)))
2429 return NULL;
2430
2431 if (parserCallbacks) {
2432 int ret = 0;
2433 /* fill in backend-specific aspects */
2434 if (parserCallbacks->postParse) {
2435 ret = parserCallbacks->postParse(def, opaque);
2436 if (ret < 0)
2437 return NULL;
2438 }
2439
2440 /* validate definition */
2441 if (parserCallbacks->validate) {
2442 ret = parserCallbacks->validate(def, opaque);
2443 if (ret < 0)
2444 return NULL;
2445 }
2446 }
2447
2448 return g_steal_pointer(&def);
2449 }
2450
2451
2452 virNodeDeviceDef *
virNodeDeviceDefParseString(const char * str,int create,const char * virt_type,virNodeDeviceDefParserCallbacks * parserCallbacks,void * opaque)2453 virNodeDeviceDefParseString(const char *str,
2454 int create,
2455 const char *virt_type,
2456 virNodeDeviceDefParserCallbacks *parserCallbacks,
2457 void *opaque)
2458 {
2459 return virNodeDeviceDefParse(str, NULL, create, virt_type, parserCallbacks, opaque);
2460 }
2461
2462
2463 virNodeDeviceDef *
virNodeDeviceDefParseFile(const char * filename,int create,const char * virt_type,virNodeDeviceDefParserCallbacks * parserCallbacks,void * opaque)2464 virNodeDeviceDefParseFile(const char *filename,
2465 int create,
2466 const char *virt_type,
2467 virNodeDeviceDefParserCallbacks *parserCallbacks,
2468 void *opaque)
2469 {
2470 return virNodeDeviceDefParse(NULL, filename, create, virt_type, parserCallbacks, opaque);
2471 }
2472
2473
2474 /*
2475 * Return fc_host dev's WWNN and WWPN
2476 */
2477 int
virNodeDeviceGetWWNs(virNodeDeviceDef * def,char ** wwnn,char ** wwpn)2478 virNodeDeviceGetWWNs(virNodeDeviceDef *def,
2479 char **wwnn,
2480 char **wwpn)
2481 {
2482 virNodeDevCapsDef *cap = NULL;
2483
2484 cap = def->caps;
2485 while (cap != NULL) {
2486 if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST &&
2487 cap->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
2488 *wwnn = g_strdup(cap->data.scsi_host.wwnn);
2489 *wwpn = g_strdup(cap->data.scsi_host.wwpn);
2490 break;
2491 }
2492
2493 cap = cap->next;
2494 }
2495
2496 if (cap == NULL) {
2497 virReportError(VIR_ERR_INTERNAL_ERROR,
2498 "%s", _("Device is not a fibre channel HBA"));
2499 return -1;
2500 }
2501
2502 return 0;
2503 }
2504
2505
2506 void
virNodeDevCapsDefFree(virNodeDevCapsDef * caps)2507 virNodeDevCapsDefFree(virNodeDevCapsDef *caps)
2508 {
2509 size_t i = 0;
2510 virNodeDevCapData *data = &caps->data;
2511
2512 switch (caps->data.type) {
2513 case VIR_NODE_DEV_CAP_SYSTEM:
2514 g_free(data->system.product_name);
2515 g_free(data->system.hardware.vendor_name);
2516 g_free(data->system.hardware.version);
2517 g_free(data->system.hardware.serial);
2518 g_free(data->system.firmware.vendor_name);
2519 g_free(data->system.firmware.version);
2520 g_free(data->system.firmware.release_date);
2521 break;
2522 case VIR_NODE_DEV_CAP_PCI_DEV:
2523 g_free(data->pci_dev.product_name);
2524 g_free(data->pci_dev.vendor_name);
2525 g_free(data->pci_dev.physical_function);
2526 for (i = 0; i < data->pci_dev.num_virtual_functions; i++)
2527 g_free(data->pci_dev.virtual_functions[i]);
2528 g_free(data->pci_dev.virtual_functions);
2529 for (i = 0; i < data->pci_dev.nIommuGroupDevices; i++)
2530 g_free(data->pci_dev.iommuGroupDevices[i]);
2531 g_free(data->pci_dev.iommuGroupDevices);
2532 virPCIEDeviceInfoFree(data->pci_dev.pci_express);
2533 for (i = 0; i < data->pci_dev.nmdev_types; i++)
2534 virMediatedDeviceTypeFree(data->pci_dev.mdev_types[i]);
2535 g_free(data->pci_dev.mdev_types);
2536 virPCIVPDResourceFree(g_steal_pointer(&data->pci_dev.vpd));
2537 break;
2538 case VIR_NODE_DEV_CAP_USB_DEV:
2539 g_free(data->usb_dev.product_name);
2540 g_free(data->usb_dev.vendor_name);
2541 break;
2542 case VIR_NODE_DEV_CAP_USB_INTERFACE:
2543 g_free(data->usb_if.description);
2544 break;
2545 case VIR_NODE_DEV_CAP_NET:
2546 g_free(data->net.ifname);
2547 g_free(data->net.address);
2548 virBitmapFree(data->net.features);
2549 break;
2550 case VIR_NODE_DEV_CAP_SCSI_HOST:
2551 g_free(data->scsi_host.wwnn);
2552 g_free(data->scsi_host.wwpn);
2553 g_free(data->scsi_host.fabric_wwn);
2554 break;
2555 case VIR_NODE_DEV_CAP_SCSI_TARGET:
2556 g_free(data->scsi_target.name);
2557 g_free(data->scsi_target.rport);
2558 g_free(data->scsi_target.wwpn);
2559 break;
2560 case VIR_NODE_DEV_CAP_SCSI:
2561 g_free(data->scsi.type);
2562 break;
2563 case VIR_NODE_DEV_CAP_STORAGE:
2564 g_free(data->storage.block);
2565 g_free(data->storage.bus);
2566 g_free(data->storage.drive_type);
2567 g_free(data->storage.model);
2568 g_free(data->storage.vendor);
2569 g_free(data->storage.serial);
2570 g_free(data->storage.media_label);
2571 break;
2572 case VIR_NODE_DEV_CAP_SCSI_GENERIC:
2573 g_free(data->sg.path);
2574 break;
2575 case VIR_NODE_DEV_CAP_MDEV:
2576 g_free(data->mdev.type);
2577 g_free(data->mdev.uuid);
2578 for (i = 0; i < data->mdev.nattributes; i++)
2579 virMediatedDeviceAttrFree(data->mdev.attributes[i]);
2580 g_free(data->mdev.attributes);
2581 g_free(data->mdev.parent_addr);
2582 break;
2583 case VIR_NODE_DEV_CAP_CSS_DEV:
2584 for (i = 0; i < data->ccw_dev.nmdev_types; i++)
2585 virMediatedDeviceTypeFree(data->ccw_dev.mdev_types[i]);
2586 g_free(data->ccw_dev.mdev_types);
2587 break;
2588 case VIR_NODE_DEV_CAP_AP_MATRIX:
2589 g_free(data->ap_matrix.addr);
2590 for (i = 0; i < data->ap_matrix.nmdev_types; i++)
2591 virMediatedDeviceTypeFree(data->ap_matrix.mdev_types[i]);
2592 g_free(data->ap_matrix.mdev_types);
2593 break;
2594 case VIR_NODE_DEV_CAP_MDEV_TYPES:
2595 case VIR_NODE_DEV_CAP_DRM:
2596 case VIR_NODE_DEV_CAP_FC_HOST:
2597 case VIR_NODE_DEV_CAP_VPORTS:
2598 case VIR_NODE_DEV_CAP_CCW_DEV:
2599 case VIR_NODE_DEV_CAP_VDPA:
2600 case VIR_NODE_DEV_CAP_AP_CARD:
2601 case VIR_NODE_DEV_CAP_AP_QUEUE:
2602 case VIR_NODE_DEV_CAP_VPD:
2603 case VIR_NODE_DEV_CAP_LAST:
2604 /* This case is here to shutup the compiler */
2605 break;
2606 }
2607
2608 g_free(caps);
2609 }
2610
2611
2612 int
virNodeDeviceUpdateCaps(virNodeDeviceDef * def)2613 virNodeDeviceUpdateCaps(virNodeDeviceDef *def)
2614 {
2615 virNodeDevCapsDef *cap = def->caps;
2616
2617 while (cap) {
2618 switch (cap->data.type) {
2619 case VIR_NODE_DEV_CAP_SCSI_HOST:
2620 virNodeDeviceGetSCSIHostCaps(&cap->data.scsi_host);
2621 break;
2622 case VIR_NODE_DEV_CAP_SCSI_TARGET:
2623 virNodeDeviceGetSCSITargetCaps(def->sysfs_path,
2624 &cap->data.scsi_target);
2625 break;
2626 case VIR_NODE_DEV_CAP_NET:
2627 if (virNetDevGetLinkInfo(cap->data.net.ifname,
2628 &cap->data.net.lnk) < 0)
2629 return -1;
2630 virBitmapFree(cap->data.net.features);
2631 if (virNetDevGetFeatures(cap->data.net.ifname,
2632 &cap->data.net.features) < 0)
2633 return -1;
2634 break;
2635 case VIR_NODE_DEV_CAP_PCI_DEV:
2636 if (virNodeDeviceGetPCIDynamicCaps(def->sysfs_path,
2637 &cap->data.pci_dev) < 0)
2638 return -1;
2639 break;
2640 case VIR_NODE_DEV_CAP_CSS_DEV:
2641 if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path,
2642 &cap->data.ccw_dev) < 0)
2643 return -1;
2644 break;
2645 case VIR_NODE_DEV_CAP_AP_MATRIX:
2646 if (virNodeDeviceGetAPMatrixDynamicCaps(def->sysfs_path,
2647 &cap->data.ap_matrix) < 0)
2648 return -1;
2649 break;
2650
2651 /* all types that (supposedly) don't require any updates
2652 * relative to what's in the cache.
2653 */
2654 case VIR_NODE_DEV_CAP_DRM:
2655 case VIR_NODE_DEV_CAP_SYSTEM:
2656 case VIR_NODE_DEV_CAP_USB_DEV:
2657 case VIR_NODE_DEV_CAP_USB_INTERFACE:
2658 case VIR_NODE_DEV_CAP_SCSI:
2659 case VIR_NODE_DEV_CAP_STORAGE:
2660 case VIR_NODE_DEV_CAP_FC_HOST:
2661 case VIR_NODE_DEV_CAP_VPORTS:
2662 case VIR_NODE_DEV_CAP_SCSI_GENERIC:
2663 case VIR_NODE_DEV_CAP_MDEV_TYPES:
2664 case VIR_NODE_DEV_CAP_MDEV:
2665 case VIR_NODE_DEV_CAP_CCW_DEV:
2666 case VIR_NODE_DEV_CAP_VDPA:
2667 case VIR_NODE_DEV_CAP_AP_CARD:
2668 case VIR_NODE_DEV_CAP_AP_QUEUE:
2669 case VIR_NODE_DEV_CAP_VPD:
2670 case VIR_NODE_DEV_CAP_LAST:
2671 break;
2672 }
2673 cap = cap->next;
2674 }
2675
2676 return 0;
2677 }
2678
2679
2680 /**
2681 * virNodeDeviceCapsListExport:
2682 * @def: node device definition
2683 * @list: pointer to an array to store all supported capabilities by a device
2684 *
2685 * Takes the definition, scans through all the capabilities that the device
2686 * supports (including the nested caps) and populates a newly allocated list
2687 * with them. Caller is responsible for freeing the list.
2688 * If NULL is passed to @list, only the number of caps will be returned.
2689 *
2690 * Returns the number of capabilities the device supports, -1 on error.
2691 */
2692 int
virNodeDeviceCapsListExport(virNodeDeviceDef * def,virNodeDevCapType ** list)2693 virNodeDeviceCapsListExport(virNodeDeviceDef *def,
2694 virNodeDevCapType **list)
2695 {
2696 virNodeDevCapsDef *caps = NULL;
2697 g_autofree virNodeDevCapType *tmp = NULL;
2698 bool want_list = !!list;
2699 int ncaps = 0;
2700
2701 #define MAYBE_ADD_CAP(cap) \
2702 do { \
2703 if (want_list) \
2704 tmp[ncaps] = cap; \
2705 } while (0)
2706
2707 if (virNodeDeviceUpdateCaps(def) < 0)
2708 return -1;
2709
2710 if (want_list)
2711 tmp = g_new0(virNodeDevCapType, VIR_NODE_DEV_CAP_LAST - 1);
2712
2713 for (caps = def->caps; caps; caps = caps->next) {
2714 unsigned int flags;
2715
2716 MAYBE_ADD_CAP(caps->data.type);
2717 ncaps++;
2718
2719 /* check nested caps for a given type as well */
2720 if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
2721 flags = caps->data.scsi_host.flags;
2722
2723 if (flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
2724 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_FC_HOST);
2725 ncaps++;
2726 }
2727
2728 if (flags & VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS) {
2729 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_VPORTS);
2730 ncaps++;
2731 }
2732 }
2733
2734 if (caps->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
2735 flags = caps->data.pci_dev.flags;
2736
2737 if (flags & VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) {
2738 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES);
2739 ncaps++;
2740 }
2741 if (flags & VIR_NODE_DEV_CAP_FLAG_PCI_VPD) {
2742 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_VPD);
2743 ncaps++;
2744 }
2745 }
2746
2747 if (caps->data.type == VIR_NODE_DEV_CAP_CSS_DEV) {
2748 flags = caps->data.ccw_dev.flags;
2749
2750 if (flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV) {
2751 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES);
2752 ncaps++;
2753 }
2754 }
2755
2756 if (caps->data.type == VIR_NODE_DEV_CAP_AP_MATRIX) {
2757 flags = caps->data.ap_matrix.flags;
2758
2759 if (flags & VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV) {
2760 MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES);
2761 ncaps++;
2762 }
2763 }
2764 }
2765
2766 #undef MAYBE_ADD_CAP
2767
2768 if (want_list)
2769 *list = g_steal_pointer(&tmp);
2770
2771 return ncaps;
2772 }
2773
2774
2775 #ifdef __linux__
2776
2777 int
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHost * scsi_host)2778 virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHost *scsi_host)
2779 {
2780 g_autofree char *tmp = NULL;
2781 int ret = -1;
2782
2783 if ((scsi_host->unique_id =
2784 virSCSIHostGetUniqueId(NULL, scsi_host->host)) < 0) {
2785 VIR_DEBUG("Failed to read unique_id for host%d", scsi_host->host);
2786 scsi_host->unique_id = -1;
2787 }
2788
2789 VIR_DEBUG("Checking if host%d is an FC HBA", scsi_host->host);
2790
2791 if (virVHBAPathExists(NULL, scsi_host->host)) {
2792 scsi_host->flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST;
2793
2794 if (!(tmp = virVHBAGetConfig(NULL, scsi_host->host, "port_name"))) {
2795 VIR_WARN("Failed to read WWPN for host%d", scsi_host->host);
2796 goto cleanup;
2797 }
2798 VIR_FREE(scsi_host->wwpn);
2799 scsi_host->wwpn = g_steal_pointer(&tmp);
2800
2801 if (!(tmp = virVHBAGetConfig(NULL, scsi_host->host, "node_name"))) {
2802 VIR_WARN("Failed to read WWNN for host%d", scsi_host->host);
2803 goto cleanup;
2804 }
2805 VIR_FREE(scsi_host->wwnn);
2806 scsi_host->wwnn = g_steal_pointer(&tmp);
2807
2808 if ((tmp = virVHBAGetConfig(NULL, scsi_host->host, "fabric_name"))) {
2809 VIR_FREE(scsi_host->fabric_wwn);
2810 scsi_host->fabric_wwn = g_steal_pointer(&tmp);
2811 }
2812 }
2813
2814 if (virVHBAIsVportCapable(NULL, scsi_host->host)) {
2815 scsi_host->flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS;
2816
2817 if (!(tmp = virVHBAGetConfig(NULL, scsi_host->host,
2818 "max_npiv_vports"))) {
2819 VIR_WARN("Failed to read max_npiv_vports for host%d",
2820 scsi_host->host);
2821 goto cleanup;
2822 }
2823
2824 if (virStrToLong_i(tmp, NULL, 10, &scsi_host->max_vports) < 0) {
2825 VIR_WARN("Failed to parse value of max_npiv_vports '%s'", tmp);
2826 goto cleanup;
2827 }
2828
2829 if (!(tmp = virVHBAGetConfig(NULL, scsi_host->host,
2830 "npiv_vports_inuse"))) {
2831 VIR_WARN("Failed to read npiv_vports_inuse for host%d",
2832 scsi_host->host);
2833 goto cleanup;
2834 }
2835
2836 if (virStrToLong_i(tmp, NULL, 10, &scsi_host->vports) < 0) {
2837 VIR_WARN("Failed to parse value of npiv_vports_inuse '%s'", tmp);
2838 goto cleanup;
2839 }
2840 }
2841
2842 ret = 0;
2843 cleanup:
2844 if (ret < 0) {
2845 /* Clear the two flags in case of producing confusing XML output */
2846 scsi_host->flags &= ~(VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST |
2847 VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS);
2848
2849 VIR_FREE(scsi_host->wwnn);
2850 VIR_FREE(scsi_host->wwpn);
2851 VIR_FREE(scsi_host->fabric_wwn);
2852 }
2853 return ret;
2854 }
2855
2856
2857 int
virNodeDeviceGetSCSITargetCaps(const char * sysfsPath,virNodeDevCapSCSITarget * scsi_target)2858 virNodeDeviceGetSCSITargetCaps(const char *sysfsPath,
2859 virNodeDevCapSCSITarget *scsi_target)
2860 {
2861 int ret = -1;
2862 g_autofree char *dir = NULL;
2863 g_autofree char *rport = NULL;
2864
2865 VIR_DEBUG("Checking if '%s' is an FC remote port", scsi_target->name);
2866
2867 /* /sys/devices/[...]/host0/rport-0:0-0/target0:0:0 -> rport-0:0-0 */
2868 dir = g_path_get_dirname(sysfsPath);
2869
2870 rport = g_path_get_basename(dir);
2871
2872 if (!virFCIsCapableRport(rport))
2873 goto cleanup;
2874
2875 VIR_FREE(scsi_target->rport);
2876 scsi_target->rport = g_steal_pointer(&rport);
2877
2878 if (virFCReadRportValue(scsi_target->rport, "port_name",
2879 &scsi_target->wwpn) < 0) {
2880 VIR_WARN("Failed to read port_name for '%s'", scsi_target->rport);
2881 goto cleanup;
2882 }
2883
2884 scsi_target->flags |= VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
2885 ret = 0;
2886
2887 cleanup:
2888 if (ret < 0) {
2889 VIR_FREE(scsi_target->rport);
2890 VIR_FREE(scsi_target->wwpn);
2891 scsi_target->flags &= ~VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
2892 }
2893
2894 return ret;
2895 }
2896
2897
2898 static int
virNodeDeviceGetPCISRIOVCaps(const char * sysfsPath,virNodeDevCapPCIDev * pci_dev)2899 virNodeDeviceGetPCISRIOVCaps(const char *sysfsPath,
2900 virNodeDevCapPCIDev *pci_dev)
2901 {
2902 g_autoptr(virPCIVirtualFunctionList) vfs = NULL;
2903 size_t i;
2904 int ret;
2905
2906 /* this could be a refresh, so clear out the old data */
2907 for (i = 0; i < pci_dev->num_virtual_functions; i++)
2908 VIR_FREE(pci_dev->virtual_functions[i]);
2909 VIR_FREE(pci_dev->virtual_functions);
2910 VIR_FREE(pci_dev->physical_function);
2911 pci_dev->num_virtual_functions = 0;
2912 pci_dev->max_virtual_functions = 0;
2913 pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
2914 pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
2915
2916 ret = virPCIGetPhysicalFunction(sysfsPath,
2917 &pci_dev->physical_function);
2918 if (ret < 0)
2919 return ret;
2920
2921 if (pci_dev->physical_function)
2922 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
2923
2924 if (virPCIGetVirtualFunctions(sysfsPath, &vfs) < 0)
2925 return -1;
2926
2927 pci_dev->virtual_functions = g_new0(virPCIDeviceAddress *, vfs->nfunctions);
2928
2929 for (i = 0; i < vfs->nfunctions; i++)
2930 pci_dev->virtual_functions[i] = g_steal_pointer(&vfs->functions[i].addr);
2931
2932 pci_dev->num_virtual_functions = vfs->nfunctions;
2933 pci_dev->max_virtual_functions = vfs->maxfunctions;
2934
2935 if (pci_dev->num_virtual_functions > 0 ||
2936 pci_dev->max_virtual_functions > 0)
2937 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
2938
2939 return ret;
2940 }
2941
2942
2943 static int
virNodeDeviceGetPCIIOMMUGroupCaps(virNodeDevCapPCIDev * pci_dev)2944 virNodeDeviceGetPCIIOMMUGroupCaps(virNodeDevCapPCIDev *pci_dev)
2945 {
2946 size_t i;
2947 int tmpGroup;
2948 virPCIDeviceAddress addr;
2949
2950 /* this could be a refresh, so clear out the old data */
2951 for (i = 0; i < pci_dev->nIommuGroupDevices; i++)
2952 VIR_FREE(pci_dev->iommuGroupDevices[i]);
2953 VIR_FREE(pci_dev->iommuGroupDevices);
2954 pci_dev->nIommuGroupDevices = 0;
2955 pci_dev->iommuGroupNumber = 0;
2956
2957 addr.domain = pci_dev->domain;
2958 addr.bus = pci_dev->bus;
2959 addr.slot = pci_dev->slot;
2960 addr.function = pci_dev->function;
2961 tmpGroup = virPCIDeviceAddressGetIOMMUGroupNum(&addr);
2962 if (tmpGroup == -1) {
2963 /* error was already reported */
2964 return -1;
2965 }
2966 if (tmpGroup == -2)
2967 /* -2 return means there is no iommu_group data */
2968 return 0;
2969 if (tmpGroup >= 0) {
2970 if (virPCIDeviceAddressGetIOMMUGroupAddresses(&addr, &pci_dev->iommuGroupDevices,
2971 &pci_dev->nIommuGroupDevices) < 0)
2972 return -1;
2973 pci_dev->iommuGroupNumber = tmpGroup;
2974 }
2975
2976 return 0;
2977 }
2978
2979
2980 static int
virNodeDeviceGetMdevTypesCaps(const char * sysfspath,virMediatedDeviceType *** mdev_types,size_t * nmdev_types)2981 virNodeDeviceGetMdevTypesCaps(const char *sysfspath,
2982 virMediatedDeviceType ***mdev_types,
2983 size_t *nmdev_types)
2984 {
2985 virMediatedDeviceType **types = NULL;
2986 size_t ntypes = 0;
2987 size_t i;
2988
2989 /* this could be a refresh, so clear out the old data */
2990 for (i = 0; i < *nmdev_types; i++)
2991 virMediatedDeviceTypeFree((*mdev_types)[i]);
2992 VIR_FREE(*mdev_types);
2993 *nmdev_types = 0;
2994
2995 if (virMediatedDeviceGetMdevTypes(sysfspath, &types, &ntypes) < 0)
2996 return -1;
2997
2998 *mdev_types = g_steal_pointer(&types);
2999 *nmdev_types = ntypes;
3000
3001 return 0;
3002 }
3003
3004
3005 /**
3006 * virNodeDeviceGetPCIVPDDynamicCap:
3007 * @devCapPCIDev: a virNodeDevCapPCIDev for which to add VPD resources.
3008 *
3009 * While VPD has a read-only portion, there may be a read-write portion per
3010 * the specs which may change dynamically.
3011 *
3012 * Returns: 0 if the operation was successful (even if VPD is not present for
3013 * that device since it is optional in the specs, -1 otherwise.
3014 */
3015 static int
virNodeDeviceGetPCIVPDDynamicCap(virNodeDevCapPCIDev * devCapPCIDev)3016 virNodeDeviceGetPCIVPDDynamicCap(virNodeDevCapPCIDev *devCapPCIDev)
3017 {
3018 g_autoptr(virPCIDevice) pciDev = NULL;
3019 virPCIDeviceAddress devAddr;
3020 g_autoptr(virPCIVPDResource) res = NULL;
3021
3022 devAddr.domain = devCapPCIDev->domain;
3023 devAddr.bus = devCapPCIDev->bus;
3024 devAddr.slot = devCapPCIDev->slot;
3025 devAddr.function = devCapPCIDev->function;
3026
3027 if (!(pciDev = virPCIDeviceNew(&devAddr)))
3028 return -1;
3029
3030 if (virPCIDeviceHasVPD(pciDev)) {
3031 /* VPD is optional in PCI(e) specs. If it is there, attempt to add it. */
3032 if ((res = virPCIDeviceGetVPD(pciDev))) {
3033 devCapPCIDev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VPD;
3034 devCapPCIDev->vpd = g_steal_pointer(&res);
3035 } else {
3036 virPCIVPDResourceFree(g_steal_pointer(&devCapPCIDev->vpd));
3037 }
3038 }
3039 return 0;
3040 }
3041
3042
3043 /* virNodeDeviceGetPCIDynamicCaps() get info that is stored in sysfs
3044 * about devices related to this device, i.e. things that can change
3045 * without this device itself changing. These must be refreshed
3046 * anytime full XML of the device is requested, because they can
3047 * change with no corresponding notification from the kernel/udev.
3048 */
3049 int
virNodeDeviceGetPCIDynamicCaps(const char * sysfsPath,virNodeDevCapPCIDev * pci_dev)3050 virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
3051 virNodeDevCapPCIDev *pci_dev)
3052 {
3053 if (virNodeDeviceGetPCISRIOVCaps(sysfsPath, pci_dev) < 0 ||
3054 virNodeDeviceGetPCIIOMMUGroupCaps(pci_dev) < 0)
3055 return -1;
3056
3057 pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
3058 if (virNodeDeviceGetMdevTypesCaps(sysfsPath,
3059 &pci_dev->mdev_types,
3060 &pci_dev->nmdev_types) < 0)
3061 return -1;
3062 if (pci_dev->nmdev_types > 0)
3063 pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
3064
3065 if (virNodeDeviceGetPCIVPDDynamicCap(pci_dev) < 0)
3066 return -1;
3067
3068 return 0;
3069 }
3070
3071
3072 /* virNodeDeviceGetCSSDynamicCaps() get info that is stored in sysfs
3073 * about devices related to this device, i.e. things that can change
3074 * without this device itself changing. These must be refreshed
3075 * anytime full XML of the device is requested, because they can
3076 * change with no corresponding notification from the kernel/udev.
3077 */
3078 int
virNodeDeviceGetCSSDynamicCaps(const char * sysfsPath,virNodeDevCapCCW * ccw_dev)3079 virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
3080 virNodeDevCapCCW *ccw_dev)
3081 {
3082 ccw_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
3083 if (virNodeDeviceGetMdevTypesCaps(sysfsPath,
3084 &ccw_dev->mdev_types,
3085 &ccw_dev->nmdev_types) < 0)
3086 return -1;
3087 if (ccw_dev->nmdev_types > 0)
3088 ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CSS_MDEV;
3089
3090 return 0;
3091 }
3092
3093 /* virNodeDeviceGetAPMatrixDynamicCaps() get info that is stored in sysfs
3094 * about devices related to this device, i.e. things that can change
3095 * without this device itself changing. These must be refreshed
3096 * anytime full XML of the device is requested, because they can
3097 * change with no corresponding notification from the kernel/udev.
3098 */
3099 int
virNodeDeviceGetAPMatrixDynamicCaps(const char * sysfsPath,virNodeDevCapAPMatrix * ap_matrix)3100 virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath,
3101 virNodeDevCapAPMatrix *ap_matrix)
3102 {
3103 ap_matrix->flags &= ~VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV;
3104 if (virNodeDeviceGetMdevTypesCaps(sysfsPath,
3105 &ap_matrix->mdev_types,
3106 &ap_matrix->nmdev_types) < 0)
3107 return -1;
3108 if (ap_matrix->nmdev_types > 0)
3109 ap_matrix->flags |= VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV;
3110
3111 return 0;
3112 }
3113
3114 #else
3115
3116 int
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHost * scsi_host G_GNUC_UNUSED)3117 virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHost *scsi_host G_GNUC_UNUSED)
3118 {
3119 return -1;
3120 }
3121
3122 int
virNodeDeviceGetPCIDynamicCaps(const char * sysfsPath G_GNUC_UNUSED,virNodeDevCapPCIDev * pci_dev G_GNUC_UNUSED)3123 virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
3124 virNodeDevCapPCIDev *pci_dev G_GNUC_UNUSED)
3125 {
3126 return -1;
3127 }
3128
3129
virNodeDeviceGetSCSITargetCaps(const char * sysfsPath G_GNUC_UNUSED,virNodeDevCapSCSITarget * scsi_target G_GNUC_UNUSED)3130 int virNodeDeviceGetSCSITargetCaps(const char *sysfsPath G_GNUC_UNUSED,
3131 virNodeDevCapSCSITarget *scsi_target G_GNUC_UNUSED)
3132 {
3133 return -1;
3134 }
3135
3136 int
virNodeDeviceGetCSSDynamicCaps(const char * sysfsPath G_GNUC_UNUSED,virNodeDevCapCCW * ccw_dev G_GNUC_UNUSED)3137 virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
3138 virNodeDevCapCCW *ccw_dev G_GNUC_UNUSED)
3139 {
3140 return -1;
3141 }
3142
3143 int
virNodeDeviceGetAPMatrixDynamicCaps(const char * sysfsPath G_GNUC_UNUSED,virNodeDevCapAPMatrix * ap_matrix G_GNUC_UNUSED)3144 virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
3145 virNodeDevCapAPMatrix *ap_matrix G_GNUC_UNUSED)
3146 {
3147 return -1;
3148 }
3149
3150 #endif /* __linux__ */
3151