@@ -131,7 +131,11 @@ There are two areas that need to be set up on a System Under Test:
You may specify the optional hugepage configuration in the DTS config file.
If you do, DTS will take care of configuring hugepages,
- overwriting your current SUT hugepage configuration.
+ overwriting your current SUT hugepage configuration. Configuration of hugepages via DTS
+ allows only for allocation of 2MB hugepages, as doing so prevents accidental/over
+ allocation of hugepage sizes not recommended during runtime due to
+ contiguous memory space requirements. Thus, if you require hugepage
+ sizes not equal to 2MB, then this configuration must be done outside of the DTS framework.
* System under test configuration
@@ -35,7 +35,7 @@ nodes:
lcores: "" # use all the available logical cores
use_first_core: false # tells DPDK to use any physical core
memory_channels: 4 # tells DPDK to use 4 memory channels
- hugepages: # optional; if removed, will use system hugepage configuration
+ hugepages_2mb: # optional; if removed, will use system hugepage configuration
amount: 256
force_first_numa: false
ports:
@@ -71,7 +71,7 @@ nodes:
os_driver: rdma
peer_node: "SUT 1"
peer_pci: "0000:00:08.1"
- hugepages: # optional; if removed, will use system hugepage configuration
+ hugepages_2mb: # optional; if removed, will use system hugepage configuration
amount: 256
force_first_numa: false
traffic_generator:
@@ -255,8 +255,8 @@ def from_dict(
Either an SUT or TG configuration instance.
"""
hugepage_config = None
- if "hugepages" in d:
- hugepage_config_dict = d["hugepages"]
+ if "hugepages_2mb" in d:
+ hugepage_config_dict = d["hugepages_2mb"]
if "force_first_numa" not in hugepage_config_dict:
hugepage_config_dict["force_first_numa"] = False
hugepage_config = HugepageConfiguration(**hugepage_config_dict)
@@ -146,7 +146,7 @@
"compiler"
]
},
- "hugepages": {
+ "hugepages_2mb": {
"type": "object",
"description": "Optional hugepage configuration. If not specified, hugepages won't be configured and DTS will use system configuration.",
"properties": {
@@ -253,8 +253,8 @@
"type": "integer",
"description": "How many memory channels to use. Optional, defaults to 1."
},
- "hugepages": {
- "$ref": "#/definitions/hugepages"
+ "hugepages_2mb": {
+ "$ref": "#/definitions/hugepages_2mb"
},
"ports": {
"type": "array",
@@ -46,7 +46,7 @@ class NodeConfigDict(TypedDict):
"""Allowed keys and values."""
#:
- hugepages: HugepageConfigurationDict
+ hugepages_2mb: HugepageConfigurationDict
#:
name: str
#:
@@ -15,7 +15,7 @@
from typing_extensions import NotRequired
-from framework.exception import RemoteCommandExecutionError
+from framework.exception import ConfigurationError, RemoteCommandExecutionError
from framework.utils import expand_range
from .cpu import LogicalCore
@@ -84,14 +84,20 @@ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
"""Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
return dpdk_prefix
- def setup_hugepages(self, hugepage_count: int, force_first_numa: bool) -> None:
+ def setup_hugepages(
+ self, hugepage_count: int, hugepage_size: int, force_first_numa: bool
+ ) -> None:
"""Overrides :meth:`~.os_session.OSSession.setup_hugepages`."""
self._logger.info("Getting Hugepage information.")
- hugepage_size = self._get_hugepage_size()
- hugepages_total = self._get_hugepages_total()
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
self._numa_nodes = self._get_numa_nodes()
- if force_first_numa or hugepages_total != hugepage_count:
+ if force_first_numa or hugepages_total < hugepage_count:
# when forcing numa, we need to clear existing hugepages regardless
# of size, so they can be moved to the first numa node
self._configure_huge_pages(hugepage_count, hugepage_size, force_first_numa)
@@ -99,13 +105,9 @@ def setup_hugepages(self, hugepage_count: int, force_first_numa: bool) -> None:
self._logger.info("Hugepages already configured.")
self._mount_huge_pages()
- def _get_hugepage_size(self) -> int:
- hugepage_size = self.send_command("awk '/Hugepagesize/ {print $2}' /proc/meminfo").stdout
- return int(hugepage_size)
-
- def _get_hugepages_total(self) -> int:
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
hugepages_total = self.send_command(
- "awk '/HugePages_Total/ { print $2 }' /proc/meminfo"
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
).stdout
return int(hugepages_total)
@@ -266,7 +266,9 @@ def _setup_hugepages(self) -> None:
"""
if self.config.hugepages:
self.main_session.setup_hugepages(
- self.config.hugepages.amount, self.config.hugepages.force_first_numa
+ self.config.hugepages.amount,
+ self.main_session.hugepage_size,
+ self.config.hugepages.force_first_numa,
)
def configure_port_state(self, port: Port, enable: bool = True) -> None:
@@ -64,6 +64,7 @@ class OSSession(ABC):
_logger: DTSLogger
remote_session: RemoteSession
interactive_session: InteractiveRemoteSession
+ hugepage_size: int
def __init__(
self,
@@ -80,6 +81,7 @@ def __init__(
name: The name of the session.
logger: The logger instance this session will use.
"""
+ self.hugepage_size = 2048
self._config = node_config
self.name = name
self._logger = logger
@@ -345,7 +347,9 @@ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
"""
@abstractmethod
- def setup_hugepages(self, hugepage_count: int, force_first_numa: bool) -> None:
+ def setup_hugepages(
+ self, hugepage_count: int, hugepage_size: int, force_first_numa: bool
+ ) -> None:
"""Configure hugepages on the node.
Get the node's Hugepage Size, configure the specified count of hugepages
@@ -353,6 +357,7 @@ def setup_hugepages(self, hugepage_count: int, force_first_numa: bool) -> None:
Args:
hugepage_count: Configure this many hugepages.
+ hugepage_size: Configure hugepages of this size.
force_first_numa: If :data:`True`, configure hugepages just on the first numa node.
"""