X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=tools%2Fdpdk-devbind.py;h=47597deee939ae03acca73c31606ecdac01ecaf0;hb=refs%2Fchanges%2F33%2F18433%2F1;hp=b69ca2a0dbdbf2fb98ead9ba679089ca33184bcc;hpb=5b1ff351aa2d38446487eed6ccd7ace1b654bbe6;p=deb_dpdk.git diff --git a/tools/dpdk-devbind.py b/tools/dpdk-devbind.py index b69ca2a0..47597dee 100755 --- a/tools/dpdk-devbind.py +++ b/tools/dpdk-devbind.py @@ -40,6 +40,7 @@ from os.path import exists, abspath, dirname, basename # The PCI base class for NETWORK devices NETWORK_BASE_CLASS = "02" +CRYPTO_BASE_CLASS = "0b" # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties @@ -72,7 +73,7 @@ Options: Display usage information and quit -s, --status: - Print the current status of all known network interfaces. + Print the current status of all known network and crypto devices. For each device, it displays the PCI domain, bus, slot and function, along with a text description of the device. Depending upon whether the device is being used by a kernel driver, the igb_uio driver, or no @@ -92,7 +93,7 @@ Options: Unbind a device (Equivalent to \"-b none\") --force: - By default, devices which are used by Linux - as indicated by having + By default, network devices which are used by Linux - as indicated by having routes in the routing table - cannot be modified. Using the --force flag overrides this behavior, allowing active links to be forcibly unbound. @@ -125,40 +126,6 @@ def check_output(args, stderr=None): stderr=stderr).communicate()[0] -def find_module(mod): - '''find the .ko file for kernel module named mod. - Searches the $RTE_SDK/$RTE_TARGET directory, the kernel - modules directory and finally under the parent directory of - the script ''' - # check $RTE_SDK/$RTE_TARGET directory - if 'RTE_SDK' in os.environ and 'RTE_TARGET' in os.environ: - path = "%s/%s/kmod/%s.ko" % (os.environ['RTE_SDK'], - os.environ['RTE_TARGET'], mod) - if exists(path): - return path - - # check using depmod - try: - depmod_out = check_output(["modinfo", "-n", mod], - stderr=subprocess.STDOUT).lower() - if "error" not in depmod_out: - path = depmod_out.strip() - if exists(path): - return path - except: # if modinfo can't find module, it fails, so continue - pass - - # check for a copy based off current path - tools_dir = dirname(abspath(sys.argv[0])) - if (tools_dir.endswith("tools")): - base_dir = dirname(tools_dir) - find_out = check_output(["find", base_dir, "-name", mod + ".ko"]) - if len(find_out) > 0: # something matched - path = find_out.splitlines()[0] - if exists(path): - return path - - def check_modules(): '''Checks that igb_uio is loaded''' global dpdk_drivers @@ -181,8 +148,7 @@ def check_modules(): # special case for vfio_pci (module is named vfio-pci, # but its .ko is named vfio_pci) - sysfs_mods = map(lambda a: - a if a != 'vfio_pci' else 'vfio-pci', sysfs_mods) + sysfs_mods = [a if a != 'vfio_pci' else 'vfio-pci' for a in sysfs_mods] for mod in mods: if mod["Name"] in sysfs_mods: @@ -221,11 +187,12 @@ def get_pci_device_details(dev_id): name = name.strip(":") + "_str" device[name] = value # check for a unix interface name - sys_path = "/sys/bus/pci/devices/%s/net/" % dev_id - if exists(sys_path): - device["Interface"] = ",".join(os.listdir(sys_path)) - else: - device["Interface"] = "" + device["Interface"] = "" + for base, dirs, _ in os.walk("/sys/bus/pci/devices/%s/" % dev_id): + if "net" in dirs: + device["Interface"] = \ + ",".join(os.listdir(os.path.join(base, "net"))) + break # check if a port is used for ssh connection device["Ssh_if"] = False device["Active"] = "" @@ -299,6 +266,57 @@ def get_nic_details(): devices[d]["Module_str"] = ",".join(modules) +def get_crypto_details(): + '''This function populates the "devices" dictionary. The keys used are + the pci addresses (domain:bus:slot.func). The values are themselves + dictionaries - one for each NIC.''' + global devices + global dpdk_drivers + + # clear any old data + # devices = {} + # first loop through and read details for all devices + # request machine readable format, with numeric IDs + dev = {} + dev_lines = check_output(["lspci", "-Dvmmn"]).splitlines() + for dev_line in dev_lines: + if (len(dev_line) == 0): + if (dev["Class"][0:2] == CRYPTO_BASE_CLASS): + # convert device and vendor ids to numbers, then add to global + dev["Vendor"] = int(dev["Vendor"], 16) + dev["Device"] = int(dev["Device"], 16) + # use dict to make copy of dev + devices[dev["Slot"]] = dict(dev) + else: + name, value = dev_line.decode().split("\t", 1) + dev[name.rstrip(":")] = value + + # based on the basic info, get extended text details + for d in devices.keys(): + if devices[d]["Class"][0:2] != CRYPTO_BASE_CLASS: + continue + + # get additional info and add it to existing data + devices[d] = devices[d].copy() + devices[d].update(get_pci_device_details(d).items()) + + # add igb_uio to list of supporting modules if needed + if "Module_str" in devices[d]: + for driver in dpdk_drivers: + if driver not in devices[d]["Module_str"]: + devices[d]["Module_str"] = \ + devices[d]["Module_str"] + ",%s" % driver + else: + devices[d]["Module_str"] = ",".join(dpdk_drivers) + + # make sure the driver and module strings do not have any duplicates + if has_driver(d): + modules = devices[d]["Module_str"].split(",") + if devices[d]["Driver_str"] in modules: + modules.remove(devices[d]["Driver_str"]) + devices[d]["Module_str"] = ",".join(modules) + + def dev_id_from_dev_name(dev_name): '''Take a device "name" - a string passed in by user to identify a NIC device, and determine the device id - i.e. the domain:bus:slot.func - for @@ -480,15 +498,16 @@ def show_status(): dpdk_drv = [] no_drv = [] - # split our list of devices into the three categories above + # split our list of network devices into the three categories above for d in devices.keys(): - if not has_driver(d): - no_drv.append(devices[d]) - continue - if devices[d]["Driver_str"] in dpdk_drivers: - dpdk_drv.append(devices[d]) - else: - kernel_drv.append(devices[d]) + if (NETWORK_BASE_CLASS in devices[d]["Class"]): + if not has_driver(d): + no_drv.append(devices[d]) + continue + if devices[d]["Driver_str"] in dpdk_drivers: + dpdk_drv.append(devices[d]) + else: + kernel_drv.append(devices[d]) # print each category separately, so we can clearly see what's used by DPDK display_devices("Network devices using DPDK-compatible driver", dpdk_drv, @@ -498,6 +517,28 @@ def show_status(): "unused=%(Module_str)s %(Active)s") display_devices("Other network devices", no_drv, "unused=%(Module_str)s") + # split our list of crypto devices into the three categories above + kernel_drv = [] + dpdk_drv = [] + no_drv = [] + + for d in devices.keys(): + if (CRYPTO_BASE_CLASS in devices[d]["Class"]): + if not has_driver(d): + no_drv.append(devices[d]) + continue + if devices[d]["Driver_str"] in dpdk_drivers: + dpdk_drv.append(devices[d]) + else: + kernel_drv.append(devices[d]) + + display_devices("Crypto devices using DPDK-compatible driver", dpdk_drv, + "drv=%(Driver_str)s unused=%(Module_str)s") + display_devices("Crypto devices using kernel driver", kernel_drv, + "drv=%(Driver_str)s " + "unused=%(Module_str)s") + display_devices("Other crypto devices", no_drv, "unused=%(Module_str)s") + def parse_args(): '''Parses the command-line arguments given by the user and takes the @@ -562,14 +603,23 @@ def do_arg_actions(): if status_flag: if b_flag is not None: get_nic_details() # refresh if we have changed anything + get_crypto_details() # refresh if we have changed anything show_status() def main(): '''program main function''' + # check if lspci is installed, suppress any output + with open(os.devnull, 'w') as devnull: + ret = subprocess.call(['which', 'lspci'], + stdout=devnull, stderr=devnull) + if ret != 0: + print("'lspci' not found - please install 'pciutils'") + sys.exit(1) parse_args() check_modules() get_nic_details() + get_crypto_details() do_arg_actions() if __name__ == "__main__":