@@ -284,49 +284,62 @@ def __init__(self, dev_type, slot, function, iommu_group, numa_node,
284284 :param multiple_gpu_types: (bool) Supports different vGPU types
285285 """
286286
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 ):
287298 vend_id = PCI_VEND_ID
288299 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 :
291303 raise ValueError ('vf_ratio does not apply for PCI devices' )
292304
293305 prod_id = PCI_PROD_ID
294306 prod_name = PCI_PROD_NAME
295307 driver = PCI_DRIVER_NAME
296- capability = ''
297- elif dev_type == 'PF' :
308+ elif self .dev_type == 'PF' :
298309 prod_id = PF_PROD_ID
299310 prod_name = PF_PROD_NAME
300311 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' :
315327 prod_id = VF_PROD_ID
316328 prod_name = VF_PROD_NAME
317329 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+ }
327341 }
328- }
329- elif dev_type == 'MDEV_TYPES' :
342+ elif self .dev_type == 'MDEV_TYPES' :
330343 prod_id = MDEV_CAPABLE_PROD_ID
331344 prod_name = MDEV_CAPABLE_PROD_NAME
332345 driver = MDEV_CAPABLE_DRIVER_NAME
@@ -336,36 +349,37 @@ def __init__(self, dev_type, slot, function, iommu_group, numa_node,
336349 'type_id' : NVIDIA_11_VGPU_TYPE ,
337350 'instances' : 16 ,
338351 }]
339- if multiple_gpu_types :
352+ if self . multiple_gpu_types :
340353 types .append (self .mdevtypes_templ % {
341354 'type_id' : NVIDIA_12_VGPU_TYPE ,
342355 'instances' : 8 ,
343356 })
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+ }
348362 self .is_capable_of_mdevs = True
349363 else :
350364 raise ValueError ('Expected one of: PCI, VF, PCI' )
351365
352366 self .pci_device = self .pci_device_template % {
353- 'slot' : slot ,
354- 'function' : function ,
367+ 'slot' : self . slot ,
368+ 'function' : self . function ,
355369 'vend_id' : vend_id ,
356370 'vend_name' : vend_name ,
357371 'prod_id' : prod_id ,
358372 'prod_name' : prod_name ,
359373 'driver' : driver ,
360374 '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
364378 }
365379 # -1 is the sentinel set in /sys/bus/pci/devices/*/numa_node
366380 # for no NUMA affinity. When the numa_node is set to -1 on a device
367381 # Libvirt omits the NUMA element so we remove it.
368- if numa_node == - 1 :
382+ if self . numa_node == - 1 :
369383 self .pci_device = self .pci_device .replace ("<numa node='-1'/>" , "" )
370384
371385 def XMLDesc (self , flags ):
@@ -943,6 +957,20 @@ def _parse_definition(self, xml):
943957 nic_info ['source' ] = source .get ('network' )
944958 elif nic_info ['type' ] == 'bridge' :
945959 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
946974
947975 nics_info += [nic_info ]
948976
@@ -984,11 +1012,32 @@ def _parse_definition(self, xml):
9841012
9851013 return definition
9861014
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+
9871035 def create (self ):
9881036 self .createWithFlags (0 )
9891037
9901038 def createWithFlags (self , flags ):
9911039 # FIXME: Not handling flags at the moment
1040+ self .verify_hostdevs_interface_are_vfs ()
9921041 self ._state = VIR_DOMAIN_RUNNING
9931042 self ._connection ._mark_running (self )
9941043 self ._has_saved_state = False
@@ -1112,7 +1161,7 @@ def XMLDesc(self, flags):
11121161
11131162 nics = ''
11141163 for nic in self ._def ['devices' ]['nics' ]:
1115- if 'source' in nic :
1164+ if 'source' in nic and nic [ 'type' ] != 'hostdev' :
11161165 nics += '''<interface type='%(type)s'>
11171166 <mac address='%(mac)s'/>
11181167 <source %(type)s='%(source)s'/>
0 commit comments