Skip to content

Commit 3ca23a2

Browse files
committed
Dpdk: 32bit test
Allow building rdma-core and dpdk as 32bit applications before test. Add the 32bit test. This is a beefy commit because we must extend the Installer class to support 32bit builds. This means adding invalid arch checks, adding arch checks to the DependencyInstaller, adding changes to PKG_CONFIG_PATH and allowing updating environment variables everywhere. The result is that we can install DPDK and RDMA core and run their 32bit versions to test basic send/receive stuff.
1 parent c3599a8 commit 3ca23a2

File tree

7 files changed

+469
-112
lines changed

7 files changed

+469
-112
lines changed

lisa/tools/meson.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Licensed under the MIT license.
33

44
from pathlib import PurePath
5-
from typing import cast
5+
from typing import Dict, Optional, cast
66

77
from semver import VersionInfo
88

@@ -50,15 +50,22 @@ def _install(self) -> bool:
5050
)
5151
return self._check_exists()
5252

53-
def setup(self, args: str, cwd: PurePath, build_dir: str = "build") -> PurePath:
53+
def setup(
54+
self,
55+
args: str,
56+
cwd: PurePath,
57+
build_dir: str = "build",
58+
update_envs: Optional[Dict[str, str]] = None,
59+
) -> PurePath:
5460
self.run(
55-
f"{args} {build_dir}",
61+
parameters=f"{args} {build_dir}",
5662
force_run=True,
5763
shell=True,
5864
cwd=cwd,
5965
expected_exit_code=0,
6066
expected_exit_code_failure_message=(
6167
f"Could not configure {str(cwd)} with meson using args {args}"
6268
),
69+
update_envs=update_envs,
6370
)
6471
return cwd.joinpath(build_dir)

microsoft/testsuites/dpdk/common.py

+122-21
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,24 @@
1414
from lisa.operating_system import Debian, Fedora, Oracle, Posix, Suse, Ubuntu
1515
from lisa.tools import Git, Lscpu, Tar, Wget
1616
from lisa.tools.lscpu import CpuArchitecture
17-
from lisa.util import UnsupportedDistroException
17+
from lisa.util import UnsupportedCpuArchitectureException, UnsupportedDistroException
1818

1919
DPDK_STABLE_GIT_REPO = "https://dpdk.org/git/dpdk-stable"
20-
20+
# 32bit test relies on newer versions of DPDK.
21+
# Release candidates are not in stable, so use the github mirror.
22+
DPDK_32BIT_DEFAULT_BRANCH = "v24.11"
23+
# MANA testing requires newer versions of DPDK.
24+
DPDK_MANA_DEFAULT_BRANCH = "v24.11"
2125
# azure routing table magic subnet prefix
2226
# signals 'route all traffic on this subnet'
2327
AZ_ROUTE_ALL_TRAFFIC = "0.0.0.0/0"
2428

29+
ARCH_COMPATIBILITY_MATRIX = {
30+
CpuArchitecture.X64: [CpuArchitecture.X64],
31+
CpuArchitecture.I386: [CpuArchitecture.I386, CpuArchitecture.X64],
32+
CpuArchitecture.ARM64: [CpuArchitecture.ARM64],
33+
}
34+
2535

