From 1738c931ab93816007b5434c17d46842e488424a Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Tue, 6 Feb 2018 10:34:33 +0000 Subject: Improve SampleVNF hugepages setup The goal of this function is to: - Read the default hugepage size. - Set 16GB of hugepages. - Check if the status of the last action. According to [1], the default hugepage size could be read in "/proc/meminfo", always in kB. Then "/proc/sys/vm/nr_hugepages" could be used to set the number of default hugepages. [1] https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt JIRA: YARDSTICK-997 Change-Id: I762d1b16294ba1c1c2feee56610819ac358c7410 Signed-off-by: Rodolfo Alonso Hernandez --- yardstick/common/utils.py | 15 +++++++++++ .../network_services/vnf_generic/vnf/sample_vnf.py | 30 ++++++++++++---------- yardstick/tests/unit/common/test_utils.py | 30 ++++++++++++++++++---- 3 files changed, 56 insertions(+), 19 deletions(-) (limited to 'yardstick') diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index 8604e900f..495290122 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -22,6 +22,7 @@ import ipaddress import logging import os import random +import re import socket import subprocess import sys @@ -395,3 +396,17 @@ class Timer(object): def __getattr__(self, item): return getattr(self.delta, item) + + +def read_meminfo(ssh_client): + """Read "/proc/meminfo" file and parse all keys and values""" + + cpuinfo = six.BytesIO() + ssh_client.get_file_obj('/proc/meminfo', cpuinfo) + lines = cpuinfo.getvalue().decode('utf-8') + matches = re.findall(r"([\w\(\)]+):\s+(\d+)( kB)*", lines) + output = {} + for match in matches: + output[match[0]] = match[1] + + return output diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py index fbaaa0ca8..18b4f0b12 100644 --- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py +++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py @@ -19,16 +19,19 @@ from multiprocessing import Queue, Value, Process import os import posixpath import re -from six.moves import cStringIO import subprocess import time +import six +from six.moves import cStringIO + from trex_stl_lib.trex_stl_client import LoggerApi from trex_stl_lib.trex_stl_client import STLClient from trex_stl_lib.trex_stl_exceptions import STLError from yardstick.benchmark.contexts.base import Context from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file from yardstick.common import exceptions as y_exceptions +from yardstick.common import utils from yardstick.common.process import check_if_process_failed from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper from yardstick.network_services.helpers.samplevnf_helper import PortPairs @@ -119,6 +122,8 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): APP_NAME = 'DpdkVnf' FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'" + NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages' + HUGEPAGES_KB = 1024 * 1024 * 16 @staticmethod def _update_packet_type(ip_pipeline_cfg, traffic_options): @@ -155,19 +160,16 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper): self.dpdk_bind_helper = DpdkBindHelper(ssh_helper) def _setup_hugepages(self): - cmd = "awk '/Hugepagesize/ { print $2$3 }' < /proc/meminfo" - hugepages = self.ssh_helper.execute(cmd)[1].rstrip() - - memory_path = \ - '/sys/kernel/mm/hugepages/hugepages-%s/nr_hugepages' % hugepages - self.ssh_helper.execute("awk -F: '{ print $1 }' < %s" % memory_path) - - if hugepages == "2048kB": - pages = 8192 - else: - pages = 16 - - self.ssh_helper.execute("echo %s | sudo tee %s" % (pages, memory_path)) + meminfo = utils.read_meminfo(self.ssh_helper) + hp_size_kb = int(meminfo['Hugepagesize']) + nr_hugepages = int(abs(self.HUGEPAGES_KB / hp_size_kb)) + self.ssh_helper.execute('echo %s | sudo tee %s' % + (nr_hugepages, self.NR_HUGEPAGES_PATH)) + hp = six.BytesIO() + self.ssh_helper.get_file_obj(self.NR_HUGEPAGES_PATH, hp) + nr_hugepages_set = int(hp.getvalue().decode('utf-8').splitlines()[0]) + LOG.info('Hugepages size (kB): %s, number claimed: %s, number set: %s', + hp_size_kb, nr_hugepages, nr_hugepages_set) def build_config(self): vnf_cfg = self.scenario_helper.vnf_cfg diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py index 033bb0243..b4907addc 100644 --- a/yardstick/tests/unit/common/test_utils.py +++ b/yardstick/tests/unit/common/test_utils.py @@ -19,6 +19,7 @@ from six.moves import configparser import unittest import yardstick +from yardstick import ssh from yardstick.common import utils from yardstick.common import constants @@ -1075,8 +1076,27 @@ class SafeDecodeUtf8TestCase(unittest.TestCase): self.assertEqual('this is a byte array', out) -def main(): - unittest.main() - -if __name__ == '__main__': - main() +class ReadMeminfoTestCase(unittest.TestCase): + + MEMINFO = (b'MemTotal: 65860500 kB\n' + b'MemFree: 28690900 kB\n' + b'MemAvailable: 52873764 kB\n' + b'Active(anon): 3015676 kB\n' + b'HugePages_Total: 8\n' + b'Hugepagesize: 1048576 kB') + MEMINFO_DICT = {'MemTotal': '65860500', + 'MemFree': '28690900', + 'MemAvailable': '52873764', + 'Active(anon)': '3015676', + 'HugePages_Total': '8', + 'Hugepagesize': '1048576'} + + def test_read_meminfo(self): + ssh_client = ssh.SSH('user', 'host') + with mock.patch.object(ssh_client, 'get_file_obj') as \ + mock_get_client, \ + mock.patch.object(six, 'BytesIO', + return_value=six.BytesIO(self.MEMINFO)): + output = utils.read_meminfo(ssh_client) + mock_get_client.assert_called_once_with('/proc/meminfo', mock.ANY) + self.assertEqual(self.MEMINFO_DICT, output) -- cgit 1.2.3-korg