Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
648d3b4
dpdk: testpmd multiple process argument processing
mcgov Nov 12, 2025
9d71393
multiple process testpmd work
mcgov Nov 13, 2025
c9561bb
black and mypy
mcgov Feb 10, 2026
a3bb951
rebased to main
mcgov Feb 10, 2026
a0cb2ba
dpdk: testpmd multiple process argument processing
mcgov Nov 12, 2025
48a21ca
DPDK: five tuple swap test
mcgov Jan 21, 2026
7818958
dpdk: annotate pps number in result
mcgov Jan 28, 2026
9fcfed6
black
mcgov Jan 28, 2026
87fabbb
must check none type
mcgov Jan 28, 2026
32b40b7
black format
mcgov Jan 28, 2026
de81c72
undo change to multiple port test
mcgov Feb 10, 2026
26992cc
black changes
mcgov Feb 10, 2026
5af1119
Apply suggestions from code review
mcgov Mar 18, 2026
6b74fb2
rename RXONLY -> RX_ONLY and fix missing f string
mcgov Mar 18, 2026
159ffa6
dpdk: pass pmd argument directly to testpmd
mcgov Mar 18, 2026
da81849
Update lisa/microsoft/testsuites/dpdk/dpdkutil.py
mcgov Mar 24, 2026
25bb6f4
Update lisa/microsoft/testsuites/dpdk/dpdkutil.py
mcgov Mar 24, 2026
4572e52
apply some copilot suggestions locally
mcgov Mar 24, 2026
4fad4b5
guard 5tswap grading for pps only
mcgov Mar 24, 2026
149cf09
unreachable error messages to make copilot happy
mcgov Mar 24, 2026
403df15
copilot handle numa and cpu layout
mcgov Mar 24, 2026
8340dc3
line wrapping
mcgov Mar 24, 2026
a7ad795
fix copilot suggestion to handle multiple process output on same node
mcgov Mar 25, 2026
aeae796
make source build the default
mcgov Apr 1, 2026
d4de1b8
default sources
mcgov Apr 1, 2026
d8d698d
centos
mcgov Apr 1, 2026
2d17de9
dpdk: deprecate ubuntu 18.04
mcgov Apr 2, 2026
23f4b99
organize imports, reduce complexity of function refactor
mcgov Apr 3, 2026
0901e01
handle failed build, bump meson version
mcgov Apr 3, 2026
9fa9164
branches on dpdk git don't include .0 default patch version
mcgov Apr 8, 2026
2c6d61e
Update lisa/tools/meson.py
mcgov Apr 8, 2026
7473d1c
set default rdma-core for distros with old rdma-core packages to forc…
mcgov Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 89 additions & 4 deletions lisa/microsoft/testsuites/dpdk/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from lisa.operating_system import Debian, Fedora, Oracle, Posix, Suse, Ubuntu
from lisa.tools import Git, Lscpu, Tar, Wget
from lisa.tools.lscpu import CpuArchitecture
from lisa.util import UnsupportedDistroException
from lisa.util import UnsupportedDistroException, parse_version

DPDK_STABLE_GIT_REPO = "https://dpdk.org/git/dpdk-stable"

Expand Down Expand Up @@ -289,7 +289,7 @@ def force_dpdk_default_source(variables: Dict[str, Any]) -> None:
variables["dpdk_source"] = DPDK_STABLE_GIT_REPO


_UBUNTU_LTS_VERSIONS = ["24.4.0", "22.4.0", "20.4.0", "18.4.0"]
_UBUNTU_LTS_VERSIONS = ["24.4.0", "22.4.0", "20.4.0"]
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is described as adding a simpler 5tswap forwarding test, but it also changes platform support behavior by removing Ubuntu 18.04 from _UBUNTU_LTS_VERSIONS and making check_dpdk_support() reject 18.4.0. If dropping 18.04 support is intentional, it should be called out in the PR description (and ideally in release notes/changelog). If not intentional, adjust the gating logic to preserve prior support.

Copilot uses AI. Check for mistakes.


