@@ -284,49 +284,62 @@ def __init__(self, dev_type, slot, function, iommu_group, numa_node,
284
284
:param multiple_gpu_types: (bool) Supports different vGPU types
285
285
"""
286
286
287
+ self .dev_type = dev_type
288
+ self .slot = slot
289
+ self .function = function
290
+ self .iommu_group = iommu_group
291
+ self .numa_node = numa_node
292
+ self .vf_ratio = vf_ratio
293
+ self .multiple_gpu_types = multiple_gpu_types
294
+ self .parent = parent
295
+ self .generate_xml ()
296
+
297
+ def generate_xml (self , skip_capability = False ):
287
298
vend_id = PCI_VEND_ID
288
299
vend_name = PCI_VEND_NAME
289
- if dev_type == 'PCI' :
290
- if vf_ratio :
300
+ capability = ''
301
+ if self .dev_type == 'PCI' :
302
+ if self .vf_ratio :
291
303
raise ValueError ('vf_ratio does not apply for PCI devices' )
292
304
293
305
prod_id = PCI_PROD_ID
294
306
prod_name = PCI_PROD_NAME
295
307
driver = PCI_DRIVER_NAME
296
- capability = ''
297
- elif dev_type == 'PF' :
308
+ elif self .dev_type == 'PF' :
298
309
prod_id = PF_PROD_ID
299
310
prod_name = PF_PROD_NAME
300
311
driver = PF_DRIVER_NAME
301
- capability = self .cap_templ % {
302
- 'cap_type' : PF_CAP_TYPE ,
303
- 'addresses' : '\n ' .join ([
304
- self .addr_templ % {
305
- # these are the slot, function values of the child VFs
306
- # we can only assign 8 functions to a slot (0-7) so
307
- # bump the slot each time we exceed this
308
- 'slot' : slot + (x // 8 ),
309
- # ...and wrap the function value
310
- 'function' : x % 8 ,
311
- # the offset is because the PF is occupying function 0
312
- } for x in range (1 , vf_ratio + 1 )])
313
- }
314
- elif dev_type == 'VF' :
312
+ if not skip_capability :
313
+ capability = self .cap_templ % {
314
+ 'cap_type' : PF_CAP_TYPE ,
315
+ 'addresses' : '\n ' .join ([
316
+ self .addr_templ % {
317
+ # these are the slot, function values of the child
318
+ # VFs, we can only assign 8 functions to a slot
319
+ # (0-7) so bump the slot each time we exceed this
320
+ 'slot' : self .slot + (x // 8 ),
321
+ # ...and wrap the function value
322
+ 'function' : x % 8 ,
323
+ # the offset is because the PF is occupying function 0
324
+ } for x in range (1 , self .vf_ratio + 1 )])
325
+ }
326
+ elif self .dev_type == 'VF' :
315
327
prod_id = VF_PROD_ID
316
328
prod_name = VF_PROD_NAME
317
329
driver = VF_DRIVER_NAME
318
- capability = self .cap_templ % {
319
- 'cap_type' : VF_CAP_TYPE ,
320
- 'addresses' : self .addr_templ % {
321
- # this is the slot, function value of the parent PF
322
- # if we're e.g. device 8, we'll have a different slot
323
- # to our parent so reverse this
324
- 'slot' : slot - ((vf_ratio + 1 ) // 8 ),
325
- # the parent PF is always function 0
326
- 'function' : 0 ,
330
+ if not skip_capability :
331
+ capability = self .cap_templ % {
332
+ 'cap_type' : VF_CAP_TYPE ,
333
+ 'addresses' : self .addr_templ % {
334
+ # this is the slot, function value of the parent PF
335
+ # if we're e.g. device 8, we'll have a different slot
336
+ # to our parent so reverse this
337
+ 'slot' : self .slot - ((self .vf_ratio + 1 ) // 8 ),
338
+ # the parent PF is always function 0
339
+ 'function' : 0 ,
340
+ }
327
341
}
328
- }
329
- elif dev_type == 'MDEV_TYPES' :
342
+ elif self .dev_type == 'MDEV_TYPES' :
330
343
prod_id = MDEV_CAPABLE_PROD_ID
331
344
prod_name = MDEV_CAPABLE_PROD_NAME
332
345
driver = MDEV_CAPABLE_DRIVER_NAME
@@ -336,36 +349,37 @@ def __init__(self, dev_type, slot, function, iommu_group, numa_node,
336
349
'type_id' : NVIDIA_11_VGPU_TYPE ,
337
350
'instances' : 16 ,
338
351
}]
339
- if multiple_gpu_types :
352
+ if self . multiple_gpu_types :
340
353
types .append (self .mdevtypes_templ % {
341
354
'type_id' : NVIDIA_12_VGPU_TYPE ,
342
355
'instances' : 8 ,
343
356
})
344
- capability = self .cap_templ % {
345
- 'cap_type' : MDEV_CAPABLE_CAP_TYPE ,
346
- 'addresses' : '\n ' .join (types )
347
- }
357
+ if not skip_capability :
358
+ capability = self .cap_templ % {
359
+ 'cap_type' : MDEV_CAPABLE_CAP_TYPE ,
360
+ 'addresses' : '\n ' .join (types )
361
+ }
348
362
self .is_capable_of_mdevs = True
349
363
else :
350
364
raise ValueError ('Expected one of: PCI, VF, PCI' )
351
365
352
366
self .pci_device = self .pci_device_template % {
353
- 'slot' : slot ,
354
- 'function' : function ,
367
+ 'slot' : self . slot ,
368
+ 'function' : self . function ,
355
369
'vend_id' : vend_id ,
356
370
'vend_name' : vend_name ,
357
371
'prod_id' : prod_id ,
358
372
'prod_name' : prod_name ,
359
373
'driver' : driver ,
360
374
'capability' : capability ,
361
- 'iommu_group' : iommu_group ,
362
- 'numa_node' : numa_node ,
363
- 'parent' : parent or self .pci_default_parent
375
+ 'iommu_group' : self . iommu_group ,
376
+ 'numa_node' : self . numa_node ,
377
+ 'parent' : self . parent or self .pci_default_parent
364
378
}
365
379
# -1 is the sentinel set in /sys/bus/pci/devices/*/numa_node
366
380
# for no NUMA affinity. When the numa_node is set to -1 on a device
367
381
# Libvirt omits the NUMA element so we remove it.
368
- if numa_node == - 1 :
382
+ if self . numa_node == - 1 :
369
383
self .pci_device = self .pci_device .replace ("<numa node='-1'/>" , "" )
370
384
371
385
def XMLDesc (self , flags ):
@@ -943,6 +957,20 @@ def _parse_definition(self, xml):
943
957
nic_info ['source' ] = source .get ('network' )
944
958
elif nic_info ['type' ] == 'bridge' :
945
959
nic_info ['source' ] = source .get ('bridge' )
960
+ elif nic_info ['type' ] == 'hostdev' :
961
+ # <interface type='hostdev'> is for VF when vnic_type
962
+ # is direct. Add sriov vf pci information in nic_info
963
+ address = source .find ('./address' )
964
+ pci_type = address .get ('type' )
965
+ pci_domain = address .get ('domain' ).replace ('0x' , '' )
966
+ pci_bus = address .get ('bus' ).replace ('0x' , '' )
967
+ pci_slot = address .get ('slot' ).replace ('0x' , '' )
968
+ pci_function = address .get ('function' ).replace (
969
+ '0x' , '' )
970
+ pci_device = "%s_%s_%s_%s_%s" % (pci_type , pci_domain ,
971
+ pci_bus , pci_slot ,
972
+ pci_function )
973
+ nic_info ['source' ] = pci_device
946
974
947
975
nics_info += [nic_info ]
948
976
@@ -984,11 +1012,32 @@ def _parse_definition(self, xml):
984
1012
985
1013
return definition
986
1014
1015
+ def verify_hostdevs_interface_are_vfs (self ):
1016
+ """Verify for interface type hostdev if the pci device is VF or not.
1017
+ """
1018
+
1019
+ error_message = ("Interface type hostdev is currently supported on "
1020
+ "SR-IOV Virtual Functions only" )
1021
+
1022
+ nics = self ._def ['devices' ].get ('nics' , [])
1023
+ for nic in nics :
1024
+ if nic ['type' ] == 'hostdev' :
1025
+ pci_device = nic ['source' ]
1026
+ pci_info_from_connection = self ._connection .pci_info .devices [
1027
+ pci_device ]
1028
+ if 'phys_function' not in pci_info_from_connection .pci_device :
1029
+ raise make_libvirtError (
1030
+ libvirtError ,
1031
+ error_message ,
1032
+ error_code = VIR_ERR_CONFIG_UNSUPPORTED ,
1033
+ error_domain = VIR_FROM_DOMAIN )
1034
+
987
1035
def create (self ):
988
1036
self .createWithFlags (0 )
989
1037
990
1038
def createWithFlags (self , flags ):
991
1039
# FIXME: Not handling flags at the moment
1040
+ self .verify_hostdevs_interface_are_vfs ()
992
1041
self ._state = VIR_DOMAIN_RUNNING
993
1042
self ._connection ._mark_running (self )
994
1043
self ._has_saved_state = False
@@ -1112,7 +1161,7 @@ def XMLDesc(self, flags):
1112
1161
1113
1162
nics = ''
1114
1163
for nic in self ._def ['devices' ]['nics' ]:
1115
- if 'source' in nic :
1164
+ if 'source' in nic and nic [ 'type' ] != 'hostdev' :
1116
1165
nics += '''<interface type='%(type)s'>
1117
1166
<mac address='%(mac)s'/>
1118
1167
<source %(type)s='%(source)s'/>
0 commit comments