From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [143.182.124.21]) by dpdk.org (Postfix) with ESMTP id 532B3B0A8 for ; Tue, 27 May 2014 05:43:04 +0200 (CEST) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 26 May 2014 20:43:14 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.98,916,1392192000"; d="scan'208,217";a="437152385" Received: from fmsmsx107.amr.corp.intel.com ([10.19.9.54]) by azsmga001.ch.intel.com with ESMTP; 26 May 2014 20:43:13 -0700 Received: from fmsmsx155.amr.corp.intel.com (10.18.116.71) by FMSMSX107.amr.corp.intel.com (10.19.9.54) with Microsoft SMTP Server (TLS) id 14.3.123.3; Mon, 26 May 2014 20:43:12 -0700 Received: from shsmsx151.ccr.corp.intel.com (10.239.6.50) by FMSMSX155.amr.corp.intel.com (10.18.116.71) with Microsoft SMTP Server (TLS) id 14.3.123.3; Mon, 26 May 2014 20:43:12 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.7]) by SHSMSX151.ccr.corp.intel.com ([169.254.3.7]) with mapi id 14.03.0123.003; Tue, 27 May 2014 11:43:10 +0800 From: "Xu, HuilongX" To: "dev@dpdk.org" , "Burakov, Anatoly" , Thomas Monjalon Thread-Topic: RE: [dpdk-dev] [PATCH v2 15/16] Added support for VFIO drivers in dpdk_nic_bind.py Thread-Index: Ac95XcWuDzbL1zBFReGgsBx7+mZsKg== Date: Tue, 27 May 2014 03:43:10 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-cr-hashedpuzzle: Aaus FtNV G1x8 G78s In0X Iyzg Izfk JOXJ J0FA MLlL PJnD PLvQ RjsG SnCo TcBJ U+7Y; 2; ZABlAHYAQABkAHAAZABrAC4AbwByAGcAOwB0AGgAbwBtAGEAcwAuAG0AbwBuAGoAYQBsAG8AbgBAADYAdwBpAG4AZAAuAGMAbwBtAA==; Sosha1_v1; 7; {9CABA86A-83E1-4CEF-8CA3-84B05FF49406}; aAB1AGkAbABvAG4AZwB4AC4AeAB1AEAAaQBuAHQAZQBsAC4AYwBvAG0A; Tue, 27 May 2014 03:43:07 GMT; UgBFADoAIABbAGQAcABkAGsALQBkAGUAdgBdACAAWwBQAEEAVABDAEgAIAB2ADIAIAAxADUALwAxADYAXQAgAEEAZABkAGUAZAAgAHMAdQBwAHAAbwByAHQAIABmAG8AcgAgAFYARgBJAE8AIABkAHIAaQB2AGUAcgBzACAAaQBuAAkAZABwAGQAawBfAG4AaQBjAF8AYgBpAG4AZAAuAHAAeQA= x-cr-puzzleid: {9CABA86A-83E1-4CEF-8CA3-84B05FF49406} x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.15 Subject: Re: [dpdk-dev] [PATCH v2 15/16] Added support for VFIO drivers in dpdk_nic_bind.py X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 May 2014 03:43:06 -0000 Since igb_uio no longer has a PCI ID list, the script will no longer distinguish between supported and unsupported NICs. There's a weird behaviour of sysfs when a new device ID is added to new_id. Subsequent writing to "bind" will result in IOError on closing the file. This error is harmless but it triggers the exception anyway, so in order to work around that, we check if the device was actually bound to the driver before raising an error. Signed-off-by: Anatoly Burakov Test-by: HuilongX Xu Compile pass >>Compile OS: FC20 x86_64 >>Kernel version: 3.13.6-200 >>GCC version: 4.8.2 >>Server: Crownpass --- tools/dpdk_nic_bind.py | 163 ++++++++++++++++++++++++++-------------------= --- 1 files changed, 89 insertions(+), 74 deletions(-) diff --git a/tools/dpdk_nic_bind.py b/tools/dpdk_nic_bind.py index 824aa2b..06fb28a 100755 --- a/tools/dpdk_nic_bind.py +++ b/tools/dpdk_nic_bind.py @@ -42,8 +42,8 @@ ETHERNET_CLASS =3D "0200" # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties devices =3D {} -# list of vendor:device pairs (again stored as dictionary) supported by ig= b_uio -module_dev_ids =3D [] +# list of supported DPDK drivers +dpdk_drivers =3D [ "igb_uio", "vfio-pci" ] def usage(): '''Print usage information for the program''' @@ -147,64 +147,70 @@ def find_module(mod): return path def check_modules(): - '''Checks that the needed modules (igb_uio) is loaded, and then - determine from the .ko file, what its supported device ids are''' - global module_dev_ids + '''Checks that the needed modules (igb_uio or vfio_pci) are loaded''' + global dpdk_drivers fd =3D file("/proc/modules") loaded_mods =3D fd.readlines() fd.close() - mod =3D "igb_uio" + + # list of supported modules + mods =3D [{"Name" : driver, "Found" : False} for driver in dpdk_drive= rs] # first check if module is loaded - found =3D False for line in loaded_mods: - if line.startswith(mod): - found =3D True - break - if not found: - print "Error - module %s not loaded" %mod - sys.exit(1) - - # now find the .ko and get list of supported vendor/dev-ids - modpath =3D find_module(mod) - if modpath is None: - print "Cannot find module file %s" % (mod + ".ko") + for mod in mods: + if line.startswith(mod["Name"]): + mod["Found"] =3D True + # special case for vfio_pci (module is named vfio-pci, + # but its .ko is named vfio_pci) + elif line.replace("_", "-").startswith(mod["Name"]): + mod["Found"] =3D True + + # check if we have at least one loaded module + if True not in [mod["Found"] for mod in mods]: + print "Error - no supported modules are loaded" sys.exit(1) - depmod_output =3D check_output(["depmod", "-n", modpath]).splitlines() - for line in depmod_output: - if not line.startswith("alias"): - continue - if not line.endswith(mod): - continue - lineparts =3D line.split() - if not(lineparts[1].startswith("pci:")): - continue; - else: - lineparts[1] =3D lineparts[1][4:] - vendor =3D lineparts[1][:9] - device =3D lineparts[1][9:18] - if vendor.startswith("v") and device.startswith("d"): - module_dev_ids.append({"Vendor": int(vendor[1:],16), - "Device": int(device[1:],16)}) - -def is_supported_device(dev_id): - '''return true if device is supported by igb_uio, false otherwise''' - for dev in module_dev_ids: - if (dev["Vendor"] =3D=3D devices[dev_id]["Vendor"] and - dev["Device"] =3D=3D devices[dev_id]["Device"]): - return True - return False + + # change DPDK driver list to only contain drivers that are loaded + dpdk_drivers =3D [mod["Name"] for mod in mods if mod["Found"]] + def has_driver(dev_id): '''return true if a device is assigned to a driver. False otherwise''' return "Driver_str" in devices[dev_id] +def get_pci_device_details(dev_id): + '''This function gets additional details for a PCI device''' + device =3D {} + + extra_info =3D check_output(["lspci", "-vmmks", dev_id]).splitlines() + + # parse lspci details + for line in extra_info: + if len(line) =3D=3D 0: + continue + name, value =3D line.split("\t", 1) + name =3D name.strip(":") + "_str" + device[name] =3D value + # check for a unix interface name + sys_path =3D "/sys/bus/pci/devices/%s/net/" % dev_id + if exists(sys_path): + device["Interface"] =3D ",".join(os.listdir(sys_path)) + else: + device["Interface"] =3D "" + # check if a port is used for ssh connection + device["Ssh_if"] =3D False + device["Active"] =3D "" + + return device + def get_nic_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 =3D {} @@ -237,38 +243,23 @@ def get_nic_details(): # based on the basic info, get extended text details for d in devices.keys(): - extra_info =3D check_output(["lspci", "-vmmks", d]).splitlines() - # parse lspci details - for line in extra_info: - if len(line) =3D=3D 0: - continue - name, value =3D line.split("\t", 1) - name =3D name.strip(":") + "_str" - devices[d][name] =3D value - # check for a unix interface name - sys_path =3D "/sys/bus/pci/devices/%s/net/" % d - if exists(sys_path): - devices[d]["Interface"] =3D ",".join(os.listdir(sys_path)) - else: - devices[d]["Interface"] =3D "" - # check if a port is used for ssh connection - devices[d]["Ssh_if"] =3D False - devices[d]["Active"] =3D "" + # get additional info and add it to existing data + devices[d] =3D dict(devices[d].items() + get_pci_device_details(d)= .items()) + for _if in ssh_if: if _if in devices[d]["Interface"].split(","): devices[d]["Ssh_if"] =3D True devices[d]["Active"] =3D "*Active*" break; - # add igb_uio to list of supporting modules if needed - if is_supported_device(d): - if "Module_str" in devices[d]: - if "igb_uio" not in devices[d]["Module_str"]: - devices[d]["Module_str"] =3D devices[d]["Module_str"] = + ",igb_uio" - else: - devices[d]["Module_str"] =3D "igb_uio" - if "Module_str" not in devices[d]: - devices[d]["Module_str"] =3D "" + # add DPDK drivers 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"] =3D devices[d]["Module_str"] = + ",%s" % driver + else: + devices[d]["Module_str"] =3D ",".join(dpdk_drivers) + # make sure the driver and module strings do not have any duplicat= es if has_driver(d): modules =3D devices[d]["Module_str"].split(",") @@ -298,7 +289,7 @@ def dev_id_from_dev_name(dev_name): sys.exit(1) def unbind_one(dev_id, force): - '''Unbind the device identified by "dev_id" from its current driver''' + '''Unbind the device identified by "dev_id" from its current driver''' dev =3D devices[dev_id] if not has_driver(dev_id): print "%s %s %s is not currently managed by any driver\n" % \ @@ -329,8 +320,8 @@ def bind_one(dev_id, driver, force): # prevent disconnection of our ssh session if dev["Ssh_if"] and not force: - print "Routing table indicates that interface %s is active" \ - ". Not modifying" % (dev_id) + print ("Routing table indicates that interface %s is active" + ". Not modifying" % (dev_id)) return # unbind any existing drivers we don't want @@ -343,6 +334,22 @@ def bind_one(dev_id, driver, force): unbind_one(dev_id, force) dev["Driver_str"] =3D "" # clear driver string + # if we are binding to one of DPDK drivers, add PCI id's to that drive= r + if driver in dpdk_drivers: + filename =3D "/sys/bus/pci/drivers/%s/new_id" % driver + try: + f =3D open(filename, "w") + except: + print "Error: bind failed for %s - Cannot open %s" % (dev_id, = filename) + return + try: + f.write("%04x %04x" % (dev["Vendor"], dev["Device"])) + f.close() + except: + print "Error: bind failed for %s - Cannot write new PCI ID to = " \ + "driver %s" % (dev_id, driver) + return + # do the bind by writing to /sys filename =3D "/sys/bus/pci/drivers/%s/bind" % driver try: @@ -356,6 +363,12 @@ def bind_one(dev_id, driver, force): f.write(dev_id) f.close() except: + # for some reason, closing dev_id after adding a new PCI ID to new= _id + # results in IOError. however, if the device was successfully boun= d, + # we don't care for any errors and can safely ignore IOError + tmp =3D get_pci_device_details(dev_id) + if "Driver_str" in tmp and tmp["Driver_str"] =3D=3D driver: + return print "Error: bind failed for %s - Cannot bind to driver %s" % (de= v_id, driver) if saved_driver is not None: # restore any previous driver bind_one(dev_id, saved_driver, force) @@ -399,21 +412,23 @@ def show_status(): '''Function called when the script is passed the "--status" option. Di= splays to the user what devices are bound to the igb_uio driver, the kernel d= river or to no driver''' + global dpdk_drivers kernel_drv =3D [] - uio_drv =3D [] + dpdk_drv =3D [] no_drv =3D [] + # split our list of 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"] =3D=3D "igb_uio": - uio_drv.append(devices[d]) + 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 IGB_UIO driver", uio_drv, \ + display_devices("Network devices using IGB_UIO driver", dpdk_drv, \ "drv=3D%(Driver_str)s unused=3D%(Module_str)s") display_devices("Network devices using kernel driver", kernel_drv, "if=3D%(Interface)s drv=3D%(Driver_str)s unused=3D%(Mo= dule_str)s %(Active)s") -- 1.7.0.7