Netdev List
 help / color / mirror / Atom feed
From: Cosmin Ratiu <cratiu@nvidia.com>
To: <netdev@vger.kernel.org>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Shuah Khan <shuah@kernel.org>, Simon Horman <horms@kernel.org>,
	Cosmin Ratiu <cratiu@nvidia.com>, Petr Machata <petrm@nvidia.com>,
	Breno Leitao <leitao@debian.org>, Nimrod Oren <noren@nvidia.com>,
	Gal Pressman <gal@nvidia.com>,
	Willem de Bruijn <willemb@google.com>,
	Dimitri Daskalakis <dimitri.daskalakis1@gmail.com>,
	<linux-kselftest@vger.kernel.org>
Subject: [PATCH net-next 3/3] selftests: Use a master ssh connection for remote commands
Date: Mon, 18 May 2026 12:36:53 +0300	[thread overview]
Message-ID: <20260518093653.551166-4-cratiu@nvidia.com> (raw)
In-Reply-To: <20260518093653.551166-1-cratiu@nvidia.com>

Every remote test command done via remote_ssh has to exchange ssh keys
and authenticate, paying a (sometimes significant) setup cost. This cost
is compounded when several remote commands are run in sequence, and made
even worse when the remote configuration is usually restored on defer().

Fix that by using a master ssh connection per remote host, allowing
subsequent connections to skip these steps and be almost as fast as
running those commands locally. This will reduce infrastructure usage by
these tests because they will finish much faster.

This finally implements this part of
tools/testing/selftests/drivers/net/README.rst:
"Using persistent SSH connections is strongly encouraged to avoid
the latency of SSH connection setup on every command."

Significant improvements are seen in a b2b setup involving NIS, here's
an example with the ping.py test, with remote cmd execution instrumented
with timing info:

Before (one ssh connection per remote command):
  # ./tools/testing/selftests/drivers/net/ping.py
  [...]
  remote: 0.769s  ping -c 1 -W0.5 1.0.0.1
  remote: 0.790s  ping -s 65000 -c 1 -W0.5 1.0.0.1
  remote: 0.775s  command -v -- socat
  remote: 0.784s  echo dwlelyrvaimmzirvhlfrgxtjxpxjdwcxmzj...
  remote: 1.238s  cat /proc/net/tcp*
  remote: 0.761s  ping -c 1 -W0.5 1.0.0.1
  remote: 0.753s  ping -s 65000 -c 1 -W0.5 1.0.0.1
  remote: 0.787s  echo zmhdqnnwidygdmoylhpdimcfmtgubbvygkc...
  remote: 1.034s  cat /proc/net/tcp*
  ok 1 ping.test_default_v4
  [...]
  # Totals: pass:5 fail:0 xfail:0 xpass:0 skip:2 error:0
  # Total remote cmd time: 55.416s

After (a single master ssh connection):
  # ./tools/testing/selftests/drivers/net/ping.py
  [...]
  remote: 0.017s  ping -c 1 -W0.5 1.0.0.1
  remote: 0.017s  ping -s 65000 -c 1 -W0.5 1.0.0.1
  remote: 0.016s  command -v -- socat
  remote: 0.020s  echo njbgxukbquvxqxynzyelisajhilshglkqmv...
  remote: 0.022s  cat /proc/net/tcp*
  remote: 0.017s  ping -c 1 -W0.5 1.0.0.1
  remote: 0.017s  ping -s 65000 -c 1 -W0.5 1.0.0.1
  remote: 0.020s  echo rmjpqfbfwfdtzesiqpmeljpdipiopvcfrhs...
  remote: 0.022s  cat /proc/net/tcp*
  ok 1 ping.test_default_v4
  [...]
  # Totals: pass:5 fail:0 xfail:0 xpass:0 skip:2 error:0
  # Total remote cmd time: 2.563s

So a reduction in total time spent executing remote commands from 55s to
2.5s. Similar speedups should apply across all tests using remote_ssh.

Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
---
 .../drivers/net/lib/py/remote_ssh.py          | 48 ++++++++++++++++---
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py b/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py
index 427082561d00..8f2e57ccbe2f 100644
--- a/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py
+++ b/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py
@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
 
 import os
