pci: Add utility method for getting the MAC addr
We will need to tell Neutron about the MAC address of the PF port as it cannot set by the VIF driver. This method lets su figure it out from sysfs Change-Id: Iad44405488395ce08d1a893f50edfce20fdae7d2 Related-blueprint: sriov-pf-passthrough-neutron-port
This commit is contained in:
parent
410a87ae29
commit
b2385fb781
|
@ -23,6 +23,7 @@ from oslo_log import log as logging
|
|||
import six
|
||||
|
||||
from nova import exception
|
||||
from nova.i18n import _LW
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -105,16 +106,23 @@ def is_physical_function(domain, bus, slot, function):
|
|||
return False
|
||||
|
||||
|
||||
def _get_sysfs_netdev_path(pci_addr, pf_interface):
|
||||
"""Get the sysfs path based on the PCI address of the device.
|
||||
|
||||
Assumes a networking device - will not check for the existence of the path.
|
||||
"""
|
||||
if pf_interface:
|
||||
return "/sys/bus/pci/devices/%s/physfn/net" % (pci_addr)
|
||||
return "/sys/bus/pci/devices/%s/net" % (pci_addr)
|
||||
|
||||
|
||||
def get_ifname_by_pci_address(pci_addr, pf_interface=False):
|
||||
"""Get the interface name based on a VF's pci address
|
||||
|
||||
The returned interface name is either the parent PF's or that of the VF
|
||||
itself based on the argument of pf_interface.
|
||||
"""
|
||||
if pf_interface:
|
||||
dev_path = "/sys/bus/pci/devices/%s/physfn/net" % (pci_addr)
|
||||
else:
|
||||
dev_path = "/sys/bus/pci/devices/%s/net" % (pci_addr)
|
||||
dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface)
|
||||
try:
|
||||
dev_info = os.listdir(dev_path)
|
||||
return dev_info.pop()
|
||||
|
@ -122,6 +130,27 @@ def get_ifname_by_pci_address(pci_addr, pf_interface=False):
|
|||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||
|
||||
|
||||
def get_mac_by_pci_address(pci_addr, pf_interface=False):
|
||||
"""Get the MAC address of the nic based on it's PCI address
|
||||
|
||||
Raises PciDeviceNotFoundById in case the pci device is not a NIC
|
||||
"""
|
||||
dev_path = _get_sysfs_netdev_path(pci_addr, pf_interface)
|
||||
if_name = get_ifname_by_pci_address(pci_addr, pf_interface)
|
||||
addr_file = os.path.join(dev_path, if_name, 'address')
|
||||
|
||||
try:
|
||||
with open(addr_file) as f:
|
||||
mac = next(f).strip()
|
||||
return mac
|
||||
except (IOError, StopIteration) as e:
|
||||
LOG.warning(_LW("Could not find the expected sysfs file for "
|
||||
"determining the MAC address of the PCI device "
|
||||
"%(addr)s. May not be a NIC. Error: %(e)s"),
|
||||
{'addr': pci_addr, 'e': e})
|
||||
raise exception.PciDeviceNotFoundById(id=pci_addr)
|
||||
|
||||
|
||||
def get_vf_num_by_pci_address(pci_addr):
|
||||
"""Get the VF number based on a VF's pci address
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import glob
|
||||
import os
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
from six.moves import builtins
|
||||
|
||||
|
@ -149,6 +150,60 @@ class GetIfnameByPciAddressTestCase(test.NoDBTestCase):
|
|||
)
|
||||
|
||||
|
||||
class GetMacByPciAddressTestCase(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(GetMacByPciAddressTestCase, self).setUp()
|
||||
self.pci_address = '0000:07:00.1'
|
||||
self.if_name = 'enp7s0f1'
|
||||
self.tmpdir = self.useFixture(fixtures.TempDir())
|
||||
self.fake_file = os.path.join(self.tmpdir.path, "address")
|
||||
with open(self.fake_file, "w") as f:
|
||||
f.write("a0:36:9f:72:00:00\n")
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(os.path, 'join')
|
||||
def test_get_mac(self, mock_join, mock_listdir):
|
||||
mock_listdir.return_value = [self.if_name]
|
||||
mock_join.return_value = self.fake_file
|
||||
mac = utils.get_mac_by_pci_address(self.pci_address)
|
||||
mock_join.assert_called_once_with(
|
||||
"/sys/bus/pci/devices/%s/net" % self.pci_address, self.if_name,
|
||||
"address")
|
||||
self.assertEqual("a0:36:9f:72:00:00", mac)
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(os.path, 'join')
|
||||
def test_get_mac_fails(self, mock_join, mock_listdir):
|
||||
os.unlink(self.fake_file)
|
||||
mock_listdir.return_value = [self.if_name]
|
||||
mock_join.return_value = self.fake_file
|
||||
self.assertRaises(
|
||||
exception.PciDeviceNotFoundById,
|
||||
utils.get_mac_by_pci_address, self.pci_address)
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(os.path, 'join')
|
||||
def test_get_mac_fails_empty(self, mock_join, mock_listdir):
|
||||
with open(self.fake_file, "w") as f:
|
||||
f.truncate(0)
|
||||
mock_listdir.return_value = [self.if_name]
|
||||
mock_join.return_value = self.fake_file
|
||||
self.assertRaises(
|
||||
exception.PciDeviceNotFoundById,
|
||||
utils.get_mac_by_pci_address, self.pci_address)
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(os.path, 'join')
|
||||
def test_get_physical_function_mac(self, mock_join, mock_listdir):
|
||||
mock_listdir.return_value = [self.if_name]
|
||||
mock_join.return_value = self.fake_file
|
||||
mac = utils.get_mac_by_pci_address(self.pci_address, pf_interface=True)
|
||||
mock_join.assert_called_once_with(
|
||||
"/sys/bus/pci/devices/%s/physfn/net" % self.pci_address,
|
||||
self.if_name, "address")
|
||||
self.assertEqual("a0:36:9f:72:00:00", mac)
|
||||
|
||||
|
||||
class GetVfNumByPciAddressTestCase(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue