From: Bobby Eshleman <bobbyeshleman@gmail.com>
To: 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>, Simon Horman <horms@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Alex Shi <alexs@kernel.org>, Yanteng Si <si.yanteng@linux.dev>,
Dongliang Mu <dzm91@hust.edu.cn>,
Michael Chan <michael.chan@broadcom.com>,
Pavan Chebbi <pavan.chebbi@broadcom.com>,
Joshua Washington <joshwash@google.com>,
Harshitha Ramamurthy <hramamurthy@google.com>,
Saeed Mahameed <saeedm@nvidia.com>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Alexander Duyck <alexanderduyck@fb.com>,
kernel-team@meta.com, Daniel Borkmann <daniel@iogearbox.net>,
Nikolay Aleksandrov <razor@blackwall.org>,
Shuah Khan <shuah@kernel.org>,
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>, Simon Horman <horms@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Alex Shi <alexs@kernel.org>, Yanteng Si <si.yanteng@linux.dev>,
Dongliang Mu <dzm91@hust.edu.cn>,
Michael Chan <michael.chan@broadcom.com>,
Pavan Chebbi <pavan.chebbi@broadcom.com>,
Joshua Washington <joshwash@google.com>,
Harshitha Ramamurthy <hramamurthy@google.com>,
Saeed Mahameed <saeedm@nvidia.com>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Alexander Duyck <alexanderduyck@fb.com>,
kernel-team@meta.com, Daniel Borkmann <daniel@iogearbox.net>,
Nikolay Aleksandrov <razor@blackwall.org>,
Shuah Khan <shuah@kernel.org>
Cc: dw@davidwei.uk, sdf.kernel@gmail.com, mohsin.bashr@gmail.com,
willemb@google.com, jiang.kun2@zte.com.cn, xu.xin16@zte.com.cn,
wang.yaxin@zte.com.cn, netdev@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-rdma@vger.kernel.org, bpf@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Stanislav Fomichev <sdf@fomichev.me>,
Mina Almasry <almasrymina@google.com>,
netdev@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
bpf@vger.kernel.org, linux-kselftest@vger.kernel.org,
Bobby Eshleman <bobbyeshleman@meta.com>
Subject: [PATCH net-next v3 6/8] selftests: drv-net: refactor devmem command builders into lib module
Date: Thu, 07 May 2026 19:27:51 -0700 [thread overview]
Message-ID: <20260507-tcp-dm-netkit-v3-6-52821445867c@meta.com> (raw)
In-Reply-To: <20260507-tcp-dm-netkit-v3-0-52821445867c@meta.com>
From: Bobby Eshleman <bobbyeshleman@meta.com>
Adding netkit-based devmem tests is a straight-forward copy of devmem
test commands plus some args for the nk cases, so this patch breaks out
these command builders into helpers used by both.
Though we tried to avoid libraries to avoid increasing the barrier of
entry/complexity (see selftests/drivers/net/README.md, section "Avoid
libraries and frameworks"), factoring out these functions seemed like
the lesser of two evils in this case of using the same commands, just
with slightly different args per environment.
I experimented with just having all of the tests in the same file to
avoid having helpers in a library file, but because ksft_run() is
limited to a single call per file, and the new tests will require
different environments (NetDrvContEnv/NetDrvEpEnv), it would have been
necessary to have each test set up its own environment instead of
sharing one for the entire ksft_run() run. This came at the cost of
ballooning the test time (from under 5s to 30s on my test system), so to
strike a balance these tests were placed in separate files so they could
keep a shared environment across a single ksft_run() run shared across
all tests using the same env type (introduced in subsequent patches).
The helpers work transparently with both plain and netkit environments
by inspecting cfg for netkit-specific attributes (netns, nk_queue,
etc...).
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Changes in v4:
- Make socat_send() always bind the source; drop its bind= parameter
and the matching bind=not_ns at the run_rx call site.
- Drop socat_send()'s nodelay= arg; have buf_size>0 imply TCP_NODELAY
since they are only meaningful together.
- configure_nic(): stash originals on cfg instead of using defer(); add
paired cleanup_nic() helper. Drop the per-test configure_nic() calls
from run_rx/run_tx/run_tx_chunks/run_rx_hds; the netkit test file
invokes configure_nic/cleanup_nic once around ksft_run().
- make cfg.devmem_supported and cfg.devmem_probed public attrs (no '_')
for sake of linting
- general cleanup of the code, linting fixes
Changes in v3:
- In setup_test, drop the unused cfg.listen_ns = getattr(cfg, 'netns',
None) assignment.
- In run_rx, pass flow_steer=not_ns to ncdevmem_rx and bind=not_ns to
socat_send to avoid changing functionality (we want just a straight
refactor here)
Changes in v2:
- Move require_devmem() into individual test functions so KsftSkipEx goes up to
ksft_run() (Sashiko)
- in ncdevmem_rx(), move -v 7 to take effect for both netns and
non-netns when verify=True
---
tools/testing/selftests/drivers/net/hw/devmem.py | 77 ++------
.../selftests/drivers/net/hw/lib/py/devmem.py | 218 +++++++++++++++++++++
2 files changed, 231 insertions(+), 64 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/devmem.py b/tools/testing/selftests/drivers/net/hw/devmem.py
index ee863e90d1e0..dbc1e6a27b6a 100755
--- a/tools/testing/selftests/drivers/net/hw/devmem.py
+++ b/tools/testing/selftests/drivers/net/hw/devmem.py
@@ -2,91 +2,40 @@
# SPDX-License-Identifier: GPL-2.0
from os import path
-from lib.py import ksft_run, ksft_exit
-from lib.py import ksft_eq, KsftSkipEx
+from lib.py import ksft_run, ksft_exit, ksft_disruptive
from lib.py import NetDrvEpEnv
-from lib.py import bkg, cmd, rand_port, wait_port_listen
-from lib.py import ksft_disruptive
-
-
-def require_devmem(cfg):
- if not hasattr(cfg, "_devmem_probed"):
- probe_command = f"{cfg.bin_local} -f {cfg.ifname}"
- cfg._devmem_supported = cmd(probe_command, fail=False, shell=True).ret == 0
- cfg._devmem_probed = True
-
- if not cfg._devmem_supported:
- raise KsftSkipEx("Test requires devmem support")
+from lib.py.devmem import setup_test, run_rx, run_tx, run_tx_chunks, run_rx_hds
@ksft_disruptive
def check_rx(cfg) -> None:
- require_devmem(cfg)
-
- port = rand_port()
- socat = f"socat -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{port},bind={cfg.remote_baddr}:{port}"
- listen_cmd = f"{cfg.bin_local} -l -f {cfg.ifname} -s {cfg.addr} -p {port} -c {cfg.remote_addr} -v 7"
-
- with bkg(listen_cmd, exit_wait=True) as ncdevmem:
- wait_port_listen(port)
- cmd(f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | \
- head -c 1K | {socat}", host=cfg.remote, shell=True)
-
- ksft_eq(ncdevmem.ret, 0)
+ """Run the devmem RX test."""
+ run_rx(cfg)
@ksft_disruptive
def check_tx(cfg) -> None:
- require_devmem(cfg)
-
- port = rand_port()
- listen_cmd = f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}"
-
- with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
- wait_port_listen(port, host=cfg.remote)
- cmd(f"echo -e \"hello\\nworld\"| {cfg.bin_local} -f {cfg.ifname} -s {cfg.remote_addr} -p {port}", shell=True)
-
- ksft_eq(socat.stdout.strip(), "hello\nworld")
+ """Run the devmem TX test."""
+ run_tx(cfg)
@ksft_disruptive
def check_tx_chunks(cfg) -> None:
- require_devmem(cfg)
-
- port = rand_port()
- listen_cmd = f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}"
-
- with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
- wait_port_listen(port, host=cfg.remote)
- cmd(f"echo -e \"hello\\nworld\"| {cfg.bin_local} -f {cfg.ifname} -s {cfg.remote_addr} -p {port} -z 3", shell=True)
-
- ksft_eq(socat.stdout.strip(), "hello\nworld")
+ """Run the devmem TX chunking test."""
+ run_tx_chunks(cfg)
def check_rx_hds(cfg) -> None:
- """Test HDS splitting across payload sizes."""
- require_devmem(cfg)
-
- for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]:
- port = rand_port()
- listen_cmd = f"{cfg.bin_local} -L -l -f {cfg.ifname} -s {cfg.addr} -p {port}"
-
- with bkg(listen_cmd, exit_wait=True) as ncdevmem:
- wait_port_listen(port)
- cmd(f"dd if=/dev/zero bs={size} count=1 2>/dev/null | " +
- f"socat -b {size} -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{port},nodelay",
- host=cfg.remote, shell=True)
-
- ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}")
+ """Run the HDS test."""
+ run_rx_hds(cfg)
def main() -> None:
+ """Run the devmem test cases."""
with NetDrvEpEnv(__file__) as cfg:
- cfg.bin_local = path.abspath(path.dirname(__file__) + "/ncdevmem")
- cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
-
+ setup_test(cfg, path.abspath(path.dirname(__file__) + "/ncdevmem"))
ksft_run([check_rx, check_tx, check_tx_chunks, check_rx_hds],
- args=(cfg, ))
+ args=(cfg,))
ksft_exit()
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/devmem.py b/tools/testing/selftests/drivers/net/hw/lib/py/devmem.py
new file mode 100644
index 000000000000..d3e7a3645cba
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/devmem.py
@@ -0,0 +1,218 @@
+# SPDX-License-Identifier: GPL-2.0
+"""Shared helpers for devmem TCP selftests."""
+
+import re
+
+from net.lib.py import (bkg, cmd, defer, ethtool, rand_port, wait_port_listen,
+ ksft_eq, KsftSkipEx, NetNSEnter, EthtoolFamily,
+ NetdevFamily)
+
+
+def require_devmem(cfg):
+ """Probe ncdevmem on cfg.ifname and SKIP the test if devmem isn't supported."""
+ if not hasattr(cfg, "devmem_probed"):
+ probe_command = f"{cfg.bin_local} -f {cfg.ifname}"
+ cfg.devmem_supported = cmd(probe_command, fail=False, shell=True).ret == 0
+ cfg.devmem_probed = True
+
+ if not cfg.devmem_supported:
+ raise KsftSkipEx("Test requires devmem support")
+
+
+def configure_nic(cfg):
+ """Channels, rings, RSS, queue lease for netkit devmem."""
+ cfg.require_ipver('6')
+ ethnl = EthtoolFamily()
+
+ channels = ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
+ channels = channels['combined-count']
+ if channels < 2:
+ raise KsftSkipEx(
+ 'Test requires NETIF with at least 2 combined channels'
+ )
+
+ rings = ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
+ cfg.orig_rx_rings = rings['rx']
+ cfg.orig_hds_thresh = rings.get('hds-thresh', 0)
+ cfg.orig_data_split = rings.get('tcp-data-split', 'unknown')
+
+ ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
+ 'tcp-data-split': 'enabled',
+ 'hds-thresh': 0,
+ 'rx': min(64, cfg.orig_rx_rings)})
+
+ cfg.src_queue = channels - 1
+ ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")
+
+ with NetNSEnter(str(cfg.netns)):
+ netdevnl = NetdevFamily()
+ lease_result = netdevnl.queue_create({
+ "ifindex": cfg.nk_guest_ifindex,
+ "type": "rx",
+ "lease": {
+ "ifindex": cfg.ifindex,
+ "queue": {"id": cfg.src_queue, "type": "rx"},
+ "netns-id": 0,
+ },
+ })
+ cfg.nk_queue = lease_result['id']
+
+
+def cleanup_nic(cfg):
+ """Undo configure_nic() by restoring RSS and ring settings."""
+ ethtool(f"-X {cfg.ifname} default")
+ EthtoolFamily().rings_set({'header': {'dev-index': cfg.ifindex},
+ 'tcp-data-split': cfg.orig_data_split,
+ 'hds-thresh': cfg.orig_hds_thresh,
+ 'rx': cfg.orig_rx_rings})
+
+
+def set_flow_rule(cfg, port):
+ """Install a flow rule steering to src_queue and return the flow rule ID."""
+ output = ethtool(
+ f"-N {cfg.ifname} flow-type tcp6 dst-port {port}"
+ f" action {cfg.src_queue}"
+ ).stdout
+ return int(re.search(r'ID (\d+)', output).group(1))
+
+
+def ncdevmem_rx(cfg, port, verify=True, fail_on_linear=False, flow_steer=False):
+ """Build the ncdevmem RX listener command."""
+ if hasattr(cfg, 'netns'):
+ flow_rule_id = set_flow_rule(cfg, port)
+ defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
+
+ ifname = cfg.nk_guest_ifname
+ addr = cfg.nk_guest_ipv6
+ extras = [f"-t {cfg.nk_queue}", "-q 1", "-n"]
+ else:
+ ifname = cfg.ifname
+ addr = cfg.addr
+ extras = []
+ if flow_steer:
+ extras.append(f"-c {cfg.remote_addr}")
+
+ if verify:
+ extras.append("-v 7")
+ if fail_on_linear:
+ extras.append("-L")
+
+ parts = [cfg.bin_local, "-l", f"-f {ifname}", f"-s {addr}",
+ f"-p {port}", *extras]
+ return " ".join(parts)
+
+
+def ncdevmem_tx(cfg, port, chunk_size=0):
+ """Build the ncdevmem TX send command."""
+ if hasattr(cfg, 'netns'):
+ ifname = cfg.nk_guest_ifname
+ addr = cfg.remote_addr_v['6']
+ extras = ["-t 0", "-q 1", "-n"]
+ else:
+ ifname = cfg.ifname
+ addr = cfg.remote_addr
+ extras = []
+
+ if chunk_size:
+ extras.append(f"-z {chunk_size}")
+
+ parts = [cfg.bin_local, f"-f {ifname}", f"-s {addr}",
+ f"-p {port}", *extras]
+ return " ".join(parts)
+
+
+def socat_send(cfg, port, buf_size=0):
+ """Socat command for sending to the devmem listener.
+
+ When buf_size > 0, force one TCP segment per write of exactly that size by
+ setting socat's buffer (-b) and disabling Nagle (TCP_NODELAY).
+ """
+ proto = f"TCP{cfg.addr_ipver}"
+
+ if hasattr(cfg, 'netns'):
+ addr = f"[{cfg.nk_guest_ipv6}]"
+ else:
+ addr = cfg.baddr
+
+ suffix = f",bind={cfg.remote_baddr}:{port}"
+
+ buf = ""
+ if buf_size:
+ buf = f"-b {buf_size}"
+ suffix += ",nodelay"
+
+ return f"socat {buf} -u - {proto}:{addr}:{port}{suffix}"
+
+
+def socat_listen(cfg, port):
+ """Socat listen command for TX tests."""
+ return f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}"
+
+
+def setup_test(cfg, bin_local):
+ """Stash the local ncdevmem path on cfg and deploy it to the remote."""
+ cfg.bin_local = bin_local
+ cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
+
+
+def run_rx(cfg):
+ """Run the devmem RX test."""
+ require_devmem(cfg)
+ port = rand_port()
+ socat = socat_send(cfg, port)
+ data_pipe = (f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | head -c 1K"
+ f" | {socat}")
+ netns = getattr(cfg, "netns", None)
+
+ listen_cmd = ncdevmem_rx(cfg, port, flow_steer=not hasattr(cfg, 'netns'))
+ with bkg(listen_cmd, exit_wait=True, ns=netns) as ncdevmem:
+ wait_port_listen(port, proto="tcp", ns=netns)
+ cmd(data_pipe, host=cfg.remote, shell=True)
+ ksft_eq(ncdevmem.ret, 0)
+
+
+def run_tx(cfg):
+ """Run the devmem TX test."""
+ require_devmem(cfg)
+ netns = getattr(cfg, "netns", None)
+ port = rand_port()
+ tx_cmd = ncdevmem_tx(cfg, port)
+ listen_cmd = socat_listen(cfg, port)
+
+ with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
+ wait_port_listen(port, host=cfg.remote)
+ cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx_cmd}'", ns=netns, shell=True)
+ ksft_eq(socat.stdout.strip(), "hello\nworld")
+
+
+def run_tx_chunks(cfg):
+ """Run the devmem TX chunking test."""
+ require_devmem(cfg)
+ netns = getattr(cfg, "netns", None)
+ port = rand_port()
+ tx_cmd = ncdevmem_tx(cfg, port, chunk_size=3)
+ listen_cmd = socat_listen(cfg, port)
+
+ with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as socat:
+ wait_port_listen(port, host=cfg.remote)
+ cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx_cmd}'", ns=netns, shell=True)
+ ksft_eq(socat.stdout.strip(), "hello\nworld")
+
+
+def run_rx_hds(cfg):
+ """Run the HDS test by running devmem RX across a segment size sweep."""
+ require_devmem(cfg)
+ netns = getattr(cfg, "netns", None)
+
+ for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]:
+ port = rand_port()
+
+ listen_cmd = ncdevmem_rx(cfg, port, verify=False,
+ fail_on_linear=True)
+ socat = socat_send(cfg, port, buf_size=size)
+
+ with bkg(listen_cmd, exit_wait=True, ns=netns) as ncdevmem:
+ wait_port_listen(port, proto="tcp", ns=netns)
+ cmd(f"dd if=/dev/zero bs={size} count=1 2>/dev/null | "
+ f"{socat}", host=cfg.remote, shell=True)
+ ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}")
--
2.53.0-Meta
next prev parent reply other threads:[~2026-05-08 2:28 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-08 2:27 [PATCH net-next v3 0/8] net: devmem: support devmem with netkit devices Bobby Eshleman
2026-05-08 2:27 ` [PATCH net-next v3 1/8] net: convert netmem_tx flag to enum Bobby Eshleman
2026-05-08 14:56 ` Stanislav Fomichev
2026-05-08 16:11 ` Bobby Eshleman
2026-05-08 2:27 ` [PATCH net-next v3 2/8] net: netkit: declare NETMEM_TX_NO_DMA mode Bobby Eshleman
2026-05-08 14:57 ` Stanislav Fomichev
2026-05-08 2:27 ` [PATCH net-next v3 3/8] net: devmem: support TX over NETMEM_TX_NO_DMA devices Bobby Eshleman
2026-05-08 15:01 ` Stanislav Fomichev
2026-05-08 16:19 ` Bobby Eshleman
2026-05-08 20:44 ` Jakub Kicinski
2026-05-08 20:47 ` Jakub Kicinski
2026-05-08 21:28 ` Bobby Eshleman
2026-05-08 22:27 ` Jakub Kicinski
2026-05-08 23:03 ` Bobby Eshleman
2026-05-08 2:27 ` [PATCH net-next v3 4/8] selftests: drv-net: ncdevmem: add -n flag to skip NIC configuration Bobby Eshleman
2026-05-08 15:01 ` Stanislav Fomichev
2026-05-08 2:27 ` [PATCH net-next v3 5/8] selftests: drv-net: make attr _nk_guest_ifname public Bobby Eshleman
2026-05-08 15:01 ` Stanislav Fomichev
2026-05-08 2:27 ` Bobby Eshleman [this message]
2026-05-08 15:03 ` [PATCH net-next v3 6/8] selftests: drv-net: refactor devmem command builders into lib module Stanislav Fomichev
2026-05-08 16:19 ` Bobby Eshleman
2026-05-08 2:27 ` [PATCH net-next v3 7/8] selftests: drv-net: add primary_rx_redirect support to NetDrvContEnv Bobby Eshleman
2026-05-08 15:03 ` Stanislav Fomichev
2026-05-08 2:27 ` [PATCH net-next v3 8/8] selftests: drv-net: add netkit devmem tests Bobby Eshleman
2026-05-08 15:03 ` Stanislav Fomichev
2026-05-10 20:33 ` [PATCH net-next v3 0/8] net: devmem: support devmem with netkit devices Zhu Yanjun
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=20260507-tcp-dm-netkit-v3-6-52821445867c@meta.com \
--to=bobbyeshleman@gmail.com \
--cc=alexanderduyck@fb.com \
--cc=alexs@kernel.org \
--cc=almasrymina@google.com \
--cc=andrew+netdev@lunn.ch \
--cc=bobbyeshleman@meta.com \
--cc=bpf@vger.kernel.org \
--cc=corbet@lwn.net \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dw@davidwei.uk \
--cc=dzm91@hust.edu.cn \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=hramamurthy@google.com \
--cc=jiang.kun2@zte.com.cn \
--cc=joshwash@google.com \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=mbloch@nvidia.com \
--cc=michael.chan@broadcom.com \
--cc=mohsin.bashr@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pavan.chebbi@broadcom.com \
--cc=razor@blackwall.org \
--cc=saeedm@nvidia.com \
--cc=sdf.kernel@gmail.com \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=si.yanteng@linux.dev \
--cc=skhan@linuxfoundation.org \
--cc=tariqt@nvidia.com \
--cc=wang.yaxin@zte.com.cn \
--cc=willemb@google.com \
--cc=xu.xin16@zte.com.cn \
/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