vDPA support for CentOS9

Multiple things changed between latest release of CentOS8 and CentOS9
that affects the vDPA stack:
- The vhost devices are no longer created automatically by the kernel
  module, we need to use the newly introduced vdpa command.
- The naming of the interfaces has changed drastically and they are no
  more triggering the udev rules.
- The udev devices are lacking some easily matchable attributes so we
  need to match by MAC address.

We're also moving a few functions from utils/sriov_config to the new
common library for easier maintenance.

Conflict:
    os_net_config/sriov_config.py

Change-Id: I1d718c8d949ac04c560a726f54b64aea0b162081
(cherry picked from commit b30304d706)
This commit is contained in:
David Vallee Delisle 2021-10-22 21:58:54 -04:00 committed by Karthik S
parent d5ab3eeed1
commit 6626afc240
12 changed files with 508 additions and 313 deletions

View File

@ -22,12 +22,47 @@
import logging
import logging.handlers
import os
from oslo_concurrency import processutils
import sys
import yaml
# File to contain the DPDK mapped nics, as nic name will not be available after
# binding driver, which is required for correct nic numbering.
# Format of the file (list mapped nic's details):
# -
# name: eth1
# pci_address: 0000:02:00.0
# mac_address: 01:02:03:04:05:06
# driver: vfio-pci
DPDK_MAPPING_FILE = '/var/lib/os-net-config/dpdk_mapping.yaml'
# File to contain the list of SR-IOV PF, VF and their configurations
# Format of the file shall be
# - device_type: pf
# name: <pf name>
# numvfs: <number of VFs>
# promisc: "on"/"off"
# - device_type: vf
# device:
# name: <pf name>
# vfid: <VF id>
# name: <vf name>
# vlan_id: <vlan>
# qos: <qos>
# spoofcheck: "on"/"off"
# trust: "on"/"off"
# state: "auto"/"enable"/"disable"
# macaddr: <mac address>
# promisc: "on"/"off"
SRIOV_CONFIG_FILE = '/var/lib/os-net-config/sriov_config.yaml'
SYS_CLASS_NET = '/sys/class/net'
_LOG_FILE = '/var/log/os-net-config.log'
MLNX_VENDOR_ID = "0x15b3"
logger = logging.getLogger(__name__)
def configure_logger(log_file=False, verbose=False, debug=False):
LOG_FORMAT = ('%(asctime)s.%(msecs)03d %(levelname)s '
@ -87,6 +122,96 @@ def get_device_id(ifname):
return
def get_file_data(filename):
if not os.path.exists(filename):
return ''
try:
with open(filename, 'r') as f:
return f.read()
except IOError:
logger.error(f"Error reading file: {filename}")
return ''
def get_sriov_map(pf_name=None):
contents = get_file_data(SRIOV_CONFIG_FILE)
sriov_map = yaml.safe_load(contents) if contents else []
if len(sriov_map) and pf_name:
return [pf for pf in sriov_map if pf['name'] == pf_name]
return sriov_map
def _get_dpdk_mac_address(name):
contents = get_file_data(DPDK_MAPPING_FILE)
dpdk_map = yaml.safe_load(contents) if contents else []
for item in dpdk_map:
if item['name'] == name:
return item['mac_address']
def interface_mac(name):
try: # If the iface is part of a Linux bond, the real MAC is only here.
with open(get_dev_path(name, 'bonding_slave/perm_hwaddr'),
'r') as f:
return f.read().rstrip()
except IOError:
pass # Iface is not part of a bond, continue
try:
with open(get_dev_path(name, '_address'), 'r') as f:
return f.read().rstrip()
except IOError:
# If the interface is bound to a DPDK driver, get the mac address from
# the DPDK mapping file as /sys files will be removed after binding.
dpdk_mac_address = _get_dpdk_mac_address(name)
if dpdk_mac_address:
return dpdk_mac_address
logger.error("Unable to read mac address: %s" % name)
raise
def is_mellanox_interface(ifname):
vendor_id = get_vendor_id(ifname)
return vendor_id == MLNX_VENDOR_ID
def list_kmods(mods: list) -> list:
"""Listing Kernel Modules
Checks in currently loaded modules for a list
of modules and returns the ones that are not loaded
"""
try:
stdout, stderr = processutils.execute('lsmod')
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to get lsmod: {exc}")
raise
modules = set([line.split()[0] for line in stdout.strip().split('\n')])
return list(set(mods) - set(modules))
def load_kmods(mods: list):
"""Loading Kernel Modules
Loads modules from list that are not already loaded
"""
needed = list_kmods(mods)
for mod in needed:
try:
stdout, stderr = processutils.execute('modprobe', mod)
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to modprobe {mod}: {exc}")
raise
def restorecon(path: str):
"""Executes restorecon on a path"""
logger.info(f"Restoring selinux context on {path}")
try:
stdout, stderr = processutils.execute('restorecon', '-R', '-F', '-v',
path)
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to restorecon on {path}: {exc}")
raise
logger.debug(f"Restorecon completed: {stdout}")

View File

@ -18,10 +18,10 @@ import logging
import netaddr
import os_net_config
from os_net_config import common
from os_net_config import objects
from os_net_config import utils
logger = logging.getLogger(__name__)
@ -98,7 +98,8 @@ class ENINetConfig(os_net_config.NetConfig):
if isinstance(mem, objects.Interface):
data += " pre-up ip addr flush dev %s\n" % mem.name
if interface.primary_interface_name:
mac = utils.interface_mac(interface.primary_interface_name)
mac = common.interface_mac(
interface.primary_interface_name)
ovs_extra.append("set bridge %s other-config:hwaddr=%s" %
(interface.name, mac))
ovs_extra.extend(interface.ovs_extra)

View File

@ -248,7 +248,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
:returns: boolean value for whether a restart is required
"""
file_data = utils.get_file_data(filename)
file_data = common.get_file_data(filename)
logger.debug("Original ifcfg file:\n%s" % file_data)
logger.debug("New ifcfg file:\n%s" % new_data)
file_values = self.parse_ifcfg(file_data)
@ -292,7 +292,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
:returns: commands (commands to be run)
"""
previous_cfg = utils.get_file_data(filename)
previous_cfg = common.get_file_data(filename)
file_values = self.parse_ifcfg(previous_cfg)
data_values = self.parse_ifcfg(data)
logger.debug("File values:\n%s" % file_values)
@ -341,7 +341,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
:return: list of commands to feed to 'ip' to reconfigure routes
"""
file_values = self.parse_ifcfg_routes(utils.get_file_data(filename))
file_values = self.parse_ifcfg_routes(common.get_file_data(filename))
data_values = self.parse_ifcfg_routes(data)
route_changes = self.enumerate_ifcfg_route_changes(file_values,
data_values)
@ -366,7 +366,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
:return: list of commands to feed to 'ip' to reconfigure route rules
"""
file_values = self.parse_ifcfg_rules(utils.get_file_data(filename))
file_values = self.parse_ifcfg_rules(common.get_file_data(filename))
data_values = self.parse_ifcfg_rules(data)
rule_changes = self.enumerate_ifcfg_rule_changes(file_values,
data_values)
@ -473,7 +473,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
if base_opt.use_dhcp:
data += ("OVSDHCPINTERFACES=\"%s\"\n" % " ".join(members))
if base_opt.primary_interface_name:
mac = utils.interface_mac(base_opt.primary_interface_name)
mac = common.interface_mac(base_opt.primary_interface_name)
ovs_extra.append("set bridge %s other-config:hwaddr=%s" %
(base_opt.name, mac))
if base_opt.ovs_options:
@ -517,12 +517,12 @@ class IfcfgNetConfig(os_net_config.NetConfig):
self.member_names[base_opt.name] = members
if base_opt.primary_interface_name:
primary_name = base_opt.primary_interface_name
primary_mac = utils.interface_mac(primary_name)
primary_mac = common.interface_mac(primary_name)
data += "MACADDR=\"%s\"\n" % primary_mac
elif isinstance(base_opt, objects.LinuxBond):
if base_opt.primary_interface_name:
primary_name = base_opt.primary_interface_name
primary_mac = utils.interface_mac(primary_name)
primary_mac = common.interface_mac(primary_name)
data += "MACADDR=\"%s\"\n" % primary_mac
if base_opt.use_dhcp:
data += "BOOTPROTO=dhcp\n"
@ -534,7 +534,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
elif isinstance(base_opt, objects.LinuxTeam):
if base_opt.primary_interface_name:
primary_name = base_opt.primary_interface_name
primary_mac = utils.interface_mac(primary_name)
primary_mac = common.interface_mac(primary_name)
data += "MACADDR=\"%s\"\n" % primary_mac
if base_opt.use_dhcp:
data += "BOOTPROTO=dhcp\n"
@ -1070,7 +1070,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
if not vpp_interface.pci_dev:
vpp_interface.pci_dev = utils.get_stored_pci_address(
vpp_interface.name, False)
vpp_interface.hwaddr = utils.interface_mac(vpp_interface.name)
vpp_interface.hwaddr = common.interface_mac(vpp_interface.name)
if not self.noop:
self.ifdown(vpp_interface.name)
remove_ifcfg_config(vpp_interface.name)
@ -1211,7 +1211,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
custom_tables = {}
res_ids = ['0', '253', '254', '255']
res_names = ['unspec', 'default', 'main', 'local']
rt_config = utils.get_file_data(route_table_config_path()).split('\n')
rt_config = common.get_file_data(route_table_config_path()).split('\n')
rt_defaults = _ROUTE_TABLE_DEFAULT.split("\n")
data = _ROUTE_TABLE_DEFAULT
for line in (line for line in rt_config if line not in rt_defaults):

View File

@ -23,6 +23,7 @@ import logging
import netaddr
from oslo_utils import strutils
from os_net_config import common
from os_net_config import utils
@ -151,7 +152,7 @@ def mapped_nics(nic_mapping=None):
# If 'nic' is actually a mac address, retrieve actual nic name
for nic in available_nics:
try:
mac = utils.interface_mac(nic)
mac = common.interface_mac(nic)
except IOError:
continue
if nic_mapped == mac:
@ -352,7 +353,7 @@ class _BaseOpts(object):
self.name = name
self.hwname = '%s%s' % (mapped_nic_names[base_name],
vlan_suffix)
self.hwaddr = utils.interface_mac(self.hwname)
self.hwaddr = common.interface_mac(self.hwname)
self.renamed = True
else:
self.name = '%s%s' % (mapped_nic_names[base_name], vlan_suffix)

View File

@ -28,8 +28,8 @@ import queue
import re
import sys
import time
import yaml
from json import loads
from os_net_config import common
from os_net_config import sriov_bind_config
from oslo_concurrency import processutils
@ -43,9 +43,16 @@ _RESET_SRIOV_RULES_FILE = '/etc/udev/rules.d/70-tripleo-reset-sriov.rules'
_ALLOCATE_VFS_FILE = '/etc/sysconfig/allocate_vfs'
_MLNX_DRIVER = "mlx5_core"
MLNX_UNBIND_FILE_PATH = "/sys/bus/pci/drivers/mlx5_core/unbind"
MLNX5_VDPA_KMODS = [
"vdpa",
"vhost_vdpa",
"mlx5_vdpa",
]
MAX_RETRIES = 10
PF_FUNC_RE = re.compile(r"\.(\d+)$", 0)
VF_PCI_RE = re.compile(r'/[\d]{4}\:(\d+):(\d+)\.(\d+)/net/[^\/]+$')
# In order to keep VF representor name consistent specially after the upgrade
# proccess, we should have a udev rule to handle that.
# The udev rule will rename the VF representor as "<sriov_pf_name>_<vf_num>"
@ -61,25 +68,9 @@ echo "NUMBER=${PORT##pf*vf}"
vf_queue = queue.Queue()
# File to contain the list of SR-IOV PF, VF and their configurations
# Format of the file shall be
# - device_type: pf
# name: <pf name>
# numvfs: <number of VFs>
# promisc: "on"/"off"
# - device_type: vf
# device:
# name: <pf name>
# vfid: <VF id>
# name: <vf name>
# vlan_id: <vlan>
# qos: <qos>
# spoofcheck: "on"/"off"
# trust: "on"/"off"
# state: "auto"/"enable"/"disable"
# macaddr: <mac address>
# promisc: "on"/"off"
_SRIOV_CONFIG_FILE = '/var/lib/os-net-config/sriov_config.yaml'
# Global variable to store link between pci/pf
# for udev rule creationg when dealing with mlnx vdpa
vf_to_pf = {}
class SRIOVNumvfsException(ValueError):
@ -94,50 +85,79 @@ def udev_event_handler(action, device):
vf_queue.put(event)
def get_file_data(filename):
if not os.path.exists(filename):
return ''
try:
with open(filename, 'r') as f:
return f.read()
except IOError:
logger.error(f"Error reading file: {filename}")
return ''
def _norm_path(dev, suffix):
return os.path.normpath(os.path.join(dev, suffix))
def _get_sriov_map():
contents = get_file_data(_SRIOV_CONFIG_FILE)
sriov_map = yaml.safe_load(contents) if contents else []
return sriov_map
def _get_pf_path(device):
pf_path = _norm_path(device, "../../physfn/net")
if not os.path.isdir(pf_path):
pf_path = _norm_path(device, "physfn/net")
if not os.path.isdir(pf_path):
pf_path = None
return pf_path
def _driver_unbind(dev):
vf_pci_path = f"/sys/bus/pci/devices/{dev}/driver"
if os.path.exists(vf_pci_path):
logger.info(f"{dev}: Unbinding driver")
with open(MLNX_UNBIND_FILE_PATH, 'w') as f:
f.write(dev)
else:
logger.info(f"{dev}: No driver to unbind")
def _wait_for_vf_creation(pf_name, numvfs):
vf_count = 0
vf_list = []
pf_config = common.get_sriov_map(pf_name)
vdpa = False
if len(pf_config):
vdpa = pf_config[0].get('vdpa', False)
while vf_count < numvfs:
try:
# wait for 5 seconds after every udev event
event = vf_queue.get(True, 5)
vf_name = os.path.basename(event["device"])
pf_path = os.path.normpath(os.path.join(event["device"],
"../../physfn/net"))
if os.path.isdir(pf_path):
pf_path = _get_pf_path(event["device"])
logger.debug(f"{event['device']}: Got udev event: {event}")
if pf_path:
pf_nic = os.listdir(pf_path)
if len(pf_nic) == 1 and pf_name == pf_nic[0]:
if vf_name not in vf_list:
vf_list.append(vf_name)
logger.info(
f"VF: {vf_name} created for PF: {pf_name}"
)
vf_count = vf_count + 1
# NOTE(dvd): For vDPA devices, the VF event we're interrested
# in contains all the VFs. We can also use this to build a dict
# to correlate the VF pci address to the PF when creating the
# vdpa representator udev rule
#
# Data structure sample for vDPA:
# pf_path:
# /sys/devices/pci0000:00/0000:00:02.2/0000:06:01.2/physfn/net
# pf_nic: ['enp6s0f1np1_0', 'enp6s0f1np1_1', 'enp6s0f1np1']
# pf_name: enp6s0f1np1
if vf_name not in vf_to_pf and pf_name in pf_nic:
vf_to_pf[vf_name] = {
'device': event['device'],
'pf': pf_name
}
logger.info(
f"{pf_name}: VF {vf_name} created"
)
vf_count += 1
elif vf_name in vf_to_pf:
logger.debug(
f"{pf_name}: VF {vf_name} was already created"
)
elif vdpa:
logger.warning(f"{pf_name}: This PF is not in {pf_path}")
else:
logger.warning(f"Unable to parse event {event['device']}")
else:
logger.warning(f"{pf_path} is not a directory")
logger.warning(
f"{pf_name}: Unable to parse event {event['device']}"
)
elif not vdpa:
logger.warning(f"{event['device']}: Unable to find PF")
except queue.Empty:
logger.info(f"Timeout in the creation of VFs for PF {pf_name}")
logger.info(f"{pf_name}: Timeout in the creation of VFs")
return
logger.info(f"Required VFs are created for PF {pf_name}")
logger.info(f"{pf_name}: Required VFs are created")
def get_numvfs(ifname):
@ -150,14 +170,14 @@ def get_numvfs(ifname):
:raises: SRIOVNumvfsException
"""
sriov_numvfs_path = common.get_dev_path(ifname, "sriov_numvfs")
logger.debug(f"Getting numvfs for interface {ifname}")
logger.debug(f"{ifname}: Getting numvfs for interface")
try:
with open(sriov_numvfs_path, 'r') as f:
curr_numvfs = int(f.read())
except IOError as exc:
msg = f"Unable to read numvfs for {ifname}: {exc}"
msg = f"{ifname}: Unable to read numvfs: {exc}"
raise SRIOVNumvfsException(msg)
logger.debug(f"Interface {ifname} has {curr_numvfs} configured")
logger.debug(f"{ifname}: Interface has {curr_numvfs} configured")
return curr_numvfs
@ -179,17 +199,17 @@ def set_numvfs(ifname, numvfs):
:raises: SRIOVNumvfsException
"""
curr_numvfs = get_numvfs(ifname)
logger.debug(f"Interface {ifname} has {curr_numvfs} configured, setting "
logger.debug(f"{ifname}: Interface has {curr_numvfs} configured, setting "
f"to {numvfs}")
if not isinstance(numvfs, int):
msg = (f"Unable to configure pf: {ifname} with numvfs: {numvfs}\n"
msg = (f"{ifname}: Unable to configure pf with numvfs: {numvfs}\n"
f"numvfs must be an integer")
raise SRIOVNumvfsException(msg)
if numvfs != curr_numvfs:
if curr_numvfs != 0:
logger.warning(f"Numvfs already configured to {curr_numvfs} for "
f"{ifname}")
logger.warning(f"{ifname}: Numvfs already configured to "
f"{curr_numvfs}")
return curr_numvfs
sriov_numvfs_path = common.get_dev_path(ifname, "sriov_numvfs")
@ -198,14 +218,14 @@ def set_numvfs(ifname, numvfs):
with open(sriov_numvfs_path, "w") as f:
f.write("%d" % numvfs)
except IOError as exc:
msg = (f"Unable to configure pf: {ifname} with numvfs: {numvfs}\n"
msg = (f"{ifname} Unable to configure pf with numvfs: {numvfs}\n"
f"{exc}")
raise SRIOVNumvfsException(msg)
_wait_for_vf_creation(ifname, numvfs)
curr_numvfs = get_numvfs(ifname)
if curr_numvfs != numvfs:
msg = (f"Unable to configure pf: {ifname} with numvfs: {numvfs}\n"
msg = (f"{ifname}: Unable to configure pf with numvfs: {numvfs}\n"
"sriov_numvfs file is not set to the targeted number of "
"vfs")
raise SRIOVNumvfsException(msg)
@ -213,7 +233,7 @@ def set_numvfs(ifname, numvfs):
def restart_ovs_and_pfs_netdevs():
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
processutils.execute('/usr/bin/systemctl', 'restart', 'openvswitch')
for item in sriov_map:
if item['device_type'] == 'pf':
@ -265,14 +285,14 @@ def is_partitioned_pf(dev_name: str) -> bool:
Given a PF device, returns True if any VFs of this
device are in-use.
"""
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for config in sriov_map:
devtype = config.get('device_type', None)
if devtype == 'vf':
name = config.get('device', {}).get('name')
vf_name = config.get('name')
if dev_name == name:
logger.warning("%s has VF(%s) used by host" % (name, vf_name))
logger.warning(f"{name} has VF({vf_name}) used by host")
return True
return False
@ -281,12 +301,15 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
observer = udev_monitor_setup()
udev_monitor_start(observer)
sriov_map = _get_sriov_map()
mlnx_vfs_pcis_list = []
sriov_map = common.get_sriov_map()
dpdk_vfs_pcis_list = []
trigger_udev_rule = False
# Cleanup the previous config by puppet-tripleo
cleanup_puppet_config()
if any(item.get('vdpa') for item in sriov_map):
common.load_kmods(MLNX5_VDPA_KMODS)
vdpa_devices = get_vdpa_vhost_devices()
for item in sriov_map:
if item['device_type'] == 'pf':
@ -300,23 +323,30 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
# When configuring vdpa, we need to configure switchdev before
# we create the VFs
is_mlnx = common.is_mellanox_interface(item['name'])
vdpa = item.get('vdpa')
# Configure switchdev mode when vdpa
if item.get('vdpa') and is_mlnx:
# It has to happen before we set_numvfs
if vdpa and is_mlnx:
configure_switchdev(item['name'])
set_numvfs(item['name'], item['numvfs'])
# Configure switchdev mode when not vdpa
if (item.get('link_mode') == "switchdev" and is_mlnx and
not item.get('vdpa')):
# Configure switchdev, unbind driver and configure vdpa
if item.get('link_mode') == "switchdev" and is_mlnx:
logger.info(f"{item['name']}: Mellanox card")
vf_pcis_list = get_vf_pcis_list(item['name'])
mlnx_vfs_pcis_list += vf_pcis_list
for vf_pci in vf_pcis_list:
vf_pci_path = f"/sys/bus/pci/devices/{vf_pci}/driver"
if os.path.exists(vf_pci_path):
logger.info(f"Unbinding {vf_pci}")
with open(MLNX_UNBIND_FILE_PATH, 'w') as f:
f.write(vf_pci)
if not vdpa:
# For DPDK, we need to unbind the driver
_driver_unbind(vf_pci)
else:
if vf_pci not in vdpa_devices:
configure_vdpa_vhost_device(vf_pci)
else:
logger.info(
f"{item['name']}: vDPA device already created "
f"for {vf_pci}"
)
if vdpa:
common.restorecon('/dev/vhost-*')
logger.info(f"{item['name']}: Adding udev rules")
# Adding a udev rule to make vf-representors unmanaged by
# NetworkManager
@ -326,17 +356,24 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
trigger_udev_rule = add_udev_rule_for_sriov_pf(item['name'])\
or trigger_udev_rule
# Configure flow steering mode, default to smfs
configure_flow_steering(item['name'],
item.get('steering_mode', 'smfs'))
# Configure switchdev mode
configure_switchdev(item['name'])
# Adding a udev rule to rename vf-representors
trigger_udev_rule = add_udev_rule_for_vf_representors(
item['name']) or trigger_udev_rule
if not vdpa:
# This is used for the sriov_bind_config
dpdk_vfs_pcis_list += vf_pcis_list
# Configure flow steering mode, default to smfs
configure_flow_steering(item['name'],
item.get('steering_mode', 'smfs'))
# Configure switchdev mode
configure_switchdev(item['name'])
else:
trigger_udev_rule = add_udev_rule_for_vdpa_representors(
item['name']) or trigger_udev_rule
# Moving the sriov-PFs to switchdev mode will put the netdev
# interfaces in down state.
# In case we are running during initial deployment,
@ -347,8 +384,8 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
if execution_from_cli:
if_up_interface(item['name'])
if mlnx_vfs_pcis_list:
sriov_bind_pcis_map = {_MLNX_DRIVER: mlnx_vfs_pcis_list}
if dpdk_vfs_pcis_list and not vdpa:
sriov_bind_pcis_map = {_MLNX_DRIVER: dpdk_vfs_pcis_list}
if not execution_from_cli:
sriov_bind_config.update_sriov_bind_pcis_map(sriov_bind_pcis_map)
else:
@ -368,13 +405,12 @@ def _wait_for_uplink_rep_creation(pf_name):
uplink_rep_phys_switch_id_path = f"/sys/class/net/{pf_name}/phys_switch_id"
for i in range(MAX_RETRIES):
if get_file_data(uplink_rep_phys_switch_id_path):
logger.info(f"Uplink representor {pf_name} ready")
if common.get_file_data(uplink_rep_phys_switch_id_path):
logger.info(f"{pf_name} Uplink representor ready")
break
time.sleep(1)
else:
raise RuntimeError(f"Timeout while waiting for uplink representor "
f"{pf_name}.")
raise RuntimeError(f"{pf_name}: Timeout waiting uplink representor")
def create_rep_link_name_script():
@ -385,7 +421,7 @@ def create_rep_link_name_script():
def add_udev_rule_for_sriov_pf(pf_name):
logger.info(f"adding udev rules for sriov {pf_name}")
logger.info(f"{pf_name}: adding udev rules for sriov")
pf_pci = get_pf_pci(pf_name)
udev_data_line = 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '\
f'KERNELS=="{pf_pci}", NAME="{pf_name}"'
@ -393,7 +429,7 @@ def add_udev_rule_for_sriov_pf(pf_name):
def add_udev_rule_for_legacy_sriov_pf(pf_name, numvfs):
logger.info(f"adding udev rules for legacy sriov {pf_name}: {numvfs}")
logger.info(f"{pf_name}: adding udev rules for legacy sriov: {numvfs}")
udev_line = f'KERNEL=="{pf_name}", '\
f'RUN+="/bin/os-net-config-sriov -n %k:{numvfs}"'
pattern = f'KERNEL=="{pf_name}", RUN+="/bin/os-net-config-sriov -n'
@ -401,20 +437,19 @@ def add_udev_rule_for_legacy_sriov_pf(pf_name, numvfs):
def add_udev_rule_for_vf_representors(pf_name):
logger.info(f"adding udev rules for vf representators {pf_name}")
phys_switch_id_path = os.path.join(common.SYS_CLASS_NET, pf_name,
"phys_switch_id")
phys_switch_id = get_file_data(phys_switch_id_path).strip()
logger.info(f"{pf_name}: adding udev rules for vf representators")
phys_switch_id_path = common.get_dev_path(pf_name,
"_phys_switch_id")
phys_switch_id = common.get_file_data(phys_switch_id_path).strip()
pf_pci = get_pf_pci(pf_name)
pf_fun_num_match = PF_FUNC_RE.search(pf_pci)
if pf_fun_num_match:
pf_fun_num = pf_fun_num_match.group(1)
else:
logger.error(f"Failed to get function number for {pf_name} \n"
if not pf_fun_num_match:
logger.error(f"{pf_name}: Failed to get function number "
"and so failed to create a udev rule for renaming "
"its' vf-represent")
"its vf-represent")
return
pf_fun_num = pf_fun_num_match.group(1)
udev_data_line = 'SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}'\
'=="%s", ATTR{phys_port_name}=="pf%svf*", '\
'IMPORT{program}="%s $attr{phys_port_name}", '\
@ -426,8 +461,29 @@ def add_udev_rule_for_vf_representors(pf_name):
return add_udev_rule(udev_data_line, _UDEV_RULE_FILE)
def add_udev_rule_for_vdpa_representors(pf_name):
logger.info(f"{pf_name}: adding udev rules for vdpa representators")
udev_lines = ""
for vf, att in vf_to_pf.items():
mac = common.interface_mac(vf)
vadd = VF_PCI_RE.search(att.get('device'))
if not vadd:
logger.error(
f"{att.get('device')}/{vf}: Failed to get pf/vf numbers "
"and so failed to create a udev rule for renaming vdpa dev"
)
continue
vdpa_rep = f"vdpa{vadd.group(1)}p{vadd.group(2)}vf{vadd.group(3)}"
logger.info(f"{vdpa_rep}: Adding udev representor rule.")
udev_lines += (
'SUBSYSTEM=="net", ACTION=="add", '
f'ATTR{{address}}=="{mac}", NAME="{vdpa_rep}"\n'
)
return add_udev_rule(udev_lines, _UDEV_RULE_FILE)
def add_udev_rule_to_unmanage_vf_representors_by_nm():
logger.info(f"adding udev rules to unmanage vf representators")
logger.info("adding udev rules to unmanage vf representators")
udev_data_line = 'SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}'\
'!="", ATTR{phys_port_name}=="pf*vf*", '\
'ENV{NM_UNMANAGED}="1"'
@ -446,7 +502,7 @@ def add_udev_rule(udev_data, udev_file, pattern=None):
f"{udev_data}\n"
f.write(data)
else:
file_data = get_file_data(udev_file)
file_data = common.get_file_data(udev_file)
udev_lines = file_data.splitlines()
if pattern in file_data:
if udev_data in udev_lines:
@ -493,16 +549,17 @@ def configure_switchdev(pf_name):
processutils.execute('/usr/sbin/devlink', 'dev', 'eswitch', 'set',
f'pci/{pf_pci}', 'inline-mode', 'transport')
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to set inline-mode to transport for "
f"{pf_pci}: {exc}")
logger.error(f"{pf_name}: Failed to set inline-mode to transport "
f"for {pf_pci}: {exc}")
raise
try:
processutils.execute('/usr/sbin/devlink', 'dev', 'eswitch', 'set',
f'pci/{pf_pci}', 'mode', 'switchdev')
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to set mode to switchdev for {pf_pci}: {exc}")
logger.error(f"{pf_name}: Failed to set mode to switchdev for "
f"{pf_pci}: {exc}")
raise
logger.info(f"Device pci/{pf_pci} set to switchdev mode.")
logger.info(f"{pf_name}: Device pci/{pf_pci} set to switchdev mode.")
# WA to make sure that the uplink_rep is ready after moving to switchdev,
# as moving to switchdev will remove the sriov_pf and create uplink
@ -513,9 +570,29 @@ def configure_switchdev(pf_name):
try:
processutils.execute('/usr/sbin/ethtool', '-K', pf_name,
'hw-tc-offload', 'on')
logger.info(f"Enabled \"hw-tc-offload\" for PF {pf_name}.")
logger.info(f"{pf_name}: Enabled \"hw-tc-offload\" for PF.")
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to enable hw-tc-offload on {pf_name}: {exc}")
logger.error(f"{pf_name}: Failed to enable hw-tc-offload: {exc}")
raise
def get_vdpa_vhost_devices():
logger.info(f"Getting list of vdpa devices")
try:
stdout, stderr = processutils.execute('vdpa', '-j', 'dev')
except processutils.ProcessExecutionError as exc:
logger.error(f"Failed to get vdpa vhost devices: {exc}")
raise
return loads(stdout)['dev']
def configure_vdpa_vhost_device(pci):
logger.info(f"{pci}: Creating vdpa device")
try:
processutils.execute('vdpa', 'dev', 'add', 'name', pci,
'mgmtdev', f'pci/{pci}')
except processutils.ProcessExecutionError as exc:
logger.error(f"{pci}: Failed to create vdpa vhost device: {exc}")
raise
@ -545,7 +622,7 @@ def _pf_interface_up(pf_device):
if 'promisc' in pf_device:
run_ip_config_cmd('ip', 'link', 'set', 'dev', pf_device['name'],
'promisc', pf_device['promisc'])
logger.info(f"Bringing up PF: {pf_device['name']}")
logger.info(f"{pf_device['name']}: Bringing up PF")
run_ip_config_cmd('ip', 'link', 'set', 'dev', pf_device['name'], 'up')
@ -559,57 +636,56 @@ def run_ip_config_cmd_safe(raise_error, *cmd, **kwargs):
def get_pf_pci(pf_name):
pf_pci_path = common.get_dev_path(pf_name, "uevent")
pf_info = get_file_data(pf_pci_path)
pf_info = common.get_file_data(pf_pci_path)
pf_pci = re.search(r'PCI_SLOT_NAME=(.*)', pf_info, re.MULTILINE).group(1)
return pf_pci
def get_pf_device_id(pf_name):
pf_device_path = common.get_dev_path(pf_name, "device")
pf_device_id = get_file_data(pf_device_path).strip()
pf_device_id = common.get_file_data(pf_device_path).strip()
return pf_device_id
def get_vf_pcis_list(pf_name):
vf_pcis_list = []
listOfPfFiles = os.listdir(os.path.join(common.SYS_CLASS_NET, pf_name,
"device"))
for pf_file in listOfPfFiles:
pf_files = os.listdir(common.get_dev_path(pf_name, "_device"))
for pf_file in pf_files:
if pf_file.startswith("virtfn"):
vf_info = get_file_data(common.get_dev_path(pf_name,
f"{pf_file}/uevent"))
vf_info = common.get_file_data(common.get_dev_path(pf_name,
f"{pf_file}/uevent"))
vf_pcis_list.append(re.search(r'PCI_SLOT_NAME=(.*)',
vf_info, re.MULTILINE).group(1))
return vf_pcis_list
def if_down_interface(device):
logger.info(f"Running /sbin/ifdown {device}")
logger.info(f"{device}: Running /sbin/ifdown")
try:
processutils.execute('/sbin/ifdown', device)
except processutils.ProcessExecutionError:
logger.error(f"Failed to ifdown {device}")
logger.error(f"{device}: Failed to ifdown")
raise
def if_up_interface(device):
logger.info(f"Running /sbin/ifup {device}")
logger.info(f"{device}: Running /sbin/ifup")
try:
processutils.execute('/sbin/ifup', device)
except processutils.ProcessExecutionError:
logger.error(f"Failed to ifup {device}")
logger.error(f"{device}: Failed to ifup")
raise
def configure_sriov_vf():
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for item in sriov_map:
raise_error = True
if item['device_type'] == 'vf':
pf_name = item['device']['name']
vfid = item['device']['vfid']
base_cmd = ('ip', 'link', 'set', 'dev', pf_name, 'vf', str(vfid))
logger.info(f"Configuring settings for PF: {pf_name} VF: {vfid} "
logger.info(f"{pf_name}: Configuring settings for VF: {vfid} "
f"VF name: {item['name']}")
raise_error = True
if 'macaddr' in item:

View File

@ -24,9 +24,7 @@ import yaml
import os_net_config
from os_net_config import cli
from os_net_config import common
from os_net_config import sriov_config
from os_net_config.tests import base
from os_net_config import utils
REALPATH = os.path.dirname(os.path.realpath(__file__))
@ -39,7 +37,7 @@ class TestCli(base.TestCase):
def setUp(self):
super(TestCli, self).setUp()
rand = str(int(random.random() * 100000))
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common._LOG_FILE = '/tmp/' + rand + 'os_net_config.log'
sys.stdout = StringIO()
sys.stderr = StringIO()
@ -53,8 +51,8 @@ class TestCli(base.TestCase):
super(TestCli, self).tearDown()
if os.path.isfile(common._LOG_FILE):
os.remove(common._LOG_FILE)
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
def run_cli(self, argstr, exitcodes=(0,)):
for s in [sys.stdout, sys.stderr]:
@ -225,7 +223,7 @@ class TestCli(base.TestCase):
test_get_vf_devname)
self.stub_out('os_net_config.utils.get_pci_address',
test_get_pci_address)
self.stub_out('os_net_config.utils.interface_mac',
self.stub_out('os_net_config.common.interface_mac',
test_interface_mac)
ivs_yaml = os.path.join(SAMPLE_BASE, 'sriov_pf.yaml')
ivs_json = os.path.join(SAMPLE_BASE, 'sriov_pf.json')
@ -233,14 +231,14 @@ class TestCli(base.TestCase):
'--exit-on-validation-errors '
'-c %s' % ivs_yaml)
self.assertEqual('', stderr)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_config_yaml = yaml.safe_load(contents)
os.remove(sriov_config._SRIOV_CONFIG_FILE)
os.remove(common.SRIOV_CONFIG_FILE)
stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop '
'--exit-on-validation-errors '
'-c %s' % ivs_json)
self.assertEqual('', stderr)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_config_json = yaml.safe_load(contents)
sanity_devices = ['DEVICE=p2p1',
'DEVICE=p2p1_5',
@ -270,14 +268,14 @@ class TestCli(base.TestCase):
'--exit-on-validation-errors '
'-c %s' % ivs_yaml)
self.assertEqual('', stderr)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_config_yaml = yaml.safe_load(contents)
os.remove(sriov_config._SRIOV_CONFIG_FILE)
os.remove(common.SRIOV_CONFIG_FILE)
stdout_json, stderr = self.run_cli('ARG0 --provider=ifcfg --noop '
'--exit-on-validation-errors '
'-c %s' % ivs_json)
self.assertEqual('', stderr)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_config_json = yaml.safe_load(contents)
sanity_devices = ['DEVICE=p2p1',
'DEVICE=p2p1_5',

View File

@ -19,10 +19,10 @@ import tempfile
from oslo_concurrency import processutils
import os_net_config
from os_net_config import common
from os_net_config import impl_eni
from os_net_config import objects
from os_net_config.tests import base
from os_net_config import utils
_AUTO = "auto eth0\n"
@ -239,7 +239,7 @@ class TestENINetConfig(base.TestCase):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface(self.if_name, primary=True)
bridge = objects.OvsBridge('br0', use_dhcp=True,
@ -254,7 +254,7 @@ class TestENINetConfig(base.TestCase):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface(self.if_name, primary=True)
ovs_extra = "br-set-external-id br0 bridge-id br0"
@ -271,7 +271,7 @@ class TestENINetConfig(base.TestCase):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface(self.if_name, primary=True)
ovs_extra = "br-set-external-id {name} bridge-id {name}"
@ -344,7 +344,7 @@ class TestENINetConfigApply(base.TestCase):
self.provider.add_interface(interface)
self.provider.apply()
iface_data = utils.get_file_data(self.temp_config_file.name)
iface_data = common.get_file_data(self.temp_config_file.name)
self.assertEqual((_V4_IFACE_STATIC_IP + _RTS), iface_data)
self.assertIn('eth0', self.ifup_interface_names)
@ -358,7 +358,7 @@ class TestENINetConfigApply(base.TestCase):
self.provider.add_interface(interface)
self.provider.apply(activate=False)
iface_data = utils.get_file_data(self.temp_config_file.name)
iface_data = common.get_file_data(self.temp_config_file.name)
self.assertEqual((_V4_IFACE_STATIC_IP + _RTS), iface_data)
self.assertEqual([], self.ifup_interface_names)
@ -369,7 +369,7 @@ class TestENINetConfigApply(base.TestCase):
self.provider.add_interface(interface)
self.provider.add_bridge(bridge)
self.provider.apply()
iface_data = utils.get_file_data(self.temp_config_file.name)
iface_data = common.get_file_data(self.temp_config_file.name)
self.assertEqual((_OVS_BRIDGE_DHCP + _OVS_PORT_IFACE), iface_data)
self.assertIn('eth0', self.ifup_interface_names)
self.assertIn('br0', self.ifup_interface_names)

View File

@ -22,9 +22,9 @@ import tempfile
from oslo_concurrency import processutils
import os_net_config
from os_net_config import common
from os_net_config import impl_ifcfg
from os_net_config import objects
from os_net_config import sriov_config
from os_net_config.tests import base
from os_net_config import utils
@ -657,7 +657,7 @@ class TestIfcfgNetConfig(base.TestCase):
def setUp(self):
super(TestIfcfgNetConfig, self).setUp()
rand = str(int(random.random() * 100000))
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
self.provider = impl_ifcfg.IfcfgNetConfig()
@ -668,8 +668,8 @@ class TestIfcfgNetConfig(base.TestCase):
def tearDown(self):
super(TestIfcfgNetConfig, self).tearDown()
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
def get_interface_config(self, name='em1'):
return self.provider.interface_data[name]
@ -807,7 +807,7 @@ class TestIfcfgNetConfig(base.TestCase):
def test_interface_mac(name):
macs = {'em1': 'a1:b2:c3:d4:e5'}
return macs[name]
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
nic_mapping = {'nic1': 'em1'}
self.stubbed_mapped_nics = nic_mapping
@ -961,7 +961,7 @@ class TestIfcfgNetConfig(base.TestCase):
def test_network_ovs_bridge_with_dhcp_primary_interface(self):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface('em1', primary=True)
bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True,
@ -975,7 +975,7 @@ class TestIfcfgNetConfig(base.TestCase):
def test_network_ovs_bridge_with_dhcp_primary_interface_with_extra(self):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface('em1', primary=True)
ovs_extra = "br-set-external-id br-ctlplane bridge-id br-ctlplane"
@ -991,7 +991,7 @@ class TestIfcfgNetConfig(base.TestCase):
def test_network_ovs_bridge_with_dhcp_primary_interface_with_format(self):
def test_interface_mac(name):
return "a1:b2:c3:d4:e5"
self.stub_out('os_net_config.utils.interface_mac', test_interface_mac)
self.stub_out('os_net_config.common.interface_mac', test_interface_mac)
interface = objects.Interface('em1', primary=True)
ovs_extra = "br-set-external-id {name} bridge-id {name}"
@ -2222,7 +2222,7 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.apply()
route_table_data = utils.get_file_data(
route_table_data = common.get_file_data(
self.temp_route_table_file.name)
self.assertEqual(_RT_FULL, route_table_data)
@ -2253,9 +2253,9 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.apply()
ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
ifcfg_data = common.get_file_data(self.temp_ifcfg_file.name)
self.assertEqual(_V4_IFCFG, ifcfg_data)
route_data = utils.get_file_data(self.temp_route_file.name)
route_data = common.get_file_data(self.temp_route_file.name)
self.assertEqual(_ROUTES, route_data)
def test_sriov_pf_network_apply(self):
@ -2275,9 +2275,9 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.apply()
ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
ifcfg_data = common.get_file_data(self.temp_ifcfg_file.name)
self.assertEqual(_V4_SRIOV_PF_IFCFG, ifcfg_data)
route_data = utils.get_file_data(self.temp_route_file.name)
route_data = common.get_file_data(self.temp_route_file.name)
self.assertEqual(_ROUTES_PF, route_data)
def test_dhcp_ovs_bridge_network_apply(self):
@ -2288,11 +2288,11 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.add_bridge(bridge)
self.provider.apply()
ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
ifcfg_data = common.get_file_data(self.temp_ifcfg_file.name)
self.assertEqual(_OVS_INTERFACE, ifcfg_data)
bridge_data = utils.get_file_data(self.temp_bridge_file.name)
bridge_data = common.get_file_data(self.temp_bridge_file.name)
self.assertEqual(_OVS_BRIDGE_DHCP, bridge_data)
route_data = utils.get_file_data(self.temp_route_file.name)
route_data = common.get_file_data(self.temp_route_file.name)
self.assertEqual("", route_data)
def test_dhclient_stop_on_iface_activate(self):
@ -2623,7 +2623,7 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.add_vlan(vlan)
self.provider.apply()
ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
ifcfg_data = common.get_file_data(self.temp_ifcfg_file.name)
self.assertEqual(_VLAN_NO_IP, ifcfg_data)
def test_cleanup(self):

View File

@ -19,10 +19,9 @@ import os
import random
import yaml
from os_net_config import common
from os_net_config import objects
from os_net_config import sriov_config
from os_net_config.tests import base
from os_net_config import utils
class TestRoute(base.TestCase):
@ -413,7 +412,7 @@ class TestBridge(base.TestCase):
def setUp(self):
super(TestBridge, self).setUp()
rand = str(int(random.random() * 100000))
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
def stub_is_ovs_installed():
return True
@ -422,8 +421,8 @@ class TestBridge(base.TestCase):
def tearDown(self):
super(TestBridge, self).tearDown()
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
def test_from_json_dhcp(self):
data = """{
@ -484,7 +483,7 @@ class TestBridge(base.TestCase):
self.assertTrue(interface1.ovs_port)
self.assertEqual("br-foo", interface1.bridge_name)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -549,7 +548,7 @@ class TestBridge(base.TestCase):
self.assertEqual("em2", interface2.device)
self.assertEqual("br-foo", bond.bridge_name)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -612,7 +611,7 @@ class TestBridge(base.TestCase):
objects.object_from_json(json.loads(data))
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -659,7 +658,7 @@ class TestBridge(base.TestCase):
self.assertTrue(interface1.ovs_port)
self.assertEqual("br-foo", interface1.bridge_name)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -710,7 +709,7 @@ class TestBridge(base.TestCase):
self.assertFalse(dpdk_interface.ovs_port)
self.assertEqual("br-foo", dpdk_interface.bridge_name)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -766,7 +765,7 @@ class TestBridge(base.TestCase):
self.assertFalse(dpdk_interface.ovs_port)
self.assertEqual("br-foo", dpdk_interface.bridge_name)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -1159,7 +1158,7 @@ class TestLinuxBond(base.TestCase):
def setUp(self):
super(TestLinuxBond, self).setUp()
rand = str(int(random.random() * 100000))
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
def stub_is_ovs_installed():
return True
@ -1168,8 +1167,8 @@ class TestLinuxBond(base.TestCase):
def tearDown(self):
super(TestLinuxBond, self).tearDown()
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
def test_from_json_dhcp(self):
data = """{
@ -1288,7 +1287,7 @@ class TestLinuxBond(base.TestCase):
self.assertEqual("em1", interface1.device)
self.assertEqual("em2", interface2.device)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -1350,7 +1349,7 @@ class TestLinuxBond(base.TestCase):
test_get_pci_address)
objects.object_from_json(json.loads(data))
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertListEqual(vf_final, vf_map)
@ -1752,7 +1751,8 @@ class TestNicMapping(base.TestCase):
mac_map = {'em1': '12:34:56:78:9a:bc',
'em2': '12:34:56:de:f0:12'}
return mac_map[name]
self.stub_out('os_net_config.utils.interface_mac', dummy_interface_mac)
self.stub_out('os_net_config.common.interface_mac',
dummy_interface_mac)
self._stub_active_nics(['em1', 'em2'])
self._stub_available_nics(['em1', 'em2'])
mapping = {'nic1': '12:34:56:de:f0:12', 'nic2': '12:34:56:78:9a:bc'}
@ -1765,7 +1765,8 @@ class TestNicMapping(base.TestCase):
'em2': '12:34:56:de:f0:12'}
return mac_map[name]
self.stub_out('os_net_config.utils.interface_mac', dummy_interface_mac)
self.stub_out('os_net_config.common.interface_mac',
dummy_interface_mac)
self._stub_active_nics(['em1', 'em2'])
self._stub_available_nics(['em1', 'em2'])
mapping = {'nic1': '12:34:56:de:f0:12', 'nic2': 'aa:bb:cc:dd:ee:ff'}

View File

@ -47,15 +47,15 @@ class TestSriovConfig(base.TestCase):
'rules.d_70-tripleo-reset-sriov.rules'
sriov_config._ALLOCATE_VFS_FILE = '/tmp/' + rand + 'etc_sysconfig_'\
'allocate_vfs'
sriov_config._SRIOV_CONFIG_FILE = '/tmp/' + rand + 'sriov_config'\
'.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/' + rand + 'sriov_config.yaml'
sriov_config._REP_LINK_NAME_FILE = '/tmp/' + rand + 'rep_link.sh'
def tearDown(self):
super(TestSriovConfig, self).tearDown()
if os.path.isfile(common._LOG_FILE):
os.remove(common._LOG_FILE)
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
if os.path.isfile(sriov_config._IFUP_LOCAL_FILE):
os.remove(sriov_config._IFUP_LOCAL_FILE)
shutil.rmtree(common.SYS_CLASS_NET)
@ -247,7 +247,7 @@ class TestSriovConfig(base.TestCase):
cleanup_puppet_config_stub)
def _wait_for_vf_creation_stub(pf_name, numvfs):
self._save_action('_wait_for_vf_creation_stub')
self._save_action('_wait_for_vf_creation')
return
self.stub_out('os_net_config.sriov_config._wait_for_vf_creation',
_wait_for_vf_creation_stub)
@ -278,6 +278,44 @@ class TestSriovConfig(base.TestCase):
self.stub_out('os_net_config.sriov_config.set_numvfs',
set_numvfs_stub)
def get_pf_pci_stub(name):
pci_address = {"p2p1": "0000:01:01.0",
"p2p2": "0000:01:02.0",
"p2p3": "0000:01:03.0"}
return pci_address[name]
self.stub_out('os_net_config.sriov_config.get_pf_pci',
get_pf_pci_stub)
def get_vdpa_vhost_devices_stub():
self._save_action('get_vdpa_vhost_devices')
return
self.stub_out('os_net_config.sriov_config.get_vdpa_vhost_devices',
get_vdpa_vhost_devices_stub)
def load_kmods_stub(mods):
return
self.stub_out('os_net_config.sriov_config.load_kmods',
load_kmods_stub)
def modprobe_stub(*args):
out = """vdpa x
vhost_vdpa x
"""
return out, "hello"
self.stub_out('oslo_concurrency.processutils.execute',
modprobe_stub)
def reload_udev_rules_stub():
self._save_action('reload_udev_rules')
return
self.stub_out('os_net_config.sriov_config.reload_udev_rules',
reload_udev_rules_stub)
def test_list_kmods(self):
self.setUp_pf_stubs()
self.assertEqual([], common.list_kmods(["vhost_vdpa", "vdpa"]))
self.assertEqual(["test"], common.list_kmods(["test", "vdpa"]))
def test_configure_sriov_pf(self):
"""Test the numvfs setting for SR-IOV PF
@ -295,12 +333,12 @@ class TestSriovConfig(base.TestCase):
'reload_udev_rules',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'reload_udev_rules',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'udev_monitor_stop',
]
@ -314,7 +352,7 @@ class TestSriovConfig(base.TestCase):
self._write_numvfs(ifname)
self._action_order = []
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_config)
sriov_config.configure_sriov_pf()
self.assertEqual(exp_actions, self._action_order)
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
@ -337,12 +375,12 @@ class TestSriovConfig(base.TestCase):
'udev_monitor_start',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'reload_udev_rules',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'udev_monitor_stop',
]
@ -360,7 +398,7 @@ class TestSriovConfig(base.TestCase):
self._write_numvfs(ifname)
self._action_order = []
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_config)
sriov_config.configure_sriov_pf()
self.assertEqual(exp_actions, self._action_order)
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
@ -384,12 +422,12 @@ class TestSriovConfig(base.TestCase):
'reload_udev_rules',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'reload_udev_rules',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'udev_monitor_stop',
]
@ -407,7 +445,7 @@ class TestSriovConfig(base.TestCase):
self._write_numvfs(ifname)
self._action_order = []
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_config)
sriov_config.configure_sriov_pf()
self.assertEqual(exp_actions, self._action_order)
f = open(sriov_config._UDEV_LEGACY_RULE_FILE, 'r')
@ -425,18 +463,28 @@ class TestSriovConfig(base.TestCase):
exp_actions = [
'udev_monitor_setup',
'udev_monitor_start',
'get_vdpa_vhost_devices',
'configure_switchdev',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'reload_udev_rules',
'reload_udev_rules',
'reload_udev_rules',
'reload_udev_rules',
'configure_switchdev',
'set_numvfs',
'get_numvfs',
'_wait_for_vf_creation_stub',
'_wait_for_vf_creation',
'get_numvfs',
'reload_udev_rules',
'reload_udev_rules',
'reload_udev_rules',
'trigger_udev_rules',
'udev_monitor_stop',
]
pf_config = [{"device_type": "pf", "name": "p2p1", "numvfs": 10,
"vdpa": True, "link_mode": "switchdev"},
{"device_type": "pf", "name": "p2p2", "numvfs": 12,
@ -446,7 +494,7 @@ class TestSriovConfig(base.TestCase):
self._write_numvfs(ifname)
self._action_order = []
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_config)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_config)
sriov_config.configure_sriov_pf()
self.assertEqual(exp_actions, self._action_order)
self.assertEqual(10, sriov_config.get_numvfs('p2p1'))
@ -565,7 +613,7 @@ class TestSriovConfig(base.TestCase):
self.stub_out('os_net_config.sriov_config.run_ip_config_cmd',
run_ip_config_cmd_stub)
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, vf_config)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, vf_config)
sriov_config.configure_sriov_vf()
for cmd in exp_cmds:

View File

@ -88,16 +88,19 @@ class TestUtils(base.TestCase):
def setUp(self):
super(TestUtils, self).setUp()
rand = str(int(random.random() * 100000))
utils._DPDK_MAPPING_FILE = '/tmp/dpdk_mapping_' + rand + '.yaml'
sriov_config._SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common.DPDK_MAPPING_FILE = '/tmp/dpdk_mapping_' + rand + '.yaml'
common.SRIOV_CONFIG_FILE = '/tmp/sriov_config_' + rand + '.yaml'
common._LOG_FILE = '/tmp/' + rand + 'os_net_config.log'
sriov_config._UDEV_LEGACY_RULE_FILE = UDEV_FILE + rand
def tearDown(self):
super(TestUtils, self).tearDown()
if os.path.isfile(utils._DPDK_MAPPING_FILE):
os.remove(utils._DPDK_MAPPING_FILE)
if os.path.isfile(sriov_config._SRIOV_CONFIG_FILE):
os.remove(sriov_config._SRIOV_CONFIG_FILE)
if os.path.isfile(common.DPDK_MAPPING_FILE):
os.remove(common.DPDK_MAPPING_FILE)
if os.path.isfile(common._LOG_FILE):
os.remove(common._LOG_FILE)
if os.path.isfile(common.SRIOV_CONFIG_FILE):
os.remove(common.SRIOV_CONFIG_FILE)
if os.path.isfile(sriov_config._UDEV_LEGACY_RULE_FILE):
os.remove(sriov_config._UDEV_LEGACY_RULE_FILE)
@ -134,7 +137,7 @@ class TestUtils(base.TestCase):
self.stub_out('os_net_config.sriov_config.get_numvfs',
get_numvfs_stub)
utils.update_sriov_pf_map('eth1', 10, False)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_pf_map))
test_sriov_pf_map = [{'device_type': 'pf', 'link_mode': 'legacy',
@ -147,7 +150,7 @@ class TestUtils(base.TestCase):
self.stub_out('os_net_config.sriov_config.get_numvfs',
get_numvfs_stub)
utils.update_sriov_pf_map('eth1', 10, False)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_pf_map))
test_sriov_pf_map = [{'device_type': 'pf', 'link_mode': 'legacy',
@ -168,7 +171,7 @@ class TestUtils(base.TestCase):
self.stub_out('os_net_config.sriov_config.get_numvfs',
get_numvfs_stub)
utils.update_sriov_pf_map('eth1', 10, False, promisc='off')
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_pf_map))
test_sriov_pf_map = [{'device_type': 'pf', 'link_mode': 'legacy',
@ -182,7 +185,7 @@ class TestUtils(base.TestCase):
self.stub_out('os_net_config.sriov_config.get_numvfs',
get_numvfs_stub)
utils.update_sriov_pf_map('eth1', 10, False, vdpa=True)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_pf_map))
test_sriov_pf_map = [{'device_type': 'pf', 'link_mode': 'legacy',
@ -196,7 +199,7 @@ class TestUtils(base.TestCase):
get_numvfs_stub)
pf_initial = [{'device_type': 'pf', 'link_mode': 'legacy',
'name': 'eth1', 'numvfs': 10}]
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_initial)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_initial)
self.assertRaises(sriov_config.SRIOVNumvfsException,
utils.update_sriov_pf_map, 'eth1', 20, False)
@ -208,13 +211,13 @@ class TestUtils(base.TestCase):
pf_initial = [{'device_type': 'pf', 'link_mode': 'legacy',
'name': 'eth1', 'numvfs': 10, 'promisc': 'on',
'vdpa': False}]
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_initial)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_initial)
utils.update_sriov_pf_map('eth1', 10, False, promisc='off')
pf_final = [{'device_type': 'pf', 'link_mode': 'legacy',
'name': 'eth1', 'numvfs': 10, 'promisc': 'off',
'vdpa': False}]
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(pf_map))
@ -228,13 +231,13 @@ class TestUtils(base.TestCase):
pf_initial = [{'device_type': 'pf', 'link_mode': 'legacy',
'name': 'eth1', 'numvfs': 10, 'promisc': 'on',
'vdpa': False}]
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, pf_initial)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, pf_initial)
utils.update_sriov_pf_map('eth1', 10, False, vdpa=True)
pf_final = [{'device_type': 'pf', 'link_mode': 'legacy',
'name': 'eth1', 'numvfs': 10, 'promisc': 'on',
'vdpa': True}]
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
pf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(pf_map))
@ -242,7 +245,7 @@ class TestUtils(base.TestCase):
def test_update_sriov_vf_map_minimal_new(self):
utils.update_sriov_vf_map('eth1', 2, 'eth1_2')
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_vf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_vf_map))
test_sriov_vf_map = [{'device_type': 'vf', 'name': 'eth1_2',
@ -258,7 +261,7 @@ class TestUtils(base.TestCase):
utils.update_sriov_pf_map('eth1', 10, False)
utils.update_sriov_pf_map('eth2', 10, False)
utils.update_sriov_vf_map('eth1', 2, 'eth1_2')
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_vf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(3, len(sriov_vf_map))
@ -286,7 +289,7 @@ class TestUtils(base.TestCase):
spoofcheck="on", trust="on", state="enable",
macaddr="AA:BB:CC:DD:EE:FF", promisc="off",
pci_address="0000:80:00.1", max_tx_rate=10)
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
sriov_vf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(sriov_vf_map))
test_sriov_vf_map = [{'device_type': 'vf', 'name': 'eth1_2',
@ -303,7 +306,7 @@ class TestUtils(base.TestCase):
def test_update_sriov_vf_map_exist(self):
vf_initial = [{'device_type': 'vf', 'name': 'eth1_2',
'device': {"name": "eth1", "vfid": 2}}]
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, vf_initial)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, vf_initial)
utils.update_sriov_vf_map('eth1', 2, 'eth1_2', vlan_id=10, qos=5,
spoofcheck="on", trust="on", state="enable",
@ -318,7 +321,7 @@ class TestUtils(base.TestCase):
'macaddr': 'AA:BB:CC:DD:EE:FF',
'promisc': 'off',
'pci_address': '0000:80:00.1'}]
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(vf_map))
@ -334,7 +337,7 @@ class TestUtils(base.TestCase):
'macaddr': 'AA:BB:CC:DD:EE:FF',
'promisc': 'off',
'pci_address': "0000:80:00.1"}]
utils.write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, vf_initial)
utils.write_yaml_config(common.SRIOV_CONFIG_FILE, vf_initial)
utils.update_sriov_vf_map('eth1', 2, 'eth1_2', vlan_id=100, qos=15,
spoofcheck="off", trust="off", state="auto",
@ -349,7 +352,7 @@ class TestUtils(base.TestCase):
'macaddr': 'BB:BB:CC:DD:EE:FF',
'promisc': 'on',
'pci_address': '0000:80:00.1'}]
contents = utils.get_file_data(sriov_config._SRIOV_CONFIG_FILE)
contents = common.get_file_data(common.SRIOV_CONFIG_FILE)
vf_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(vf_map))
@ -485,7 +488,7 @@ class TestUtils(base.TestCase):
def test_get_dpdk_mac_address(name):
return '01:02:03:04:05:06'
self.stub_out('oslo_concurrency.processutils.execute', test_execute)
self.stub_out('os_net_config.utils._get_dpdk_mac_address',
self.stub_out('os_net_config.common._get_dpdk_mac_address',
test_get_dpdk_mac_address)
try:
utils.bind_dpdk_interfaces('nic2', 'vfio-pci', False)
@ -503,7 +506,7 @@ class TestUtils(base.TestCase):
def test_get_dpdk_mac_address(name):
return '01:02:03:04:05:06'
self.stub_out('oslo_concurrency.processutils.execute', test_execute)
self.stub_out('os_net_config.utils._get_dpdk_mac_address',
self.stub_out('os_net_config.common._get_dpdk_mac_address',
test_get_dpdk_mac_address)
self.assertRaises(utils.OvsDpdkBindException,
@ -593,7 +596,7 @@ class TestUtils(base.TestCase):
def test__update_dpdk_map_new(self):
utils._update_dpdk_map('eth1', '0000:03:00.0', '01:02:03:04:05:06',
'vfio-pci')
contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
dpdk_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(dpdk_map))
@ -606,11 +609,11 @@ class TestUtils(base.TestCase):
dpdk_test = [{'name': 'eth1', 'pci_address': '0000:03:00.0',
'mac_address': '01:02:03:04:05:06',
'driver': 'vfio-pci'}]
utils.write_yaml_config(utils._DPDK_MAPPING_FILE, dpdk_test)
utils.write_yaml_config(common.DPDK_MAPPING_FILE, dpdk_test)
utils._update_dpdk_map('eth1', '0000:03:00.0', '01:02:03:04:05:06',
'vfio-pci')
contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
dpdk_map = yaml.safe_load(contents) if contents else []
self.assertEqual(1, len(dpdk_map))
@ -619,7 +622,7 @@ class TestUtils(base.TestCase):
def test_update_dpdk_map_value_change(self):
dpdk_test = [{'name': 'eth1', 'pci_address': '0000:03:00.0',
'driver': 'vfio-pci'}]
utils.write_yaml_config(utils._DPDK_MAPPING_FILE, dpdk_test)
utils.write_yaml_config(common.DPDK_MAPPING_FILE, dpdk_test)
dpdk_test = [{'name': 'eth1', 'pci_address': '0000:03:00.0',
'mac_address': '01:02:03:04:05:06',
@ -627,7 +630,7 @@ class TestUtils(base.TestCase):
utils._update_dpdk_map('eth1', '0000:03:00.0', '01:02:03:04:05:06',
'vfio-pci')
try:
contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
except IOError:
pass
@ -702,7 +705,7 @@ class TestUtils(base.TestCase):
shutil.rmtree(tmp_pci_dir)
def test_interface_mac_raises(self):
self.assertRaises(IOError, utils.interface_mac, 'ens20f2p3')
self.assertRaises(IOError, common.interface_mac, 'ens20f2p3')
def test_get_dpdk_devargs_mlnx(self):
def test_execute(name, dummy1, dummy2=None, dummy3=None):
@ -933,7 +936,7 @@ dpdk {
utils.update_vpp_mapping(interfaces, [])
contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
dpdk_test = [{'name': 'eth1', 'pci_address': '0000:00:09.0',
'mac_address': '01:02:03:04:05:06',

View File

@ -27,15 +27,6 @@ from oslo_concurrency import processutils
logger = logging.getLogger(__name__)
_SYS_BUS_PCI_DEV = '/sys/bus/pci/devices'
# File to contain the DPDK mapped nics, as nic name will not be available after
# binding driver, which is required for correct nic numbering.
# Format of the file (list mapped nic's details):
# -
# name: eth1
# pci_address: 0000:02:00.0
# mac_address: 01:02:03:04:05:06
# driver: vfio-pci
_DPDK_MAPPING_FILE = '/var/lib/os-net-config/dpdk_mapping.yaml'
# sriov_config service shall be created and enabled so that the various
# SR-IOV PF and VF configurations shall be done during reboot as well using
# sriov_config.py installed in path /usr/bin/os-net-config-sriov
@ -95,40 +86,6 @@ def ensure_directory_presence(filepath):
os.makedirs(dir_path)
def get_file_data(filename):
if not os.path.exists(filename):
return ''
try:
with open(filename, 'r') as f:
return f.read()
except IOError:
logger.error("Error reading file: %s" % filename)
return ''
def interface_mac(name):
try: # If the iface is part of a Linux bond, the real MAC is only here.
with open(common.get_dev_path(name, 'bonding_slave/perm_hwaddr'),
'r') as f:
return f.read().rstrip()
except IOError:
pass # Iface is not part of a bond, continue
try:
with open(common.get_dev_path(name, '_address'), 'r') as f:
return f.read().rstrip()
except IOError:
# If the interface is bound to a DPDK driver, get the mac address from
# the DPDK mapping file as /sys files will be removed after binding.
dpdk_mac_address = _get_dpdk_mac_address(name)
if dpdk_mac_address:
return dpdk_mac_address
logger.error("Unable to read mac address: %s" % name)
raise
def is_active_nic(interface_name):
return _is_available_nic(interface_name, True)
@ -170,7 +127,7 @@ def _is_vf_by_name(interface_name, check_mapping_file=False):
vf_path_check = common.get_dev_path(interface_name, 'physfn')
is_sriov_vf = os.path.isdir(vf_path_check)
if not is_sriov_vf and check_mapping_file:
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for item in sriov_map:
if (item['name'] == interface_name and
item['device_type'] == 'vf'):
@ -246,7 +203,7 @@ def _ordered_nics(check_active):
# Adding nics which are bound to DPDK as it will not be found in '/sys'
# after it is bound to DPDK driver.
contents = get_file_data(_DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
if contents:
dpdk_map = yaml.safe_load(contents)
for item in dpdk_map:
@ -267,7 +224,7 @@ def _ordered_nics(check_active):
nics.append(nic)
else:
logger.info("No DPDK mapping available in path (%s)" %
_DPDK_MAPPING_FILE)
common.DPDK_MAPPING_FILE)
# NOTE: we could just natural sort all active devices,
# but this ensures em, eno, and eth are ordered first
@ -279,7 +236,7 @@ def _ordered_nics(check_active):
def diff(filename, data):
file_data = get_file_data(filename)
file_data = common.get_file_data(filename)
logger.debug("Diff file data:\n%s" % file_data)
logger.debug("Diff data:\n%s" % data)
# convert to string as JSON may have unicode in it
@ -309,7 +266,7 @@ def bind_dpdk_interfaces(ifname, driver, noop):
msg = "Failed to modprobe vfio-pci module"
raise OvsDpdkBindException(msg)
mac_address = interface_mac(ifname)
mac_address = common.interface_mac(ifname)
vendor_id = common.get_vendor_id(ifname)
try:
out, err = processutils.execute('driverctl', 'set-override',
@ -383,7 +340,7 @@ def translate_ifname_to_pci_address(ifname, noop):
pci_address = get_stored_pci_address(ifname, noop)
if pci_address is None and not noop:
pci_address = get_pci_address(ifname, noop=False)
mac_address = interface_mac(ifname)
mac_address = common.interface_mac(ifname)
_update_dpdk_map(ifname, pci_address, mac_address, driver=None)
return pci_address
@ -413,7 +370,7 @@ def get_dpdk_devargs(ifname, noop):
# address associated with multiple ports. Using a PCI
# device wont work. Instead, we should use
# "class=eth,mac=<MAC>"
dpdk_devargs = "class=eth,mac=%s" % interface_mac(ifname)
dpdk_devargs = f"class=eth,mac={common.interface_mac(ifname)}"
elif is_active_nic(ifname):
# Other Mellanox devices are active and they are not stored
# in dpdk_mapping.yaml file, so we need to get their pci
@ -436,7 +393,7 @@ def get_dpdk_devargs(ifname, noop):
# Once the interface is bound to a DPDK driver, all the references to the
# interface including '/sys' and '/proc', will be removed. And there is no
# way to identify the nic name after it is bound. So, the DPDK bound nic info
# is stored persistently in _DPDK_MAPPING_FILE and is used to for nic numbering
# is stored persistently in DPDK_MAPPING_FILE and is used to for nic numbering
# on subsequent runs of os-net-config.
def _update_dpdk_map(ifname, pci_address, mac_address, driver):
dpdk_map = _get_dpdk_map()
@ -454,23 +411,15 @@ def _update_dpdk_map(ifname, pci_address, mac_address, driver):
new_item['driver'] = driver
dpdk_map.append(new_item)
write_yaml_config(_DPDK_MAPPING_FILE, dpdk_map)
write_yaml_config(common.DPDK_MAPPING_FILE, dpdk_map)
def _get_dpdk_map():
contents = get_file_data(_DPDK_MAPPING_FILE)
contents = common.get_file_data(common.DPDK_MAPPING_FILE)
dpdk_map = yaml.safe_load(contents) if contents else []
return dpdk_map
def _get_dpdk_mac_address(name):
contents = get_file_data(_DPDK_MAPPING_FILE)
dpdk_map = yaml.safe_load(contents) if contents else []
for item in dpdk_map:
if item['name'] == name:
return item['mac_address']
def update_sriov_pf_map(ifname, numvfs, noop, promisc=None,
link_mode='legacy', vdpa=False, steering_mode=None):
if not noop:
@ -478,7 +427,7 @@ def update_sriov_pf_map(ifname, numvfs, noop, promisc=None,
if cur_numvfs > 0 and cur_numvfs != numvfs:
msg = ("Can't change the numvfs for %s" % ifname)
raise sriov_config.SRIOVNumvfsException(msg)
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for item in sriov_map:
if item['device_type'] == 'pf' and item['name'] == ifname:
item['numvfs'] = numvfs
@ -502,13 +451,7 @@ def update_sriov_pf_map(ifname, numvfs, noop, promisc=None,
new_item['steering_mode'] = steering_mode
sriov_map.append(new_item)
write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, sriov_map)
def _get_sriov_map():
contents = get_file_data(sriov_config._SRIOV_CONFIG_FILE)
sriov_map = yaml.safe_load(contents) if contents else []
return sriov_map
write_yaml_config(common.SRIOV_CONFIG_FILE, sriov_map)
def _set_vf_fields(vf_name, vlan_id, qos, spoofcheck, trust, state, macaddr,
@ -544,7 +487,7 @@ def update_sriov_vf_map(pf_name, vfid, vf_name, vlan_id=0, qos=0,
spoofcheck=None, trust=None, state=None, macaddr=None,
promisc=None, pci_address=None,
min_tx_rate=0, max_tx_rate=0):
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for item in sriov_map:
if (item['device_type'] == 'vf' and
item['device'].get('name') == pf_name and
@ -564,11 +507,11 @@ def update_sriov_vf_map(pf_name, vfid, vf_name, vlan_id=0, qos=0,
_clear_empty_values(new_item)
sriov_map.append(new_item)
write_yaml_config(sriov_config._SRIOV_CONFIG_FILE, sriov_map)
write_yaml_config(common.SRIOV_CONFIG_FILE, sriov_map)
def _get_vf_name_from_map(pf_name, vfid):
sriov_map = _get_sriov_map()
sriov_map = common.get_sriov_map()
for item in sriov_map:
if (item['device_type'] == 'vf' and
item['device'].get('name') == pf_name and
@ -627,8 +570,7 @@ def configure_sriov_vfs():
def get_vf_devname(pf_name, vfid):
vf_path = os.path.join(common.SYS_CLASS_NET, pf_name,
f"device/virtfn{vfid}/net")
vf_path = common.get_dev_path(pf_name, f"virtfn{vfid}/net")
if os.path.isdir(vf_path):
vf_nic = os.listdir(vf_path)
else:
@ -758,7 +700,7 @@ def generate_vpp_config(vpp_config_path, vpp_interfaces, vpp_bonds):
:return: updated VPP config content.
"""
data = get_file_data(vpp_config_path)
data = common.get_file_data(vpp_config_path)
# Add interface config to 'dpdk' section
for vpp_interface in vpp_interfaces:
@ -915,7 +857,7 @@ def update_vpp_mapping(vpp_interfaces, vpp_bonds):
else:
raise VppException('Bond %s not found in VPP.' % vpp_bond.name)
vpp_start_cli = get_file_data(_VPP_EXEC_FILE)
vpp_start_cli = common.get_file_data(_VPP_EXEC_FILE)
for cli_line in cli_list:
if not re.search(r'^\s*%s\s*$' % cli_line,
vpp_start_cli, re.MULTILINE):