# see https://ubuntu.com/about/release-cycle
Expand Down Expand Up @@ -331,9 +331,8 @@ def check_dpdk_support(node: Node) -> None:
f"is_latest_or_prerelease? ({is_ubuntu_latest_or_prerelease(node.os)})"
f" is_lts_version? ({is_ubuntu_lts_version(node.os)})"
)
# TODO: undo special casing for 18.04 when it's usage is less common
supported = (
node.os.information.version == "18.4.0"
node.os.information.version > "18.4.0"
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is described as adding a simpler 5tswap forwarding test, but it also changes platform support behavior by removing Ubuntu 18.04 from _UBUNTU_LTS_VERSIONS and making check_dpdk_support() reject 18.4.0. If dropping 18.04 support is intentional, it should be called out in the PR description (and ideally in release notes/changelog). If not intentional, adjust the gating logic to preserve prior support.

Copilot uses AI. Check for mistakes.
or is_ubuntu_latest_or_prerelease(node.os)
or is_ubuntu_lts_version(node.os)
)
Expand Down Expand Up @@ -472,3 +471,89 @@ class Pmd(str, Enum):
class DpdkGradeMetric(str, Enum):
PPS = "pps"
BPS = "bps"


class DpdkMpRole(str, Enum):
# dpdk multiprocessing allows numerous secondary processes to
# share a single primary context. Testpmd and other apps allow this
# to occur fairly transparently, but require it to be declared
# at start time. The primary process has a proc_id of '0'
# This is unfortunate, since it's the nice python default for
# integer arguments.
#
# Use this enum to differentiate between primary and secondary
# multiple process context types. There is no single process
# context type, because this argument will be passed as Optional.
# So DpdkMpRole is either None or PRIMARY | SECONDARY

PRIMARY_PROCESS = "primary"
SECONDARY_PROCESS = "secondary"


class TestpmdForwardMode(str, Enum):
# Forwarding modes for the testpmd application.
#
# txonly : generate and transmit packets without validating received
# traffic (useful for pure transmit/throughput tests).
# rxonly : receive and count packets without transmitting (useful for
# pure receive/throughput or loss measurement).
# 5tswap : swap the 5‑tuple fields between source and destination for
# each packet (IP src/dst, L4 src/dst ports, and protocol),
# exercising header rewrite paths.

TX_ONLY = "txonly"
RX_ONLY = "rxonly"
FIVE_TUPLE_SWAP = "5tswap"
Comment thread
mcgov marked this conversation as resolved.


_dpdk_default_source_dict = {
"Ubuntu": {
"20.4.0": "v25.11",
"22.4.0": "v24.11",
"24.4.0": "v24.11",
"25.4.0": "v25.11",
"26.4.0": "v25.11",
},
"Debian": {
"10.0.0": "v22.11",
"11.0.0": "v24.11",
"12.0.0": "v24.11",
"13.0.0": "v25.11",
},
"Redhat": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
"CentOs": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
}


def get_dpdk_default_source_version(node: Node) -> str:
# match major.minor os versions for supported distros
# to lkg dpdk versions for the source installation.
# Versions are evaluated at >= for the os version.

os_version = node.os.information.version
os_match = _dpdk_default_source_dict.get(node.os.name, None)
Comment on lines +510 to +540
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keying the mapping by node.os.name strings is brittle and can silently skip tests if the OS name doesn’t match these exact spellings/casing (e.g., 'CentOs' vs common variants like 'CentOS', 'RHEL', etc.). Consider keying by OS classes/types (isinstance checks), or centralizing canonical OS-name constants used across the codebase. At minimum, add a small normalization layer (e.g., lowercasing and known aliases) to make the mapping resilient.

Suggested change
"Ubuntu": {
"20.4.0": "v25.11",
"22.4.0": "v24.11",
"24.4.0": "v24.11",
"25.4.0": "v25.11",
"26.4.0": "v25.11",
},
"Debian": {
"10.0.0": "v22.11",
"11.0.0": "v24.11",
"12.0.0": "v24.11",
"13.0.0": "v25.11",
},
"Redhat": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
"CentOs": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
}
def get_dpdk_default_source_version(node: Node) -> str:
# match major.minor os versions for supported distros
# to lkg dpdk versions for the source installation.
# Versions are evaluated at >= for the os version.
os_version = node.os.information.version
os_match = _dpdk_default_source_dict.get(node.os.name, None)
"ubuntu": {
"20.4.0": "v25.11",
"22.4.0": "v24.11",
"24.4.0": "v24.11",
"25.4.0": "v25.11",
"26.4.0": "v25.11",
},
"debian": {
"10.0.0": "v22.11",
"11.0.0": "v24.11",
"12.0.0": "v24.11",
"13.0.0": "v25.11",
},
"redhat": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
"centos": {
"8.6.0": "v24.11",
"9.0.0": "v25.11",
},
}
def _normalize_dpdk_os_name(os_name: str) -> str:
normalized_name = os_name.strip().lower()
return {
"rhel": "redhat",
"red hat": "redhat",
"red hat enterprise linux": "redhat",
"redhatenterpriselinux": "redhat",
"centos": "centos",
"centos linux": "centos",
}.get(normalized_name, normalized_name)
def get_dpdk_default_source_version(node: Node) -> str:
# match major.minor os versions for supported distros
# to lkg dpdk versions for the source installation.
# Versions are evaluated at >= for the os version.
os_version = node.os.information.version
normalized_os_name = _normalize_dpdk_os_name(node.os.name)
os_match = _dpdk_default_source_dict.get(normalized_os_name, None)