+import shutil
 import string
 import subprocess
 import random
+import tempfile
 
 from lib.py import cmd
 
@@ -13,17 +15,50 @@ class Remote:
         self.name = name
         self.dir_path = dir_path
         self._tmpdir = None
+        self._ctl_dir = tempfile.mkdtemp(prefix="ssh-ksft-")
+        self._ctl = os.path.join(self._ctl_dir, "ctl")
+        self._ssh_opts = ["-o", "BatchMode=yes",
+                          "-o", "ConnectTimeout=20",
+                          "-o", "ControlMaster=auto",
+                          "-o", f"ControlPath={self._ctl}",
+                          "-o", "ControlPersist=30"]
+        self._ssh_base = ["ssh", "-q"] + self._ssh_opts
+        # Open the persistent connection
+        self._master_started = False
+        try:
+            r = subprocess.run(self._ssh_base + ["-fNM", self.name],
+                               stdin=subprocess.DEVNULL,
+                               stdout=subprocess.DEVNULL,
+                               stderr=subprocess.PIPE, timeout=30)
+            if r.returncode:
+                raise OSError(f"SSH master to {name} failed: {r.stderr.decode().strip()}")
+            self._master_started = True
+        finally:
+            if not self._master_started:
+                shutil.rmtree(self._ctl_dir, ignore_errors=True)
 
     def __del__(self):
-        if self._tmpdir:
-            cmd("rm -rf " + self._tmpdir, host=self)
-            self._tmpdir = None
+        try:
+            if self._tmpdir:
+                cmd("rm -rf " + self._tmpdir, host=self)
+                self._tmpdir = None
+        except Exception:
+            pass
+        try:
+            if self._master_started:
+                self._master_started = False
+                subprocess.run(self._ssh_base + ["-O", "exit", self.name],
+                               stdout=subprocess.DEVNULL,
+                               stderr=subprocess.DEVNULL, timeout=10)
+        except Exception:
+            pass
+        shutil.rmtree(self._ctl_dir, ignore_errors=True)
 
     def cmd(self, comm, pty=False):
-        args = ["ssh", "-q"]
+        args = []
         if pty:
             args += ["-tt"]
-        return subprocess.Popen(args + [self.name, comm],
+        return subprocess.Popen(self._ssh_base + args + [self.name, comm],
                                 stdin=subprocess.DEVNULL,
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
@@ -39,5 +74,6 @@ class Remote:
         if not os.path.isabs(what):
             what = os.path.abspath(self.dir_path + "/" + what)
 
-        cmd(f"scp {what} {self.name}:{file_name}")
+        cmd(["scp", "-q"] + self._ssh_opts +
+             [what, f"{self.name}:{file_name}"])
         return file_name
-- 
2.53.0


  parent reply	other threads:[~2026-05-18  9:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-18  9:36 [PATCH net-next 0/3] selftests: Use a master ssh connection for remote commands Cosmin Ratiu
2026-05-18  9:36 ` [PATCH net-next 1/3] selftests: Disable stdin for remote commands over ssh Cosmin Ratiu
2026-05-18  9:36 ` [PATCH net-next 2/3] selftests: Wrap remote command executions in PTYs Cosmin Ratiu
2026-05-18  9:36 ` Cosmin Ratiu [this message]
2026-05-19 23:08   ` [PATCH net-next 3/3] selftests: Use a master ssh connection for remote commands Jakub Kicinski

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=20260518093653.551166-4-cratiu@nvidia.com \
    --to=cratiu@nvidia.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dimitri.daskalakis1@gmail.com \
    --cc=edumazet@google.com \
    --cc=gal@nvidia.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=leitao@debian.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=noren@nvidia.com \
    --cc=pabeni@redhat.com \
    --cc=petrm@nvidia.com \
    --cc=shuah@kernel.org \
    --cc=willemb@google.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