2636
# Attempt to clean up the DPDK package dependency mess
2737
# Make a Installer class that implements the common steps
@@ -36,7 +46,7 @@ class OsPackageDependencies:
3646
# the packages to install on that OS.
3747
def __init__(
3848
self,
39-
matcher: Callable[[Posix], bool],
49+
matcher: Callable[[Posix, Optional[CpuArchitecture]], bool],
4050
packages: Optional[Sequence[Union[str, Tool, Type[Tool]]]] = None,
4151
stop_on_match: bool = False,
4252
) -> None:
@@ -47,14 +57,21 @@ def __init__(
4757

4858
class DependencyInstaller:
4959
# provide a list of OsPackageDependencies for a project
50-
def __init__(self, requirements: List[OsPackageDependencies]) -> None:
60+
def __init__(
61+
self,
62+
requirements: List[OsPackageDependencies],
63+
arch: Optional[CpuArchitecture] = None,
64+
) -> None:
5165
self.requirements = requirements
66+
self._arch = arch
5267

5368
# evaluate the list of package dependencies,
5469
def install_required_packages(
55-
self, node: Node, extra_args: Union[List[str], None]
70+
self,
71+
os: Posix,
72+
extra_args: Union[List[str], None],
73+
arch: Optional[CpuArchitecture] = None,
5674
) -> None:
57-
os = node.os
5875
assert isinstance(os, Posix), (
5976
"DependencyInstaller is not compatible with this OS: "
6077
f"{os.information.vendor} {os.information.release}"
@@ -63,13 +80,16 @@ def install_required_packages(
6380
# stop on list end or if exclusive_match parameter is true.
6481
packages: List[Union[str, Tool, Type[Tool]]] = []
6582
for requirement in self.requirements:
66-
if requirement.matcher(os) and requirement.packages:
67-
packages += requirement.packages
83+
if requirement.matcher(os, arch):
84+
if requirement.packages is not None and len(requirement.packages) > 0:
85+
packages += requirement.packages
6886
if requirement.stop_on_match:
6987
break
88+
7089
os.install_packages(packages=packages, extra_args=extra_args)
7190

7291
# NOTE: It is up to the caller to raise an exception on an invalid OS
92+
# see unsupported_os_thrower as a catch-all 'list end' function
7393

7494

7595
class Downloader:
@@ -201,23 +221,43 @@ def _uninstall(self) -> None:
201221
def _install_dependencies(self) -> None:
202222
if self._os_dependencies is not None:
203223
self._os_dependencies.install_required_packages(
204-
self._node, extra_args=self._package_manager_extra_args
224+
self._os, extra_args=self._package_manager_extra_args, arch=self._arch
205225
)
206226

207227
# define how to check the installed version
208228
def get_installed_version(self) -> VersionInfo:
209229
raise NotImplementedError(f"get_installed_version {self._err_msg}")
210230

211-
def _should_install(self, required_version: Optional[VersionInfo] = None) -> bool:
212-
return (not self._check_if_installed()) or (
213-
required_version is not None
214-
and required_version > self.get_installed_version()
231+
def _should_install(
232+
self,
233+
required_version: Optional[VersionInfo] = None,
234+
required_arch: Optional[CpuArchitecture] = None,
235+
) -> bool:
236+
return (
237+
(not self._check_if_installed())
238+
# NOTE: Taking advantage of longer-than-expected lifetimes here.
239+
# If the tool still exists we ~should~ be able to check the old version
240+
# from a previous test environment.
241+
# At the moment, we use create() to force re-initialization.
242+
# If we ever fix things so that we use .get,
243+
# we will need this check. So add it now.q
244+
or bool(self._arch and required_arch != self._arch)
245+
or (
246+
required_version is not None
247+
and required_version > self.get_installed_version()
248+
)
215249
)
216250

217251
# run the defined setup and installation steps.
218-
def do_installation(self, required_version: Optional[VersionInfo] = None) -> None:
252+
def do_installation(
253+
self,
254+
required_version: Optional[VersionInfo] = None,
255+
required_arch: Optional[CpuArchitecture] = None,
256+
) -> None:
219257
self._setup_node()
220-
if self._should_install():
258+
if self._should_install(
259+
required_version=required_version, required_arch=required_arch
260+
):
221261
self._uninstall()
222262
self._install_dependencies()
223263
self._install()
@@ -227,6 +267,7 @@ def __init__(
227267
node: Node,
228268
os_dependencies: Optional[DependencyInstaller] = None,
229269
downloader: Optional[Downloader] = None,
270+
arch: Optional[CpuArchitecture] = None,
230271
) -> None:
231272
self._node = node
232273
if not isinstance(self._node.os, Posix):
@@ -237,11 +278,22 @@ def __init__(
237278
self._package_manager_extra_args: List[str] = []
238279
self._os_dependencies = os_dependencies
239280
self._downloader = downloader
281+
self._arch = arch
282+
if self._arch:
283+
# avoid building/running arm64 on i386, etc
284+
system_arch = self._node.tools[Lscpu].get_architecture()
285+
if system_arch not in ARCH_COMPATIBILITY_MATRIX[self._arch]:
286+
raise UnsupportedCpuArchitectureException(system_arch)
240287

241288

242289
# Base class for package manager installation
243290
class PackageManagerInstall(Installer):
244-
def __init__(self, node: Node, os_dependencies: DependencyInstaller) -> None:
291+
def __init__(
292+
self,
293+
node: Node,
294+
os_dependencies: DependencyInstaller,
295+
arch: Optional[CpuArchitecture],
296+
) -> None:
245297
super().__init__(node, os_dependencies)
246298

247299
# uninstall from the package manager
@@ -250,7 +302,10 @@ def _uninstall(self) -> None:
250302
return
251303
if self._os_dependencies is not None:
252304
for os_package_check in self._os_dependencies.requirements:
253-
if os_package_check.matcher(self._os) and os_package_check.packages:
305+
if (
306+
os_package_check.matcher(self._os, self._arch)
307+
and os_package_check.packages
308+
):
254309
self._os.uninstall_packages(os_package_check.packages)
255310
if os_package_check.stop_on_match:
256311
break
@@ -263,7 +318,10 @@ def _check_if_installed(self) -> bool:
263318
# This will take too long if it's more than a few packages.
264319
if self._os_dependencies is not None:
265320
for os_package_check in self._os_dependencies.requirements:
266-
if os_package_check.matcher(self._os) and os_package_check.packages:
321+
if (
322+
os_package_check.matcher(self._os, self._arch)
323+
and os_package_check.packages
324+
):
267325
for pkg in os_package_check.packages:
268326
if not self._os.package_exists(pkg):
269327
return False
@@ -272,11 +330,40 @@ def _check_if_installed(self) -> bool:
272330
return True
273331

274332

275-
def force_dpdk_default_source(variables: Dict[str, Any]) -> None:
333+
# force specific default sources for arch tests (os-independent)
334+
def force_dpdk_default_source_variables(
335+
variables: Dict[str, Any], build_arch: Optional[CpuArchitecture] = None
336+
) -> None:
337+
if build_arch:
338+
variables["build_arch"] = build_arch
339+
340+
if build_arch == CpuArchitecture.I386:
341+
if not variables.get("dpdk_branch", None):
342+
# assign a default branch with needed MANA commits for 32bit test
343+
variables["dpdk_branch"] = DPDK_32BIT_DEFAULT_BRANCH
276344
if not variables.get("dpdk_source", None):
277345
variables["dpdk_source"] = DPDK_STABLE_GIT_REPO
278346

279347

348+
# force source builds for distros and environments which need a later verison.
349+
# ie. ubuntu 18.04 and MANA
350+
def set_default_dpdk_source(node: Node, variables: Dict[str, Any]) -> None:
351+
# DPDK packages 17.11 which is EOL and doesn't have the
352+
# net_vdev_netvsc pmd used for simple handling of hyper-v
353+
# guests. Force stable source build on this platform.
354+
# Default to 20.11 unless another version is provided by the
355+
# user. 20.11 is the latest dpdk version for 18.04.
356+
if isinstance(node.os, Ubuntu) and node.os.information.version < "20.4.0":
357+
variables["dpdk_source"] = variables.get("dpdk_source", DPDK_STABLE_GIT_REPO)
358+
variables["dpdk_branch"] = variables.get("dpdk_branch", "v20.11")
359+
# MANA runs need a later version of DPDK
360+
if node.nics.is_mana_device_present():
361+
variables["dpdk_source"] = variables.get("dpdk_source", DPDK_STABLE_GIT_REPO)
362+
variables["dpdk_branch"] = variables.get(
363+
"dpdk_branch", DPDK_MANA_DEFAULT_BRANCH
364+
)
365+
366+
280367
_UBUNTU_LTS_VERSIONS = ["24.4.0", "22.4.0", "20.4.0", "18.4.0"]
281368

282369

@@ -383,13 +470,27 @@ def is_url_for_git_repo(url: str) -> bool:
383470
return scheme == "git" or check_for_git_https
384471

385472

386-
def unsupported_os_thrower(os: Posix) -> bool:
473+
# utility matcher to throw an OS error type for a match.
474+
def unsupported_os_thrower(os: Posix, arch: Optional[CpuArchitecture]) -> bool:
475+
if arch:
476+
message_suffix = f"OS and Architecture ({arch})"
477+
else:
478+
message_suffix = "OS"
387479
raise UnsupportedDistroException(
388480
os,
389-
message=("Installer did not define dependencies for this os."),
481+
message=f"Installer did not define dependencies for this {message_suffix}",
390482
)
391483

392484

485+
# utility matcher to throw an OS error when i386 is not supported
486+
def i386_not_implemented_thrower(os: Posix, arch: Optional[CpuArchitecture]) -> bool:
487+
if arch and arch == CpuArchitecture.I386:
488+
raise NotImplementedError(
489+
"i386 is not implemented for this (installer,OS) combo."
490+
)
491+
return False
492+
493+
393494
def get_debian_backport_repo_args(os: Debian) -> List[str]:
394495
# ex: 'bionic-backports' or 'buster-backports'
395496
# these backport repos are available for the older OS's

microsoft/testsuites/dpdk/dpdkperf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from lisa.tools import Lscpu
2323
from lisa.tools.hugepages import HugePageSize
2424
from lisa.util import constants
25-
from microsoft.testsuites.dpdk.common import force_dpdk_default_source
25+
from microsoft.testsuites.dpdk.common import force_dpdk_default_source_variables
2626
from microsoft.testsuites.dpdk.dpdkutil import (
2727
DpdkTestResources,
2828
SkippedException,
@@ -256,7 +256,7 @@ def perf_dpdk_multi_queue_netvsc_pmd(
256256
def perf_dpdk_l3fwd_ntttcp_tcp(
257257
self, environment: Environment, log: Logger, variables: Dict[str, Any]
258258
) -> None:
259-
force_dpdk_default_source(variables)
259+
force_dpdk_default_source_variables(variables)
260260
verify_dpdk_l3fwd_ntttcp_tcp(
261261
environment,
262262
log,

0 commit comments

Comments
 (0)