Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/13425/?format=api
https://patches.dpdk.org/api/patches/13425/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/1465494421-6210-6-git-send-email-nhorman@tuxdriver.com/", "project": { "id": 1, "url": "https://patches.dpdk.org/api/projects/1/?format=api", "name": "DPDK", "link_name": "dpdk", "list_id": "dev.dpdk.org", "list_email": "dev@dpdk.org", "web_url": "http://core.dpdk.org", "scm_url": "git://dpdk.org/dpdk", "webscm_url": "http://git.dpdk.org/dpdk", "list_archive_url": "https://inbox.dpdk.org/dev", "list_archive_url_format": "https://inbox.dpdk.org/dev/{}", "commit_url_format": "" }, "msgid": "<1465494421-6210-6-git-send-email-nhorman@tuxdriver.com>", "list_archive_url": "https://inbox.dpdk.org/dev/1465494421-6210-6-git-send-email-nhorman@tuxdriver.com", "date": "2016-06-09T17:47:00", "name": "[dpdk-dev,PATCHv7,5/6] pmdinfo.py: Add tool to query binaries for hw and other support information", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "e7b2e3ca85114941f8e75f10eac71f00b9d47284", "submitter": { "id": 32, "url": "https://patches.dpdk.org/api/people/32/?format=api", "name": "Neil Horman", "email": "nhorman@tuxdriver.com" }, "delegate": { "id": 1, "url": "https://patches.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "https://patches.dpdk.org/project/dpdk/patch/1465494421-6210-6-git-send-email-nhorman@tuxdriver.com/mbox/", "series": [], "comments": "https://patches.dpdk.org/api/patches/13425/comments/", "check": "pending", "checks": "https://patches.dpdk.org/api/patches/13425/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@dpdk.org", "Delivered-To": "patchwork@dpdk.org", "Received": [ "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 62FD22B87;\n\tThu, 9 Jun 2016 19:47:40 +0200 (CEST)", "from smtp.tuxdriver.com (charlotte.tuxdriver.com [70.61.120.58])\n\tby dpdk.org (Postfix) with ESMTP id 22A062B83\n\tfor <dev@dpdk.org>; Thu, 9 Jun 2016 19:47:39 +0200 (CEST)", "from [107.15.76.160] (helo=localhost)\n\tby smtp.tuxdriver.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.63)\n\t(envelope-from <nhorman@tuxdriver.com>)\n\tid 1bB43I-00008I-Ek; Thu, 09 Jun 2016 13:47:36 -0400" ], "From": "Neil Horman <nhorman@tuxdriver.com>", "To": "dev@dpdk.org", "Cc": "Neil Horman <nhorman@tuxdriver.com>,\n\tBruce Richardson <bruce.richardson@intel.com>,\n\tThomas Monjalon <thomas.monjalon@6wind.com>,\n\tStephen Hemminger <stephen@networkplumber.org>,\n\tPanu Matilainen <pmatilai@redhat.com>", "Date": "Thu, 9 Jun 2016 13:47:00 -0400", "Message-Id": "<1465494421-6210-6-git-send-email-nhorman@tuxdriver.com>", "X-Mailer": "git-send-email 2.5.5", "In-Reply-To": "<1465494421-6210-1-git-send-email-nhorman@tuxdriver.com>", "References": "<1463431287-4551-1-git-send-email-nhorman@tuxdriver.com>\n\t<1465494421-6210-1-git-send-email-nhorman@tuxdriver.com>", "X-Spam-Score": "-1.0 (-)", "X-Spam-Status": "No", "Subject": "[dpdk-dev] [PATCHv7 5/6] pmdinfo.py: Add tool to query binaries for\n\thw and other support information", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "patches and discussions about DPDK <dev.dpdk.org>", "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://dpdk.org/ml/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org", "Sender": "\"dev\" <dev-bounces@dpdk.org>" }, "content": "This tool searches for the primer sting PMD_DRIVER_INFO= in any ELF binary,\nand, if found parses the remainder of the string as a json encoded string,\noutputting the results in either a human readable or raw, script parseable\nformat\n\nNote that, in the case of dynamically linked applications, pmdinfo.py will\nscan for implicitly linked PMDs by searching the specified binaries\n.dynamic section for DT_NEEDED entries that contain the substring\nlibrte_pmd. The DT_RUNPATH, LD_LIBRARY_PATH, /usr/lib and /lib are\nsearched for these libraries, in that order\n\nIf a file is specified with no path, it is assumed to be a PMD DSO, and the\nLD_LIBRARY_PATH, /usr/lib[64]/ and /lib[64] is searched for it\n\nCurrently the tool can output data in 3 formats:\n\na) raw, suitable for scripting, where the raw JSON strings are dumped out\nb) table format (default) where hex pci ids are dumped in a table format\nc) pretty, where a user supplied pci.ids file is used to print out vendor\nand device strings\n\nSigned-off-by: Neil Horman <nhorman@tuxdriver.com>\nCC: Bruce Richardson <bruce.richardson@intel.com>\nCC: Thomas Monjalon <thomas.monjalon@6wind.com>\nCC: Stephen Hemminger <stephen@networkplumber.org>\nCC: Panu Matilainen <pmatilai@redhat.com>\n---\n mk/rte.sdkinstall.mk | 2 +\n tools/pmdinfo.py | 629 +++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 631 insertions(+)\n create mode 100755 tools/pmdinfo.py", "diff": "diff --git a/mk/rte.sdkinstall.mk b/mk/rte.sdkinstall.mk\nindex 68e56b6..dc36df5 100644\n--- a/mk/rte.sdkinstall.mk\n+++ b/mk/rte.sdkinstall.mk\n@@ -126,6 +126,8 @@ install-runtime:\n \t$(Q)$(call rte_mkdir, $(DESTDIR)$(sbindir))\n \t$(Q)$(call rte_symlink, $(DESTDIR)$(datadir)/tools/dpdk_nic_bind.py, \\\n \t $(DESTDIR)$(sbindir)/dpdk_nic_bind)\n+\t$(Q)$(call rte_symlink, $(DESTDIR)$(datadir)/tools/pmdinfo.py, \\\n+\t\t\t\t $(DESTDIR)$(bindir)/dpdk-pmdinfo)\n \n install-kmod:\n ifneq ($(wildcard $O/kmod/*),)\ndiff --git a/tools/pmdinfo.py b/tools/pmdinfo.py\nnew file mode 100755\nindex 0000000..e531154\n--- /dev/null\n+++ b/tools/pmdinfo.py\n@@ -0,0 +1,629 @@\n+#!/usr/bin/python\n+# -------------------------------------------------------------------------\n+# scripts/pmdinfo.py\n+#\n+# Utility to dump PMD_INFO_STRING support from an object file\n+#\n+# -------------------------------------------------------------------------\n+import os\n+import sys\n+from optparse import OptionParser\n+import string\n+import json\n+\n+# For running from development directory. It should take precedence over the\n+# installed pyelftools.\n+sys.path.insert(0, '.')\n+\n+\n+from elftools import __version__\n+from elftools.common.exceptions import ELFError\n+from elftools.common.py3compat import (\n+ ifilter, byte2int, bytes2str, itervalues, str2bytes)\n+from elftools.elf.elffile import ELFFile\n+from elftools.elf.dynamic import DynamicSection, DynamicSegment\n+from elftools.elf.enums import ENUM_D_TAG\n+from elftools.elf.segments import InterpSegment\n+from elftools.elf.sections import SymbolTableSection\n+from elftools.elf.gnuversions import (\n+ GNUVerSymSection, GNUVerDefSection,\n+ GNUVerNeedSection,\n+)\n+from elftools.elf.relocation import RelocationSection\n+from elftools.elf.descriptions import (\n+ describe_ei_class, describe_ei_data, describe_ei_version,\n+ describe_ei_osabi, describe_e_type, describe_e_machine,\n+ describe_e_version_numeric, describe_p_type, describe_p_flags,\n+ describe_sh_type, describe_sh_flags,\n+ describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,\n+ describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,\n+ describe_ver_flags,\n+)\n+from elftools.elf.constants import E_FLAGS\n+from elftools.dwarf.dwarfinfo import DWARFInfo\n+from elftools.dwarf.descriptions import (\n+ describe_reg_name, describe_attr_value, set_global_machine_arch,\n+ describe_CFI_instructions, describe_CFI_register_rule,\n+ describe_CFI_CFA_rule,\n+)\n+from elftools.dwarf.constants import (\n+ DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)\n+from elftools.dwarf.callframe import CIE, FDE\n+\n+raw_output = False\n+pcidb = None\n+\n+# ===========================================\n+\n+\n+class Vendor:\n+ \"\"\"\n+ Class for vendors. This is the top level class\n+ for the devices belong to a specific vendor.\n+ self.devices is the device dictionary\n+ subdevices are in each device.\n+ \"\"\"\n+\n+ def __init__(self, vendorStr):\n+ \"\"\"\n+ Class initializes with the raw line from pci.ids\n+ Parsing takes place inside __init__\n+ \"\"\"\n+ self.ID = vendorStr.split()[0]\n+ self.name = vendorStr.replace(\"%s \" % self.ID, \"\").rstrip()\n+ self.devices = {}\n+\n+ def addDevice(self, deviceStr):\n+ \"\"\"\n+ Adds a device to self.devices\n+ takes the raw line from pci.ids\n+ \"\"\"\n+ s = deviceStr.strip()\n+ devID = s.split()[0]\n+ if devID in self.devices:\n+ pass\n+ else:\n+ self.devices[devID] = Device(deviceStr)\n+\n+ def report(self):\n+ print self.ID, self.name\n+ for id, dev in self.devices.items():\n+ dev.report()\n+\n+ def find_device(self, devid):\n+ # convert to a hex string and remove 0x\n+ devid = hex(devid)[2:]\n+ try:\n+ return self.devices[devid]\n+ except:\n+ return Device(\"%s Unknown Device\" % devid)\n+\n+\n+class Device:\n+\n+ def __init__(self, deviceStr):\n+ \"\"\"\n+ Class for each device.\n+ Each vendor has its own devices dictionary.\n+ \"\"\"\n+ s = deviceStr.strip()\n+ self.ID = s.split()[0]\n+ self.name = s.replace(\"%s \" % self.ID, \"\")\n+ self.subdevices = {}\n+\n+ def report(self):\n+ print \"\\t%s\\t%s\" % (self.ID, self.name)\n+ for subID, subdev in self.subdevices.items():\n+ subdev.report()\n+\n+ def addSubDevice(self, subDeviceStr):\n+ \"\"\"\n+ Adds a subvendor, subdevice to device.\n+ Uses raw line from pci.ids\n+ \"\"\"\n+ s = subDeviceStr.strip()\n+ spl = s.split()\n+ subVendorID = spl[0]\n+ subDeviceID = spl[1]\n+ subDeviceName = s.split(\" \")[-1]\n+ devID = \"%s:%s\" % (subVendorID, subDeviceID)\n+ self.subdevices[devID] = SubDevice(\n+ subVendorID, subDeviceID, subDeviceName)\n+\n+ def find_subid(self, subven, subdev):\n+ subven = hex(subven)[2:]\n+ subdev = hex(subdev)[2:]\n+ devid = \"%s:%s\" % (subven, subdev)\n+\n+ try:\n+ return self.subdevices[devid]\n+ except:\n+ if (subven == \"ffff\" and subdev == \"ffff\"):\n+ return SubDevice(\"ffff\", \"ffff\", \"(All Subdevices)\")\n+ else:\n+ return SubDevice(subven, subdev, \"(Unknown Subdevice)\")\n+\n+\n+class SubDevice:\n+ \"\"\"\n+ Class for subdevices.\n+ \"\"\"\n+\n+ def __init__(self, vendor, device, name):\n+ \"\"\"\n+ Class initializes with vendorid, deviceid and name\n+ \"\"\"\n+ self.vendorID = vendor\n+ self.deviceID = device\n+ self.name = name\n+\n+ def report(self):\n+ print \"\\t\\t%s\\t%s\\t%s\" % (self.vendorID, self.deviceID, self.name)\n+\n+\n+class PCIIds:\n+ \"\"\"\n+ Top class for all pci.ids entries.\n+ All queries will be asked to this class.\n+ PCIIds.vendors[\"0e11\"].devices[\"0046\"].\\\n+ subdevices[\"0e11:4091\"].name = \"Smart Array 6i\"\n+ \"\"\"\n+\n+ def __init__(self, filename):\n+ \"\"\"\n+ Prepares the directories.\n+ Checks local data file.\n+ Tries to load from local, if not found, downloads from web\n+ \"\"\"\n+ self.version = \"\"\n+ self.date = \"\"\n+ self.vendors = {}\n+ self.contents = None\n+ self.readLocal(filename)\n+ self.parse()\n+\n+ def reportVendors(self):\n+ \"\"\"Reports the vendors\n+ \"\"\"\n+ for vid, v in self.vendors.items():\n+ print v.ID, v.name\n+\n+ def report(self, vendor=None):\n+ \"\"\"\n+ Reports everything for all vendors or a specific vendor\n+ PCIIds.report() reports everything\n+ PCIIDs.report(\"0e11\") reports only \"Compaq Computer Corporation\"\n+ \"\"\"\n+ if vendor is not None:\n+ self.vendors[vendor].report()\n+ else:\n+ for vID, v in self.vendors.items():\n+ v.report()\n+\n+ def find_vendor(self, vid):\n+ # convert vid to a hex string and remove the 0x\n+ vid = hex(vid)[2:]\n+\n+ try:\n+ return self.vendors[vid]\n+ except:\n+ return Vendor(\"%s Unknown Vendor\" % (vid))\n+\n+ def findDate(self, content):\n+ for l in content:\n+ if l.find(\"Date:\") > -1:\n+ return l.split()[-2].replace(\"-\", \"\")\n+ return None\n+\n+ def parse(self):\n+ if len(self.contents) < 1:\n+ print \"data/%s-pci.ids not found\" % self.date\n+ else:\n+ vendorID = \"\"\n+ deviceID = \"\"\n+ for l in self.contents:\n+ if l[0] == \"#\":\n+ continue\n+ elif len(l.strip()) == 0:\n+ continue\n+ else:\n+ if l.find(\"\\t\\t\") == 0:\n+ self.vendors[vendorID].devices[\n+ deviceID].addSubDevice(l)\n+ elif l.find(\"\\t\") == 0:\n+ deviceID = l.strip().split()[0]\n+ self.vendors[vendorID].addDevice(l)\n+ else:\n+ vendorID = l.split()[0]\n+ self.vendors[vendorID] = Vendor(l)\n+\n+ def readLocal(self, filename):\n+ \"\"\"\n+ Reads the local file\n+ \"\"\"\n+ self.contents = open(filename).readlines()\n+ self.date = self.findDate(self.contents)\n+\n+ def loadLocal(self):\n+ \"\"\"\n+ Loads database from local. If there is no file,\n+ it creates a new one from web\n+ \"\"\"\n+ self.date = idsfile[0].split(\"/\")[1].split(\"-\")[0]\n+ self.readLocal()\n+\n+\n+# =======================================\n+\n+def search_file(filename, search_path):\n+ \"\"\" Given a search path, find file with requested name \"\"\"\n+ for path in string.split(search_path, \":\"):\n+ candidate = os.path.join(path, filename)\n+ if os.path.exists(candidate):\n+ return os.path.abspath(candidate)\n+ return None\n+\n+\n+class ReadElf(object):\n+ \"\"\" display_* methods are used to emit output into the output stream\n+ \"\"\"\n+\n+ def __init__(self, file, output):\n+ \"\"\" file:\n+ stream object with the ELF file to read\n+\n+ output:\n+ output stream to write to\n+ \"\"\"\n+ self.elffile = ELFFile(file)\n+ self.output = output\n+\n+ # Lazily initialized if a debug dump is requested\n+ self._dwarfinfo = None\n+\n+ self._versioninfo = None\n+\n+ def _section_from_spec(self, spec):\n+ \"\"\" Retrieve a section given a \"spec\" (either number or name).\n+ Return None if no such section exists in the file.\n+ \"\"\"\n+ try:\n+ num = int(spec)\n+ if num < self.elffile.num_sections():\n+ return self.elffile.get_section(num)\n+ else:\n+ return None\n+ except ValueError:\n+ # Not a number. Must be a name then\n+ return self.elffile.get_section_by_name(str2bytes(spec))\n+\n+ def pretty_print_pmdinfo(self, pmdinfo):\n+ global pcidb\n+\n+ for i in pmdinfo[\"pci_ids\"]:\n+ vendor = pcidb.find_vendor(i[0])\n+ device = vendor.find_device(i[1])\n+ subdev = device.find_subid(i[2], i[3])\n+ print(\"%s (%s) : %s (%s) %s\" %\n+ (vendor.name, vendor.ID, device.name,\n+ device.ID, subdev.name))\n+\n+ def parse_pmd_info_string(self, mystring):\n+ global raw_output\n+ global pcidb\n+\n+ optional_pmd_info = [{'id': 'params', 'tag': 'PMD PARAMETERS'}]\n+\n+ i = mystring.index(\"=\")\n+ mystring = mystring[i + 2:]\n+ pmdinfo = json.loads(mystring)\n+\n+ if raw_output:\n+ print(pmdinfo)\n+ return\n+\n+ print(\"PMD NAME: \" + pmdinfo[\"name\"])\n+ for i in optional_pmd_info:\n+ try:\n+ print(\"%s: %s\" % (i['tag'], pmdinfo[i['id']]))\n+ except KeyError as e:\n+ continue\n+\n+ if (len(pmdinfo[\"pci_ids\"]) != 0):\n+ print(\"PMD HW SUPPORT:\")\n+ if pcidb is not None:\n+ self.pretty_print_pmdinfo(pmdinfo)\n+ else:\n+ print(\"VENDOR\\t DEVICE\\t SUBVENDOR\\t SUBDEVICE\")\n+ for i in pmdinfo[\"pci_ids\"]:\n+ print(\"0x%04x\\t 0x%04x\\t 0x%04x\\t\\t 0x%04x\" %\n+ (i[0], i[1], i[2], i[3]))\n+\n+ print(\"\")\n+\n+ def display_pmd_info_strings(self, section_spec):\n+ \"\"\" Display a strings dump of a section. section_spec is either a\n+ section number or a name.\n+ \"\"\"\n+ section = self._section_from_spec(section_spec)\n+ if section is None:\n+ return\n+\n+ data = section.data()\n+ dataptr = 0\n+\n+ while dataptr < len(data):\n+ while (dataptr < len(data) and\n+ not (32 <= byte2int(data[dataptr]) <= 127)):\n+ dataptr += 1\n+\n+ if dataptr >= len(data):\n+ break\n+\n+ endptr = dataptr\n+ while endptr < len(data) and byte2int(data[endptr]) != 0:\n+ endptr += 1\n+\n+ mystring = bytes2str(data[dataptr:endptr])\n+ rc = mystring.find(\"PMD_INFO_STRING\")\n+ if (rc != -1):\n+ self.parse_pmd_info_string(mystring)\n+\n+ dataptr = endptr\n+\n+ def find_librte_eal(self, section):\n+ for tag in section.iter_tags():\n+ if tag.entry.d_tag == 'DT_NEEDED':\n+ if \"librte_eal\" in tag.needed:\n+ return tag.needed\n+ return None\n+\n+ def search_for_autoload_path(self):\n+ scanelf = self\n+ scanfile = None\n+ library = None\n+\n+ section = self._section_from_spec(\".dynamic\")\n+ try:\n+ eallib = self.find_librte_eal(section)\n+ if eallib is not None:\n+ ldlibpath = os.environ.get('LD_LIBRARY_PATH')\n+ if ldlibpath is None:\n+ ldlibpath = \"\"\n+ dtr = self.get_dt_runpath(section)\n+ library = search_file(eallib,\n+ dtr + \":\" + ldlibpath +\n+ \":/usr/lib64:/lib64:/usr/lib:/lib\")\n+ if library is None:\n+ return (None, None)\n+ if raw_output is False:\n+ print(\"Scanning for autoload path in %s\" % library)\n+ scanfile = open(library, 'rb')\n+ scanelf = ReadElf(scanfile, sys.stdout)\n+ except AttributeError:\n+ # Not a dynamic binary\n+ pass\n+ except ELFError:\n+ scanfile.close()\n+ return (None, None)\n+\n+ section = scanelf._section_from_spec(\".rodata\")\n+ if section is None:\n+ if scanfile is not None:\n+ scanfile.close()\n+ return (None, None)\n+\n+ data = section.data()\n+ dataptr = 0\n+\n+ while dataptr < len(data):\n+ while (dataptr < len(data) and\n+ not (32 <= byte2int(data[dataptr]) <= 127)):\n+ dataptr += 1\n+\n+ if dataptr >= len(data):\n+ break\n+\n+ endptr = dataptr\n+ while endptr < len(data) and byte2int(data[endptr]) != 0:\n+ endptr += 1\n+\n+ mystring = bytes2str(data[dataptr:endptr])\n+ rc = mystring.find(\"DPDK_PLUGIN_PATH\")\n+ if (rc != -1):\n+ rc = mystring.find(\"=\")\n+ return (mystring[rc + 1:], library)\n+\n+ dataptr = endptr\n+ if scanfile is not None:\n+ scanfile.close()\n+ return (None, None)\n+\n+ def get_dt_runpath(self, dynsec):\n+ for tag in dynsec.iter_tags():\n+ if tag.entry.d_tag == 'DT_RUNPATH':\n+ return tag.runpath\n+ return \"\"\n+\n+ def process_dt_needed_entries(self):\n+ \"\"\" Look to see if there are any DT_NEEDED entries in the binary\n+ And process those if there are\n+ \"\"\"\n+ global raw_output\n+ runpath = \"\"\n+ ldlibpath = os.environ.get('LD_LIBRARY_PATH')\n+ if ldlibpath is None:\n+ ldlibpath = \"\"\n+\n+ dynsec = self._section_from_spec(\".dynamic\")\n+ try:\n+ runpath = self.get_dt_runpath(dynsec)\n+ except AttributeError:\n+ # dynsec is None, just return\n+ return\n+\n+ for tag in dynsec.iter_tags():\n+ if tag.entry.d_tag == 'DT_NEEDED':\n+ rc = tag.needed.find(\"librte_pmd\")\n+ if (rc != -1):\n+ library = search_file(tag.needed,\n+ runpath + \":\" + ldlibpath +\n+ \":/usr/lib64:/lib64:/usr/lib:/lib\")\n+ if library is not None:\n+ if raw_output is False:\n+ print(\"Scanning %s for pmd information\" % library)\n+ with open(library, 'rb') as file:\n+ try:\n+ libelf = ReadElf(file, sys.stdout)\n+ except ELFError as e:\n+ print(\"%s is no an ELF file\" % library)\n+ continue\n+ libelf.process_dt_needed_entries()\n+ libelf.display_pmd_info_strings(\".rodata\")\n+ file.close()\n+\n+\n+def scan_autoload_path(autoload_path):\n+ global raw_output\n+\n+ if os.path.exists(autoload_path) is False:\n+ return\n+\n+ try:\n+ dirs = os.listdir(autoload_path)\n+ except OSError as e:\n+ # Couldn't read the directory, give up\n+ return\n+\n+ for d in dirs:\n+ dpath = os.path.join(autoload_path, d)\n+ if os.path.isdir(dpath):\n+ scan_autoload_path(dpath)\n+ if os.path.isfile(dpath):\n+ try:\n+ file = open(dpath, 'rb')\n+ readelf = ReadElf(file, sys.stdout)\n+ except ELFError as e:\n+ # this is likely not an elf file, skip it\n+ continue\n+ except IOError as e:\n+ # No permission to read the file, skip it\n+ continue\n+\n+ if raw_output is False:\n+ print(\"Hw Support for library %s\" % d)\n+ readelf.display_pmd_info_strings(\".rodata\")\n+ file.close()\n+\n+\n+def scan_for_autoload_pmds(dpdk_path):\n+ \"\"\"\n+ search the specified application or path for a pmd autoload path\n+ then scan said path for pmds and report hw support\n+ \"\"\"\n+ global raw_output\n+\n+ if (os.path.isfile(dpdk_path) is False):\n+ if raw_output is False:\n+ print(\"Must specify a file name\")\n+ return\n+\n+ file = open(dpdk_path, 'rb')\n+ try:\n+ readelf = ReadElf(file, sys.stdout)\n+ except ElfError as e:\n+ if raw_output is False:\n+ print(\"Unable to parse %s\" % file)\n+ return\n+\n+ (autoload_path, scannedfile) = readelf.search_for_autoload_path()\n+ if (autoload_path is None or autoload_path is \"\"):\n+ if (raw_output is False):\n+ print(\"No autoload path configured in %s\" % dpdk_path)\n+ return\n+ if (raw_output is False):\n+ if (scannedfile is None):\n+ scannedfile = dpdk_path\n+ print(\"Found autoload path %s in %s\" % (autoload_path, scannedfile))\n+\n+ file.close()\n+ if (raw_output is False):\n+ print(\"Discovered Autoload HW Support:\")\n+ scan_autoload_path(autoload_path)\n+ return\n+\n+\n+def main(stream=None):\n+ global raw_output\n+ global pcidb\n+\n+ optparser = OptionParser(\n+ usage='usage: %prog [-hrtp] [-d <pci id file] <elf-file>',\n+ description=\"Dump pmd hardware support info\",\n+ add_help_option=True,\n+ prog='pmdinfo.py')\n+ optparser.add_option('-r', '--raw',\n+ action='store_true', dest='raw_output',\n+ help='Dump raw json strings')\n+ optparser.add_option(\"-d\", \"--pcidb\", dest=\"pcifile\",\n+ help=\"specify a pci database \"\n+ \"to get vendor names from\",\n+ default=\"/usr/share/hwdata/pci.ids\", metavar=\"FILE\")\n+ optparser.add_option(\"-t\", \"--table\", dest=\"tblout\",\n+ help=\"output information on hw support as a hex table\",\n+ action='store_true')\n+ optparser.add_option(\"-p\", \"--plugindir\", dest=\"pdir\",\n+ help=\"scan dpdk for autoload plugins\",\n+ action='store_true')\n+\n+ options, args = optparser.parse_args()\n+\n+ if options.raw_output:\n+ raw_output = True\n+\n+ if options.pcifile:\n+ pcidb = PCIIds(options.pcifile)\n+ if pcidb is None:\n+ print(\"Pci DB file not found\")\n+ exit(1)\n+\n+ if options.tblout:\n+ options.pcifile = None\n+ pcidb = None\n+\n+ if (len(args) == 0):\n+ optparser.print_usage()\n+ exit(1)\n+\n+ if options.pdir is True:\n+ exit(scan_for_autoload_pmds(args[0]))\n+\n+ ldlibpath = os.environ.get('LD_LIBRARY_PATH')\n+ if (ldlibpath is None):\n+ ldlibpath = \"\"\n+\n+ if (os.path.exists(args[0]) is True):\n+ myelffile = args[0]\n+ else:\n+ myelffile = search_file(\n+ args[0], ldlibpath + \":/usr/lib64:/lib64:/usr/lib:/lib\")\n+\n+ if (myelffile is None):\n+ print(\"File not found\")\n+ sys.exit(1)\n+\n+ with open(myelffile, 'rb') as file:\n+ try:\n+ readelf = ReadElf(file, sys.stdout)\n+ readelf.process_dt_needed_entries()\n+ readelf.display_pmd_info_strings(\".rodata\")\n+ sys.exit(0)\n+\n+ except ELFError as ex:\n+ sys.stderr.write('ELF error: %s\\n' % ex)\n+ sys.exit(1)\n+\n+\n+# -------------------------------------------------------------------------\n+if __name__ == '__main__':\n+ main()\n", "prefixes": [ "dpdk-dev", "PATCHv7", "5/6" ] }{ "id": 13425, "url": "