X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=nfvbench%2Futils.py;h=3974fd7ca3b94697d40638668c2224c75a3bde8a;hb=95f2491ed89ac99b0d8bd006b4a13cbeb1eb96ce;hp=20dc588fe533bf12e850391da708662a67e8ca2d;hpb=efc678c9d3843dcfd373b5749a88c51228b0b27c;p=nfvbench.git diff --git a/nfvbench/utils.py b/nfvbench/utils.py index 20dc588..3974fd7 100644 --- a/nfvbench/utils.py +++ b/nfvbench/utils.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import glob from math import isnan import os import re @@ -22,7 +23,7 @@ import errno import fcntl from functools import wraps import json -from log import LOG +from .log import LOG class TimeoutError(Exception): @@ -73,7 +74,7 @@ def save_json_result(result, json_file, std_json_path, service_chain, service_ch 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): @@ -82,7 +83,7 @@ def byteify(data, ignore_dicts=False): # 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 @@ -91,11 +92,45 @@ def dict_to_json_dict(record): 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:%s).*?(....:..:..\..)" % nic_slot + match = re.search(regex, dmidecode, 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) @@ -110,14 +145,28 @@ def get_intel_pci(nic_ports): 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 [] + 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): + pcis.append(port[1]) + + if len(pcis) == 2: + break + + return pcis multiplier_map = {