118 lines
3.4 KiB
Python
Executable File
118 lines
3.4 KiB
Python
Executable File
#! /usr/bin/python
|
|
|
|
#
|
|
# Copyright (c) 2015 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
import sys
|
|
import os
|
|
import json
|
|
import fnmatch
|
|
|
|
|
|
def usage():
|
|
argv0 = os.path.basename(sys.argv[0])
|
|
print """
|
|
Usage:
|
|
------
|
|
%(argv0)s pci_pt_whitelist pci_sriov_whitelist
|
|
|
|
Where pci_pt_whitelist is a list of passthrough devices and the
|
|
pci_sriov_whitelist is a list of SR-IOV interfaces. The format of the lists
|
|
are as follows:
|
|
|
|
pci_pt_whitelist:
|
|
[{"address": "0000:09:00.0"}, ..]
|
|
|
|
pci_sriov_whitelist:
|
|
[{"sriov_numvfs": 16, "physical_network": "group0-nic0",
|
|
"address": "0000:02:00.0"}, ..]
|
|
|
|
""" % locals() # replace items from local variables
|
|
|
|
|
|
def get_vf_whitelist(sriov_if):
|
|
'''For the given PF PCI address and provider network, generate the list of VF
|
|
PCI addresses to create a VF based whitelist'''
|
|
|
|
pf_addr = sriov_if.get('address')
|
|
dirpcidev = '/sys/bus/pci/devices/' + pf_addr
|
|
|
|
# Attempt to configure the requested number of VFs if the device supports
|
|
# setting the number of VFs via sysfs
|
|
# Need to write 0 to sriov_numvfs before writing a new value.
|
|
numvfs = sriov_if.get('sriov_numvfs')
|
|
if numvfs is not None:
|
|
numvfs_path = os.path.join(dirpcidev, 'sriov_numvfs')
|
|
if os.path.isfile(numvfs_path):
|
|
with open(numvfs_path, 'w') as f:
|
|
f.write('0')
|
|
f.flush()
|
|
f.write(str(numvfs))
|
|
|
|
virtfn_links = len(fnmatch.filter(os.listdir(dirpcidev), 'virtfn*'))
|
|
|
|
# Some devices (for e.g. Coleto Creek) don't support configuration of the
|
|
# number of VFs. Use all the VFs present in this case.
|
|
if numvfs is not None:
|
|
if virtfn_links != numvfs:
|
|
print 'Configured number of VFs is different than the present ones', \
|
|
'(if:%s conf:%d present:%d)' % (pf_addr, numvfs, virtfn_links)
|
|
exit(1)
|
|
else:
|
|
numvfs = virtfn_links
|
|
|
|
pci_sriov_vf_whitelist = []
|
|
i = 0
|
|
while i < int(numvfs):
|
|
lvf = dirpcidev + '/virtfn' + str(i)
|
|
try:
|
|
vf_addr = os.path.basename(os.readlink(lvf))
|
|
except:
|
|
print("virtfn link %s non-existent (numvfs=%s)" % (lvf, numvfs))
|
|
sys.exit(1)
|
|
|
|
device = {'address': vf_addr}
|
|
|
|
# Some devices (for e.g. Coleto Creek) are not associated with a
|
|
# physical network.
|
|
providernets = sriov_if.get('physical_network')
|
|
if providernets:
|
|
device.update({'physical_network': providernets})
|
|
|
|
pci_sriov_vf_whitelist.append(device)
|
|
i += 1
|
|
|
|
return pci_sriov_vf_whitelist
|
|
|
|
|
|
def main():
|
|
''' The goal of this script is to properly discover SR-IOV VF PCI addresses
|
|
for interfaces that were configured for SR-IOV. It is used by the
|
|
nova-compute puppet manifest and is run at manifest application time. This
|
|
script should be run after the VF driver is loaded and the VF PCI addresses
|
|
are visible in the system.'''
|
|
|
|
if len(sys.argv) < 3:
|
|
usage()
|
|
sys.exit(1)
|
|
|
|
try:
|
|
pci_pt_whitelist = json.loads(sys.argv[1])
|
|
pci_sriov_whitelist = json.loads(sys.argv[2])
|
|
except:
|
|
usage()
|
|
exit(1)
|
|
|
|
for sriov_if in pci_sriov_whitelist:
|
|
pci_sriov_vf_whitelist = get_vf_whitelist(sriov_if)
|
|
pci_pt_whitelist.extend(pci_sriov_vf_whitelist)
|
|
|
|
return pci_pt_whitelist
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print json.dumps(main())
|