Copilot uses AI. Check for mistakes.
if os_match is None:
raise UnsupportedDistroException(
node.os,
f"Unsupported distro {node.os.name}, cannot determine "
"default DPDK source version for testpmd.",
)
for version_threshold, dpdk_version in os_match.items():
if (
os_version >= version_threshold
and os_version.major == parse_version(version_threshold).major
):
return dpdk_version
Comment on lines +547 to +552
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_dpdk_default_source_version() relies on dict insertion order for threshold evaluation. If the mapping is ever edited out of order (or loaded differently), the first match may not be the best/most specific threshold within a major series. To make this robust, iterate thresholds in a deterministic sorted order (e.g., sort by parsed version descending within the same major) so the selected DPDK branch is stable and maintainers don’t need to reason about ordering side effects.

Copilot uses AI. Check for mistakes.
# if we get here, the os version is too old to have a supported dpdk version
Comment on lines +547 to +553
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This selection depends on dict insertion order to pick the intended threshold. If the dict order changes (or is refactored), an OS version could match an unintended threshold within the same major version. Consider iterating thresholds in a deterministic sorted order (by parsed version) so the chosen DPDK version is stable and clearly correct (e.g., select the highest threshold <= os_version within the same major).

Suggested change
for version_threshold, dpdk_version in os_match.items():
if (
os_version >= version_threshold
and os_version.major == parse_version(version_threshold).major
):
return dpdk_version
# if we get here, the os version is too old to have a supported dpdk version
sorted_thresholds = sorted(
os_match.items(),
key=lambda item: parse_version(item[0]),
reverse=True,
)
for version_threshold, dpdk_version in sorted_thresholds:
parsed_threshold = parse_version(version_threshold)
if (
os_version >= parsed_threshold
and os_version.major == parsed_threshold.major
):
return dpdk_version
# if we get here, the os version is too old to have a supported dpdk version

Copilot uses AI. Check for mistakes.
raise UnsupportedDistroException(
node.os,
f"Unsupported distro version {str(os_version)} for {node.os.name}. "
"Use a version >= the following versions: "
f"{', '.join(os_match.keys())}",
)
Comment thread
mcgov marked this conversation as resolved.
44 changes: 18 additions & 26 deletions lisa/microsoft/testsuites/dpdk/dpdkperf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
verify_dpdk_build,
verify_dpdk_l3fwd_ntttcp_tcp,
verify_dpdk_send_receive,
verify_dpdk_send_receive_multi_txrx_queue,
)

