From: Jakub Kicinski <kuba@kernel.org>
To: Stanislav Fomichev <sdf.kernel@gmail.com>
Cc: netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com
Subject: Re: [RFC net-next v2 3/5] selftests: drv-net: add an iperf performance test
Date: Fri, 16 Oct 2026 10:03:37 -0700 [thread overview]
Message-ID: <20261016100337.271adfa3@kernel.org> (raw)
In-Reply-To: <20261005201115.2690830-4-sdf@fomichev.me>
On Mon, 5 Oct 2026 13:11:12 -0700 Stanislav Fomichev wrote:
> Add the drivers/net/hw/performance target. Report throughput and
> retransmits from Iperf3Runner when requested.
>
> Single-stream iperf3 throughput is flaky and can change considerably
> between back-to-back runs on the same hosts.
>
> Tested on two mlx5 hosts. Captured metric output:
>
> # # ktap-metric-policy-json: {"display_label":"Gbps","name":"throughput","regression":{"better":"higher","compare":"p50","relative_tolerance":0.05},"summarize":"p50"}
> # # ktap-metric-policy-json: {"name":"tcp.retransmits","summarize":"max"}
> # # ktap-metric-json: {"host":"local","name":"throughput","time":10.685632,"type":"scalar","value":48.561920255183196}
> # # ktap-metric-json: {"host":"remote","name":"tcp.retransmits","time":10.68565,"type":"scalar","value":0}
>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
> tools/testing/selftests/Makefile | 2 +-
> .../drivers/net/hw/performance/Makefile | 10 +++++++
> .../drivers/net/hw/performance/config | 1 +
> .../drivers/net/hw/performance/iperf.py | 27 +++++++++++++++++++
> .../drivers/net/hw/performance/settings | 1 +
> .../selftests/drivers/net/lib/py/load.py | 24 +++++++++++++++--
> 6 files changed, 62 insertions(+), 3 deletions(-)
> create mode 100644 tools/testing/selftests/drivers/net/hw/performance/Makefile
> create mode 100644 tools/testing/selftests/drivers/net/hw/performance/config
> create mode 100755 tools/testing/selftests/drivers/net/hw/performance/iperf.py
> create mode 100644 tools/testing/selftests/drivers/net/hw/performance/settings
>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index 273853937c25..7523f378e026 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -152,7 +152,7 @@ TARGETS_HOTPLUG = cpu-hotplug
> TARGETS_HOTPLUG += memory-hotplug
>
> # Networking tests want the net/lib target, include it automatically
> -ifneq ($(filter net drivers/net drivers/net/hw,$(TARGETS)),)
> +ifneq ($(filter net drivers/net drivers/net/hw drivers/net/hw/performance,$(TARGETS)),)
long strings, maybe let's s@/hw/perfromance@/perf@ ?
> ifeq ($(filter net/lib,$(TARGETS)),)
> INSTALL_DEP_TARGETS := net/lib
> endif
> diff --git a/tools/testing/selftests/drivers/net/hw/performance/Makefile b/tools/testing/selftests/drivers/net/hw/performance/Makefile
> new file mode 100644
> index 000000000000..5d53ef548306
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/performance/Makefile
> @@ -0,0 +1,10 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +TEST_PROGS := iperf.py
here..
> +TEST_INCLUDES := \
> + $(wildcard ../lib/py/*.py ../../lib/py/*.py) \
> + $(wildcard ../../../../net/lib/py/*.py) \
> + #
.. and here -
not the exact correct format for the Makefile, pls look closer
> +include ../../../../lib.mk
> diff --git a/tools/testing/selftests/drivers/net/hw/performance/config b/tools/testing/selftests/drivers/net/hw/performance/config
> new file mode 100644
> index 000000000000..6450f34933e6
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/performance/config
> @@ -0,0 +1 @@
> +CONFIG_IPV6=y
> diff --git a/tools/testing/selftests/drivers/net/hw/performance/iperf.py b/tools/testing/selftests/drivers/net/hw/performance/iperf.py
> new file mode 100755
> index 000000000000..415fb67f4100
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/performance/iperf.py
> @@ -0,0 +1,27 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0
> +
> +"""Measure TCP throughput with iperf3."""
> +
> +from os import path
> +import sys
> +
> +sys.path.insert(0, path.join(path.dirname(path.abspath(__file__)), ".."))
Nasty hacks. Something is not laid out right, mister.
> +from lib.py import Iperf3Runner, NetDrvEpEnv, ksft_exit, ksft_run
> +
> +
> +def tcp(cfg):
> + """Measure TCP throughput."""
> + Iperf3Runner(cfg).measure_bandwidth(report=True)
> +
> +
> +def main():
> + """Run the iperf performance test."""
> + with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
> + ksft_run([tcp], args=(cfg,))
> + ksft_exit()
> +
> +
> +if __name__ == "__main__":
> + main()
> diff --git a/tools/testing/selftests/drivers/net/hw/performance/settings b/tools/testing/selftests/drivers/net/hw/performance/settings
> new file mode 100644
> index 000000000000..e7b9417537fb
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/hw/performance/settings
> @@ -0,0 +1 @@
> +timeout=0
> diff --git a/tools/testing/selftests/drivers/net/lib/py/load.py b/tools/testing/selftests/drivers/net/lib/py/load.py
> index e24660e5c27f..a7da025b4e21 100644
> --- a/tools/testing/selftests/drivers/net/lib/py/load.py
> +++ b/tools/testing/selftests/drivers/net/lib/py/load.py
> @@ -4,7 +4,8 @@ import re
> import time
> import json
>
> -from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen
> +from lib.py import cmd, ip, ksft_metric, ksft_metric_policy, ksft_pr, \
> + rand_port, wait_port_listen
>
>
> class Iperf3Runner:
> @@ -53,12 +54,20 @@ from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen
> kwargs["timeout"] = duration + 5
> return cmd(cmdline, **kwargs)
>
> - def measure_bandwidth(self, reverse=False):
> + def measure_bandwidth(self, reverse=False, report=False):
> """
> Runs an iperf3 measurement and returns the average bandwidth (Gbps).
> Discards the first and last few reporting intervals and uses only the
> middle part of the run where throughput is typically stable.
> """
> + if report:
> + ksft_metric_policy(
> + "throughput", summarize="p50",
> + regression={"compare": "p50", "better": "higher",
> + "relative_tolerance": 0.05},
> + display_label="Gbps")
> + ksft_metric_policy("tcp.retransmits", summarize="max")
> +
> self.start_server()
> result = self.start_client(duration=10, reverse=reverse)
>
> @@ -77,6 +86,17 @@ from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen
> stable = samples[3:-3]
>
> avg = sum(stable) / len(stable)
> + retransmits = out.get("end", {}).get("sum_sent", {}).get(
> + "retransmits")
> + if report:
> + if not isinstance(retransmits, int) or \
> + isinstance(retransmits, bool):
> + raise ValueError("iperf3 did not report TCP retransmits")
> + receiver = "remote" if reverse else "local"
> + sender = "local" if reverse else "remote"
> + ksft_metric("throughput", avg, kind="scalar", host=receiver)
> + ksft_metric("tcp.retransmits", retransmits, kind="scalar",
> + host=sender)
I'd be tempted to find a way to pass a callback to the class
for result reporting rather than teach the class how to report.
But just a thought, not sure which ends up being cleaner.
next prev parent reply other threads:[~2026-10-16 17:03 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 20:11 [RFC net-next v2 0/5] selftests: net: add performance metric reporting Stanislav Fomichev
2026-10-05 20:11 ` [RFC net-next v2 1/5] selftests: net: py: add timestamped metric output Stanislav Fomichev
2026-10-16 16:52 ` Jakub Kicinski
2026-10-05 20:11 ` [RFC net-next v2 2/5] selftests: net: py: add metric policy output Stanislav Fomichev
2026-10-16 16:59 ` Jakub Kicinski
2026-10-05 20:11 ` [RFC net-next v2 3/5] selftests: drv-net: add an iperf performance test Stanislav Fomichev
2026-10-16 17:03 ` Jakub Kicinski [this message]
2026-10-05 20:11 ` [RFC net-next v2 4/5] selftests: drv-net: add a kperf runner Stanislav Fomichev
2026-10-16 17:05 ` Jakub Kicinski
2026-10-05 20:11 ` [RFC net-next v2 5/5] selftests: drv-net: measure devmem performance with kperf Stanislav Fomichev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261016100337.271adfa3@kernel.org \
--to=kuba@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf.kernel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox