This enables FreeBSD support for PlatformInfo part of the DPDKConfigLib script, thereby enabling FreeBSD support for the cpu_layout script.
Signed-off-by: Anatoly Burakov <anatoly.bura...@intel.com> --- usertools/DPDKConfigLib/PlatformInfo.py | 81 ++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/usertools/DPDKConfigLib/PlatformInfo.py b/usertools/DPDKConfigLib/PlatformInfo.py index 734d22026..4ca507a37 100755 --- a/usertools/DPDKConfigLib/PlatformInfo.py +++ b/usertools/DPDKConfigLib/PlatformInfo.py @@ -6,6 +6,15 @@ from .Util import * import re import glob +import platform +import subprocess +import string +import xml.etree.ElementTree # for FreeBSD topology parsing +try: + import queue # python 3 +except ImportError: + import Queue as queue # python 2 + __SYSFS_CPU_INFO_PATH = "/sys/devices/system/cpu" __SYSFS_IOMMU_CLASS_PATH = "/sys/class/iommu" @@ -26,6 +35,9 @@ __HT_CPU_FLAGS = ["ht"] +__SYSCTL_TOPOLOGY_CMDLINE = ['sysctl', '-b', 'kern.sched.topology_spec'] +__SYSCTL_MEM_CMDLINE = ['sysctl', 'hw.realmem'] + def _parse_cpuinfo(pinfo): core_info_list = [] @@ -107,6 +119,56 @@ def _iommu_is_enabled(): pass +def _parse_sysctl_cpu_topology(pinfo): + output = subprocess.check_output(__SYSCTL_TOPOLOGY_CMDLINE) + + # output from sysctl contains null terminator, remove it + raw_xml = output[:-1] + tree = xml.etree.ElementTree.fromstring(raw_xml) + groups = queue.Queue() + + # put first group onto the queue + for e in tree.findall('group'): + groups.put(e) + + # per-level list of cores + levels = {} + + while not groups.empty(): + group = groups.get() + level = int(group.get('level')) + cpus = [int(cpu) for cpu in group.find('cpu').text.split(",")] + cur_value = levels.setdefault(level, []) + + # store discovered cpu's + cur_value.append(cpus) + levels[level] = cur_value + + children = group.find('children') + if children is not None: + for c in children.findall('group'): + groups.put(c) + + # find deepest level + max_level = max(levels.keys()) + + # for each group in the deepest level, take first CPU and make it physical + # core id + for cpus in levels[max_level]: + pinfo.core_map[pinfo.numa_nodes[0], cpus[0]] = cpus + + # also make note of hyperthreading + if len(cpus) > 1: + pinfo.hyperthreading_supported = True + + +def _parse_sysctl_ram_size(): + output = subprocess.check_output(__SYSCTL_MEM_CMDLINE) + _, mem_str = kv_split(output, ':') + mem_amount = int(mem_str) / 1024 # kilobytes + return mem_amount + + class PlatformInfo: def __init__(self): self.update() @@ -125,6 +187,19 @@ def reset(self): def update(self): self.reset() - _parse_cpuinfo(self) - _parse_meminfo(self) - self.hugepage_sizes_enabled = _find_enabled_hugepage_sizes() + system = platform.system() + if system == 'Linux': + _parse_cpuinfo(self) + _parse_meminfo(self) + self.hugepage_sizes_enabled = _find_enabled_hugepage_sizes() + elif system == 'FreeBSD': + # DPDK doesn't support NUMA on FreeBSD + self.numa_nodes = [0] + # find number of threads + _parse_sysctl_cpu_topology(self) + # find RAM size + self.ram_size = _parse_sysctl_ram_size() + # DPDK doesn't use hugepages on FreeBSD + self.hugepage_sizes_supported = [] + self.hugepage_sizes_enabled = [] + self.default_hugepage_size = 0 -- 2.17.1