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