Netdev List
 help / color / mirror / Atom feed
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.

  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