From patchwork Thu Nov 15 15:47:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Burakov, Anatoly" X-Patchwork-Id: 48128 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A2F25532C; Thu, 15 Nov 2018 16:47:34 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 5F8F04CAD for ; Thu, 15 Nov 2018 16:47:25 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Nov 2018 07:47:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,236,1539673200"; d="scan'208";a="89543721" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga007.jf.intel.com with ESMTP; 15 Nov 2018 07:47:22 -0800 Received: from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com [10.237.217.45]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id wAFFlLUx024795; Thu, 15 Nov 2018 15:47:21 GMT Received: from sivswdev01.ir.intel.com (localhost [127.0.0.1]) by sivswdev01.ir.intel.com with ESMTP id wAFFlLIc028107; Thu, 15 Nov 2018 15:47:21 GMT Received: (from aburakov@localhost) by sivswdev01.ir.intel.com with LOCAL id wAFFlLfS028103; Thu, 15 Nov 2018 15:47:21 GMT From: Anatoly Burakov To: dev@dpdk.org Cc: john.mcnamara@intel.com, bruce.richardson@intel.com, pablo.de.lara.guarch@intel.com, david.hunt@intel.com, mohammad.abdul.awal@intel.com, thomas@monjalon.net, ferruh.yigit@intel.com Date: Thu, 15 Nov 2018 15:47:14 +0000 Message-Id: <3b48e558478fdad1e9e6a8e58f723734be79ae21.1542291869.git.anatoly.burakov@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [RFC v2 2/9] usertools/lib: add platform info library X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add a library that will parse system information: * NUMA nodes * Cores and threads * Mapping from NUMA node and core to thread id's * Hyperthreading support status * RAM size * Default hugepage size as reported by kernel This can be used by scripts. Signed-off-by: Anatoly Burakov --- usertools/DPDKConfigLib/PlatformInfo.py | 130 ++++++++++++++++++++++++ usertools/DPDKConfigLib/Util.py | 16 +++ 2 files changed, 146 insertions(+) create mode 100755 usertools/DPDKConfigLib/PlatformInfo.py create mode 100755 usertools/DPDKConfigLib/Util.py diff --git a/usertools/DPDKConfigLib/PlatformInfo.py b/usertools/DPDKConfigLib/PlatformInfo.py new file mode 100755 index 000000000..734d22026 --- /dev/null +++ b/usertools/DPDKConfigLib/PlatformInfo.py @@ -0,0 +1,130 @@ +#!/usr/bin/python +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + + +from .Util import * +import re +import glob + +__SYSFS_CPU_INFO_PATH = "/sys/devices/system/cpu" +__SYSFS_IOMMU_CLASS_PATH = "/sys/class/iommu" +__KERNEL_HPSZ_PATH = "/sys/kernel/mm/hugepages/hugepages-*" + +try: + xrange # python 2 +except NameError: + xrange = range # python 3 + + +__CPU_FLAGS_TO_HP_SIZE = { + # x86 supports 2M and 1G pages + "pse": 2048, + "pdpe1gb": 1048576 +} +__IOMMU_CPU_FLAGS = ["vmx", "vms"] + +__HT_CPU_FLAGS = ["ht"] + + +def _parse_cpuinfo(pinfo): + core_info_list = [] + with open("/proc/cpuinfo") as f: + cur_core = {} + for line in f: + line = line.strip() + # if we've reached end of current core info, store it and clear it + if line == "": + core_info_list.append(cur_core) + cur_core = {} + continue + key, value = kv_split(line, ":") + cur_core[key] = value + # parse flags - they're the same for all CPU's so only parse the first one + flags = set(core_info_list[0]["flags"].split()) + for flag in flags: + if flag in __CPU_FLAGS_TO_HP_SIZE: + pinfo.hugepage_sizes_supported.append(__CPU_FLAGS_TO_HP_SIZE[flag]) + elif flag in __IOMMU_CPU_FLAGS: + pinfo.iommu_supported = True + elif flag in __HT_CPU_FLAGS: + pinfo.hyperthreading_supported = True + + # parse cores and sockets + numa_nodes = set() + core_map = {} + for core_dict in core_info_list: + thread_id = int(core_dict["processor"]) + core_id = int(core_dict["core id"]) + numa_node = int(core_dict["physical id"]) + + core_map.setdefault((numa_node, core_id), []).append(thread_id) + numa_nodes.add(numa_node) + + # now, populate PlatformInfo with our, well, info - convert to lists + pinfo.numa_nodes = list(numa_nodes) + pinfo.core_map = core_map + + +def _parse_meminfo(pinfo): + meminfo_data = {} + with open("/proc/meminfo") as f: + for line in f: + key, value = kv_split(line, ":") + meminfo_data[key] = value + + # regex used to capture kilobytes + r = re.compile("(\d+) kB") + + # total ram size + m = r.match(meminfo_data["MemTotal"]) + if not m: + raise RuntimeError("BUG: Bad regular expression") + pinfo.ram_size = int(m.group(1)) + + # hugepages may not be supported + if "Hugepagesize" in meminfo_data: + m = r.match(meminfo_data["Hugepagesize"]) + if not m: + raise RuntimeError("BUG: Bad regular expression") + pinfo.default_hugepage_size = int(m.group(1)) + + +def _find_enabled_hugepage_sizes(): + paths = glob.glob(__KERNEL_HPSZ_PATH) + r = re.compile("hugepages-(\d+)kB") + sizes = [] + for p in paths: + p = os.path.basename(p) + m = r.search(p) + if not m: + raise RuntimeError("BUG: Bad regular expression") + sizes.append(int(m.group(1))) + return sizes + + +def _iommu_is_enabled(): + pass + + +class PlatformInfo: + def __init__(self): + self.update() + + def reset(self): + self.numa_nodes = [] + self.hyperthreading_supported = False + self.core_map = {} # numa_node, core_id: [thread_id] + self.iommu_supported = False + self.iommu_mode = "" + self.bootloader_iommu_mode = "" + self.hugepage_sizes_supported = [] + self.hugepage_sizes_enabled = [] + self.default_hugepage_size = 0 + self.ram_size = 0 + + def update(self): + self.reset() + _parse_cpuinfo(self) + _parse_meminfo(self) + self.hugepage_sizes_enabled = _find_enabled_hugepage_sizes() diff --git a/usertools/DPDKConfigLib/Util.py b/usertools/DPDKConfigLib/Util.py new file mode 100755 index 000000000..42434e728 --- /dev/null +++ b/usertools/DPDKConfigLib/Util.py @@ -0,0 +1,16 @@ +#!/usr/bin/python +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# split line into key-value pair, cleaning up the values in the process +def kv_split(line, separator): + # just in case + line = line.strip() + + tokens = line.split(separator, 1) + key, value = None, None + if len(tokens) > 0: + key = tokens[0].strip() + if len(tokens) > 1: + value = tokens[1].strip() + return key, value