from lisa import (
Expand Down Expand Up @@ -168,7 +167,7 @@ def perf_dpdk_minimal_failsafe_pmd(
log: Logger,
variables: Dict[str, Any],
) -> None:
self._run_dpdk_perf_test(Pmd.FAILSAFE, result, log, variables)
self._run_dpdk_testpmd_perf_test(Pmd.FAILSAFE, result, log, variables)

@TestCaseMetadata(
description="""
Expand All @@ -189,7 +188,7 @@ def perf_dpdk_minimal_netvsc_pmd(
log: Logger,
variables: Dict[str, Any],
) -> None:
self._run_dpdk_perf_test(Pmd.NETVSC, result, log, variables)
self._run_dpdk_testpmd_perf_test(Pmd.NETVSC, result, log, variables)

@TestCaseMetadata(
description="""
Expand All @@ -211,12 +210,12 @@ def perf_dpdk_multi_queue_failsafe_pmd(
log: Logger,
variables: Dict[str, Any],
) -> None:
self._run_dpdk_perf_test(
self._run_dpdk_testpmd_perf_test(
Pmd.FAILSAFE,
result,
log,
variables,
use_queues=True,
multiple_queues=True,
)

@TestCaseMetadata(
Expand All @@ -238,12 +237,12 @@ def perf_dpdk_multi_queue_netvsc_pmd(
log: Logger,
variables: Dict[str, Any],
) -> None:
self._run_dpdk_perf_test(
self._run_dpdk_testpmd_perf_test(
Pmd.NETVSC,
result,
log,
variables,
use_queues=True,
multiple_queues=True,
)

@TestCaseMetadata(
Expand Down Expand Up @@ -280,37 +279,30 @@ def perf_dpdk_l3fwd_ntttcp_tcp(
is_perf_test=True,
)

def _run_dpdk_perf_test(
def _run_dpdk_testpmd_perf_test(
self,
pmd: Pmd,
test_result: TestResult,
log: Logger,
variables: Dict[str, Any],
use_queues: bool = False,
multiple_queues: bool = False,
hugepage_size: HugePageSize = HugePageSize.HUGE_2MB,
) -> None:
environment = test_result.environment
assert environment, "fail to get environment from testresult"

# run build + validation to populate results
self._validate_core_counts_are_equal(test_result)
try:
if use_queues:
send_kit, receive_kit = verify_dpdk_send_receive_multi_txrx_queue(
environment,
log,
variables,
pmd,
result=test_result,
)
else:
send_kit, receive_kit = verify_dpdk_send_receive(
environment,
log,
variables,
pmd,
HugePageSize.HUGE_2MB,
result=test_result,
)
send_kit, receive_kit = verify_dpdk_send_receive(
environment,
log,
variables,
pmd,
multiple_queues=multiple_queues,
hugepage_size=hugepage_size,
result=test_result,
)
except UnsupportedPackageVersionException as err:
raise SkippedException(err)

Expand Down
45 changes: 42 additions & 3 deletions lisa/microsoft/testsuites/dpdk/dpdksuite.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from microsoft.testsuites.dpdk.dpdkovs import DpdkOvs
from microsoft.testsuites.dpdk.dpdkutil import (
UIO_HV_GENERIC_SYSFS_PATH,
TestpmdForwardMode,
UnsupportedPackageVersionException,
check_send_receive_compatibility,
do_parallel_cleanup,
Expand Down Expand Up @@ -541,9 +542,9 @@ def run_testpmd_hotplug_send_test(
raise SkippedException(err)
testpmd = test_kit.testpmd
test_nic = node.nics.get_secondary_nic()
testpmd_cmd = testpmd.generate_testpmd_command([test_nic], 0, "txonly")
testpmd_cmd = testpmd.generate_testpmd_command([test_nic], 0, "txonly", pmd)
kit_cmd_pairs = {
test_kit: testpmd_cmd,
test_kit: [testpmd_cmd],
}

run_testpmd_concurrent(
Expand Down Expand Up @@ -855,7 +856,7 @@ def verify_dpdk_send_receive_multi_txrx_queue_4k_mtu_netvsc(
# allow configuring for different platforms
mtu_size = 4000
try:
snd, rcv = verify_dpdk_send_receive_multi_txrx_queue(
verify_dpdk_send_receive_multi_txrx_queue(
environment,
log,
variables,
Expand Down Expand Up @@ -1077,6 +1078,44 @@ def verify_dpdk_send_receive_gb_hugepages_netvsc(
except UnsupportedPackageVersionException as err:
raise SkippedException(err)

@TestCaseMetadata(
description="""
Tests a sender/receiver 5-tuple-swap forwarding setup
for direct netvsc pmd setup.
Sender sends the packets, receiver receives them.
We check the traffic received matches the amount sent
and received by the forwarder.
Test uses 1GB hugepages.
""",
priority=2,
requirement=simple_requirement(
min_core_count=32,
min_nic_count=2,
network_interface=Sriov(),
min_count=2,
unsupported_features=[Gpu, Infiniband],
),
)
def verify_dpdk_testpmd_5tswap_gb_hugepages_netvsc(
self,
environment: Environment,
log: Logger,
variables: Dict[str, Any],
result: TestResult,
) -> None:
try:
verify_dpdk_send_receive(
environment,
log,
variables,
Pmd.NETVSC,
HugePageSize.HUGE_1GB,
result=result,
receiver_mode=TestpmdForwardMode.FIVE_TUPLE_SWAP,
)
except UnsupportedPackageVersionException as err:
raise SkippedException(err)

@TestCaseMetadata(
description="""
Run testpmd with multiple senders to a single receiver
Expand Down
Loading
Loading