# License for the specific language governing permissions and limitations
# under the License.
+import glob
from math import isnan
import os
import re
import fcntl
from functools import wraps
import json
-from log import LOG
+from .log import LOG
class TimeoutError(Exception):
if filepaths:
for file_path in filepaths:
- LOG.info('Saving results in json file: ' + file_path + "...")
+ LOG.info('Saving results in json file: %s...', file_path)
with open(file_path, 'w') as jfp:
json.dump(result,
jfp,
def byteify(data, ignore_dicts=False):
# if this is a unicode string, return its string representation
- if isinstance(data, unicode):
+ if isinstance(data, str):
return data.encode('utf-8')
# if this is a list of values, return list of byteified values
if isinstance(data, list):
# but only if we haven't already byteified it
if isinstance(data, dict) and not ignore_dicts:
return {byteify(key, ignore_dicts=ignore_dicts): byteify(value, ignore_dicts=ignore_dicts)
- for key, value in data.iteritems()}
+ for key, value in list(data.items())}
# if it's anything else, return it in its original form
return data
return json.loads(json.dumps(record, default=lambda obj: obj.to_json()))
-def get_intel_pci(nic_ports):
- """Returns the first two PCI addresses of sorted PCI list for Intel NIC (i40e, ixgbe)"""
- hx = r'[0-9a-fA-F]'
- regex = r'{hx}{{4}}:({hx}{{2}}:{hx}{{2}}\.{hx}{{1}}).*(drv={driver}|.*unused=.*{driver})'
+def get_intel_pci(nic_slot=None, nic_ports=None):
+ """Returns two PCI address that will be used for NFVbench
+
+ @param nic_slot: The physical PCIe slot number in motherboard
+ @param nic_ports: Array of two integers indicating the ports to use on the NIC
+
+ When nic_slot and nic_ports are both supplied, the function will just return
+ the PCI addresses for them. The logic used is:
+ (1) Run "dmidecode -t slot"
+ (2) Grep for "SlotID:" with given nic_slot, and derive the bus address;
+ (3) Based on given nic_ports, generate the pci addresses based on above
+ base address;
+
+ When either nic_slot or nic_ports is not supplied, the function will
+ traverse all Intel NICs which use i40e or ixgbe driver, sorted by PCI
+ address, and return first two available ports which are not bonded
+ (802.11ad).
+ """
+ if nic_slot and nic_ports:
+ dmidecode = subprocess.check_output(['dmidecode', '-t', 'slot'])
+ regex = r"(?<=SlotID:{}).*?(....:..:..\..)".format(nic_slot)
+ match = re.search(regex, dmidecode.decode('utf-8'), flags=re.DOTALL)
+ if not match:
+ return None
+
+ pcis = []
+ # On some servers, the "Bus Address" returned by dmidecode is not the
+ # base pci address of the NIC. So only keeping the bus part of the
+ # address for better compability.
+ bus = match.group(1)[:match.group(1).rindex(':') + 1] + "00."
+ for port in nic_ports:
+ pcis.append(bus + str(port))
+
+ return pcis
+
+ hx = r'[0-9a-fA-F]'
+ regex = r'({hx}{{4}}:({hx}{{2}}:{hx}{{2}}\.{hx}{{1}})).*(drv={driver}|.*unused=.*{driver})'
+ pcis = []
try:
trex_base_dir = '/opt/trex'
contents = os.listdir(trex_base_dir)
devices = ''
for driver in ['i40e', 'ixgbe']:
- matches = re.findall(regex.format(hx=hx, driver=driver), devices)
- if matches:
- pcis = [x[0] for x in matches]
- if len(pcis) < 2:
- continue
- pcis.sort()
- return [pcis[port_index] for port_index in nic_ports]
-
- return []
+ matches = re.findall(regex.format(hx=hx, driver=driver), devices.decode("utf-8"))
+ if not matches:
+ continue
+
+ matches.sort()
+ for port in matches:
+ intf_name = glob.glob("/sys/bus/pci/devices/%s/net/*" % port[0])
+ if not intf_name:
+ # Interface is not bind to kernel driver, so take it
+ pcis.append(port[1])
+ else:
+ intf_name = intf_name[0][intf_name[0].rfind('/') + 1:]
+ process = subprocess.Popen(['ip', '-o', '-d', 'link', 'show', intf_name],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ intf_info, _ = process.communicate()
+ if not re.search('team_slave|bond_slave', intf_info.decode("utf-8")):
+ pcis.append(port[1])
+ if len(pcis) == 2:
+ break
+
+ return pcis
multiplier_map = {