* [PATCH net-next v6 2/6] tls: Abort the connection on decrypt failure
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
recvmsg, read_sock, and splice_read each open-code a
tls_err_abort() call after tls_rx_one_record() fails. Move
the abort into tls_rx_one_record() so each receive path
shares a single decrypt-and-abort sequence.
A tls_check_pending_rekey() failure after successful
decryption no longer triggers tls_err_abort(). That path
fires only when skb_copy_bits() fails on a valid skb,
which is not a realistic scenario.
Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls_sw.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 20f8fc84c5f5..5626fdd4ea0a 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1799,6 +1799,9 @@ static int tls_check_pending_rekey(struct sock *sk, struct tls_context *ctx,
return 0;
}
+/* Decrypt and return one TLS record. On decrypt failure the connection is
+ * aborted (sk_err set) before returning a negative errno.
+ */
static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
struct tls_decrypt_arg *darg)
{
@@ -1810,8 +1813,10 @@ static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
err = tls_decrypt_device(sk, msg, tls_ctx, darg);
if (!err)
err = tls_decrypt_sw(sk, tls_ctx, msg, darg);
- if (err < 0)
+ if (err < 0) {
+ tls_err_abort(sk, -EBADMSG);
return err;
+ }
rxm = strp_msg(darg->skb);
rxm->offset += prot->prepend_size;
@@ -2122,10 +2127,8 @@ int tls_sw_recvmsg(struct sock *sk,
darg.async = false;
err = tls_rx_one_record(sk, msg, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto recv_end;
- }
async |= darg.async;
@@ -2284,10 +2287,8 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
memset(&darg.inargs, 0, sizeof(darg.inargs));
err = tls_rx_one_record(sk, NULL, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto splice_read_end;
- }
tls_rx_rec_done(ctx);
skb = darg.skb;
@@ -2370,10 +2371,8 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
memset(&darg.inargs, 0, sizeof(darg.inargs));
err = tls_rx_one_record(sk, NULL, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto read_sock_end;
- }
released = tls_read_flush_backlog(sk, prot, INT_MAX,
0, decrypted,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 1/6] tls: Purge async_hold in tls_decrypt_async_wait()
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
The async_hold queue pins encrypted input skbs while
the AEAD engine references their scatterlist data. Once
tls_decrypt_async_wait() returns, every AEAD operation
has completed and the engine no longer references those
skbs, so they can be freed unconditionally.
A subsequent patch adds batch async decryption to
tls_sw_read_sock(), introducing a new call site that
must drain pending AEAD operations and release held
skbs. Move __skb_queue_purge(&ctx->async_hold) into
tls_decrypt_async_wait() so the purge is centralized
and every caller -- recvmsg's drain path, the -EBUSY
fallback in tls_do_decryption(), and the new read_sock
batch path -- releases held skbs on synchronization
without each site managing the purge independently.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls_sw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index a656ce235758..20f8fc84c5f5 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -246,6 +246,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx)
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
atomic_inc(&ctx->decrypt_pending);
+ __skb_queue_purge(&ctx->async_hold);
return ctx->async_wait.err;
}
@@ -2224,7 +2225,6 @@ int tls_sw_recvmsg(struct sock *sk,
/* Wait for all previously submitted records to be decrypted */
ret = tls_decrypt_async_wait(ctx);
- __skb_queue_purge(&ctx->async_hold);
if (ret) {
if (err >= 0 || err == -EINPROGRESS)
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 0/6] TLS read_sock performance scalability
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke,
Alistair Francis
I'd like to encourage in-kernel kTLS consumers (i.e., NFS and
NVMe/TCP) to coalesce on the use of read_sock. When I suggested
this to Hannes, he reported a number of nagging performance
scalability issues with read_sock. This series is an attempt to
run these issues down and get them fixed before we convert the
above sock_recvmsg consumers over to read_sock.
Batch async decryption and its submit/deliver scaffolding were
dropped from this series because async_capable is always false
for TLS 1.3, which NFS and NVMe/TCP both require. Async crypto
support for TLS 1.3 is a prerequisite for revisiting that work.
---
Changes since v5:
- Patch 6: Set released = true when sk_flush_backlog() returns
true, so tls_strp_msg_load() knows the socket lock was
released (Sabrina)
- Patch 6: Drop Fixes tag; submit bug fix separately via net
if warranted (Sabrina)
- Patch 6: Note redundant flush on cold path in commit message
(Sabrina)
Changes since v4:
- Drop batch async decryption and submit/deliver restructure:
async_capable is always false for TLS 1.3, so the new code
was unreachable for NFS and NVMe/TCP
- Purge async_hold directly in tls_decrypt_async_wait() and drop
the tls_decrypt_async_drain() wrapper
- Merge tls_strp_check_rcv_quiet() into tls_strp_check_rcv() with
a bool wake parameter; fix lost wakeup on the recvmsg exit path
Changes since v3:
- Clarify why tls_decrypt_async_drain() is separate from _wait()
- Fold tls_err_abort() into tls_rx_one_record(), drop tls_rx_decrypt_record()
- Move backlog flush into tls_rx_rec_wait() so all RX paths benefit
Changes since v2:
- Fix short read self tests
Changes since v1:
- Add C11 reference
- Extend data_ready reduction to recvmsg and splice
- Restructure read_sock and recvmsg using shared helpers
---
- Link to v5: https://patch.msgid.link/20260324-tls-read-sock-v5-0-5408befe5774@oracle.com
---
Chuck Lever (6):
tls: Purge async_hold in tls_decrypt_async_wait()
tls: Abort the connection on decrypt failure
tls: Fix dangling skb pointer in tls_sw_read_sock()
tls: Factor tls_strp_msg_release() from tls_strp_msg_done()
tls: Suppress spurious saved_data_ready on all receive paths
tls: Flush backlog before waiting for a new record
net/tls/tls.h | 4 ++--
net/tls/tls_main.c | 2 +-
net/tls/tls_strp.c | 42 +++++++++++++++++++++++++++++++-----------
net/tls/tls_sw.c | 52 +++++++++++++++++++++++++++++++---------------------
4 files changed, 65 insertions(+), 35 deletions(-)
---
base-commit: fb78a629b4f0eb399b413f6c093a3da177b3a4eb
change-id: 20260317-tls-read-sock-a0022c9df265
Best regards,
--
Chuck Lever
^ permalink raw reply
* Re: [PATCH net] ipv6: fix data race in fib6_metric_set() using cmpxchg
From: Jiayuan Chen @ 2026-03-26 13:43 UTC (permalink / raw)
To: Hangbin Liu, Eric Dumazet
Cc: David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Simon Horman, David Ahern, netdev, linux-kernel, Fei Liu
In-Reply-To: <acUw8zYwbbpgo8KJ@fedora>
On 3/26/26 9:13 PM, Hangbin Liu wrote:
> On Thu, Mar 26, 2026 at 05:05:57AM -0700, Eric Dumazet wrote:
>>> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
>>> index dd26657b6a4a..64de761f40d5 100644
>>> --- a/net/ipv6/ip6_fib.c
>>> +++ b/net/ipv6/ip6_fib.c
>>> @@ -730,14 +730,16 @@ void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val)
>>> if (!f6i)
>>> return;
>>>
>>> - if (f6i->fib6_metrics == &dst_default_metrics) {
>>> + if (READ_ONCE(f6i->fib6_metrics) == &dst_default_metrics) {
>>> + struct dst_metrics *dflt = (struct dst_metrics *)&dst_default_metrics;
>>> struct dst_metrics *p = kzalloc_obj(*p, GFP_ATOMIC);
>>>
>>> if (!p)
>>> return;
>>>
>>> refcount_set(&p->refcnt, 1);
>>> - f6i->fib6_metrics = p;
>>> + if (cmpxchg(&f6i->fib6_metrics, dflt, p) != dflt)
>>> + kfree(p);
>>> }
>>>
>> The following line should happen before the cmpxchg(),
>> ->metrics[X] accesses also need READ_ONCE()/WRITE_ONCE() annotations.
> Hi Eric,
>
> Jiayuan also suggested to using READ_ONCE()/WRITE_ONCE() for metrics[X]
> accesses. But I don't get why this line should happen before the cmpxchg(),
> Would you please help explain?
I think what Eric means is something like this:
...
struct dst_metrics *p = kzalloc_obj(*p, GFP_ATOMIC);
if (!p)
return;
p->metrics[metric - 1] = val;
refcount_set(&p->refcnt, 1);
if (cmpxchg(&f6i->fib6_metrics, dflt, p) != dflt)
kfree(p);
else
return;
}
}
m = READ_ONCE(f6i->fib6_metrics);
WRITE_ONCE(m->metrics[metric - 1], val);
Since p is private data before being published via cmpxchg(), we can
safely initialize its metrics beforehand. This way we don't need to
worry about concurrent access to f6i->fib6_metrics->metrics[] during
initialization. Right?
^ permalink raw reply
* Re: [PATCH net-next v1 2/7] net: hsr: replace fallthrough comments with fallthrough macro
From: kernel test robot @ 2026-03-26 13:34 UTC (permalink / raw)
To: luka.gejak, davem, edumazet, kuba, pabeni, netdev
Cc: oe-kbuild-all, horms, fmaurer, liuhangbin, linux-kernel,
Luka Gejak
In-Reply-To: <20260324144630.189094-3-luka.gejak@linux.dev>
Hi,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/luka-gejak-linux-dev/net-hsr-constify-hsr_ops-and-prp_ops-protocol-operation-structures/20260326-143638
base: net-next/main
patch link: https://lore.kernel.org/r/20260324144630.189094-3-luka.gejak%40linux.dev
patch subject: [PATCH net-next v1 2/7] net: hsr: replace fallthrough comments with fallthrough macro
config: x86_64-rhel-9.4 (https://download.01.org/0day-ci/archive/20260326/202603261419.jqhvfAVi-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260326/202603261419.jqhvfAVi-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603261419.jqhvfAVi-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/compiler_types.h:88,
from <command-line>:
net/hsr/hsr_netlink.c: In function 'hsr_get_node_status':
>> include/linux/compiler_attributes.h:214:41: error: invalid use of attribute 'fallthrough'
214 | # define fallthrough __attribute__((__fallthrough__))
| ^~~~~~~~~~~~~
net/hsr/hsr_netlink.c:436:9: note: in expansion of macro 'fallthrough'
436 | fallthrough;
| ^~~~~~~~~~~
net/hsr/hsr_netlink.c: In function 'hsr_get_node_list':
>> include/linux/compiler_attributes.h:214:41: error: invalid use of attribute 'fallthrough'
214 | # define fallthrough __attribute__((__fallthrough__))
| ^~~~~~~~~~~~~
net/hsr/hsr_netlink.c:527:9: note: in expansion of macro 'fallthrough'
527 | fallthrough;
| ^~~~~~~~~~~
--
In file included from include/linux/compiler_types.h:88,
from <command-line>:
hsr_netlink.c: In function 'hsr_get_node_status':
>> include/linux/compiler_attributes.h:214:41: error: invalid use of attribute 'fallthrough'
214 | # define fallthrough __attribute__((__fallthrough__))
| ^~~~~~~~~~~~~
hsr_netlink.c:436:9: note: in expansion of macro 'fallthrough'
436 | fallthrough;
| ^~~~~~~~~~~
hsr_netlink.c: In function 'hsr_get_node_list':
>> include/linux/compiler_attributes.h:214:41: error: invalid use of attribute 'fallthrough'
214 | # define fallthrough __attribute__((__fallthrough__))
| ^~~~~~~~~~~~~
hsr_netlink.c:527:9: note: in expansion of macro 'fallthrough'
527 | fallthrough;
| ^~~~~~~~~~~
vim +/fallthrough +214 include/linux/compiler_attributes.h
294f69e662d157 Joe Perches 2019-10-05 201
294f69e662d157 Joe Perches 2019-10-05 202 /*
294f69e662d157 Joe Perches 2019-10-05 203 * Add the pseudo keyword 'fallthrough' so case statement blocks
294f69e662d157 Joe Perches 2019-10-05 204 * must end with any of these keywords:
294f69e662d157 Joe Perches 2019-10-05 205 * break;
294f69e662d157 Joe Perches 2019-10-05 206 * fallthrough;
ca0760e7d79e2b Wei Ming Chen 2021-05-06 207 * continue;
294f69e662d157 Joe Perches 2019-10-05 208 * goto <label>;
294f69e662d157 Joe Perches 2019-10-05 209 * return [expression];
294f69e662d157 Joe Perches 2019-10-05 210 *
294f69e662d157 Joe Perches 2019-10-05 211 * gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
294f69e662d157 Joe Perches 2019-10-05 212 */
294f69e662d157 Joe Perches 2019-10-05 213 #if __has_attribute(__fallthrough__)
294f69e662d157 Joe Perches 2019-10-05 @214 # define fallthrough __attribute__((__fallthrough__))
294f69e662d157 Joe Perches 2019-10-05 215 #else
294f69e662d157 Joe Perches 2019-10-05 216 # define fallthrough do {} while (0) /* fallthrough */
a3f8a30f3f0079 Miguel Ojeda 2018-08-30 217 #endif
a3f8a30f3f0079 Miguel Ojeda 2018-08-30 218
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH net-next v4 09/10] selftests: drivers: hw: update ethtool_rmon to work with a single local interface
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
This patch finalizes the transition to work with a single local
interface for the ethtool_rmon.sh test. Each 'ip link' and 'ethtool'
command used by the test is annotated with the necessary run_on in
order to be executed on the necessary target system, be it local, in
another network namespace or through ssh.
Since we need NETIF up and running also for control traffic, we now
expect that the interfaces are up and running and do not touch bring
them up or down at the end of the test. This is also documented in the
drivers/net/README.rst.
The ethtool_rmon.sh script can still be used in the older fashion by
passing two interfaces as command line arguments, the only restriction
is that those interfaces need to be already up.
$ DRIVER_TEST_CONFORMANT=no ./ethtool_rmon.sh eth0 eth1
As part of the kselftest infrastructure, this test can be run in the
following manner:
$ make -C tools/testing/selftests/ TARGETS="drivers/net drivers/net/hw" \
install INSTALL_PATH=/tmp/ksft-net-drv
$ cd /tmp/ksft-net-drv/
$ cat > ./drivers/net/net.config <<EOF
NETIF=endpmac17
LOCAL_V4=17.0.0.1
REMOTE_V4=17.0.0.2
REMOTE_TYPE=ssh
REMOTE_ARGS=root@192.168.5.200
EOF
$ ./run_kselftest.sh -t drivers/net/hw:ethtool_rmon.sh
TAP version 13
1..1
# timeout set to 0
# selftests: drivers/net/hw: ethtool_rmon.sh
# TAP version 13
# 1..14
# ok 1 ethtool_rmon.rx-pkts64to64
# ok 2 ethtool_rmon.rx-pkts65to127
# ok 3 ethtool_rmon.rx-pkts128to255
# ok 4 ethtool_rmon.rx-pkts256to511
# ok 5 ethtool_rmon.rx-pkts512to1023
# ok 6 ethtool_rmon.rx-pkts1024to1518
# ok 7 ethtool_rmon.rx-pkts1519to10240
# ok 8 ethtool_rmon.tx-pkts64to64
# ok 9 ethtool_rmon.tx-pkts65to127
# ok 10 ethtool_rmon.tx-pkts128to255
# ok 11 ethtool_rmon.tx-pkts256to511
# ok 12 ethtool_rmon.tx-pkts512to1023
# ok 13 ethtool_rmon.tx-pkts1024to1518
# ok 14 ethtool_rmon.tx-pkts1519to10240
# # Totals: pass:14 fail:0 xfail:0 xpass:0 skip:0 error:0
ok 1 selftests: drivers/net/hw: ethtool_rmon.sh
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
---
Changes in v4:
- set DRIVER_TEST_CONFORMANT to yes
- update the commit message to reflect the current output
- split some more lines to 80 chars
Changes in v3:
- none
Changes in v2:
- patch is new
.../selftests/drivers/net/hw/ethtool_rmon.sh | 30 +++++++++++--------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index ed81bdc33536..2ec19edddfaa 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -8,6 +8,7 @@ ALL_TESTS="
rmon_tx_histogram
"
+: "${DRIVER_TEST_CONFORMANT:=yes}"
NUM_NETIFS=2
lib_dir=$(dirname "$0")
source "$lib_dir"/../../../net/forwarding/lib.sh
@@ -27,9 +28,11 @@ ensure_mtu()
local required=$((len - ETH_HLEN - ETH_FCS_LEN))
local current
- current=$(ip -j link show dev "$iface" | jq -r '.[0].mtu')
+ current=$(run_on "$iface" \
+ ip -j link show dev "$iface" | jq -r '.[0].mtu')
if [ "$current" -lt "$required" ]; then
- ip link set dev "$iface" mtu "$required" || return 1
+ run_on "$iface" ip link set dev "$iface" mtu "$required" \
+ || return 1
fi
}
@@ -52,15 +55,17 @@ bucket_test()
len=$((len - ETH_FCS_LEN))
len=$((len > 0 ? len : 0))
- before=$(ethtool --json -S "$iface" --groups rmon | \
+ before=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
# Send 10k one way and 20k in the other, to detect counters
# mapped to the wrong direction
- "$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us
- "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
+ run_on "$neigh" \
+ "$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us
+ run_on "$iface" \
+ "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
- after=$(ethtool --json -S "$iface" --groups rmon | \
+ after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
delta=$((after - before))
@@ -95,7 +100,7 @@ rmon_histogram()
fi
ktap_test_pass "$TEST_NAME.$step"
nbuckets=$((nbuckets + 1))
- done < <(ethtool --json -S "$iface" --groups rmon | \
+ done < <(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
if [ "$nbuckets" -eq 0 ]; then
@@ -120,9 +125,8 @@ setup_prepare()
h2=${NETIFS[p2]}
for iface in "$h1" "$h2"; do
- netif_mtu["$iface"]=$(ip -j link show dev "$iface" | \
- jq -r '.[0].mtu')
- ip link set dev "$iface" up
+ netif_mtu["$iface"]=$(run_on "$iface" \
+ ip -j link show dev "$iface" | jq -r '.[0].mtu')
done
}
@@ -130,10 +134,10 @@ cleanup()
{
pre_cleanup
+ # Do not bring down the interfaces, just configure the initial MTU
for iface in "$h2" "$h1"; do
- ip link set dev "$iface" \
- mtu "${netif_mtu[$iface]}" \
- down
+ run_on "$iface" ip link set dev "$iface" \
+ mtu "${netif_mtu[$iface]}"
done
}
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 10/10] selftests: drivers: hw: add test for the ethtool standard counters
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Add a new selftest - ethtool_std_stats.sh - which validates the
eth-ctrl, eth-mac and pause standard statistics exported by an
interface. Collision related eth-mac counters as well as the error ones
will be checked against zero since that is the most likely correct
scenario.
The central part of this patch is the traffic_test() function which
gathers the 'before' counter values, sends a batch of traffic and then
interrogates again the same counters in order to determine if the delta
is on target. The function receives an array through which the caller
can request what counters to be interrogated and, for each of them, what
is their target delta value.
The output from this selftest looks as follows on a LX2160ARDB board:
$ ./run_kselftest.sh -t drivers/net/hw:ethtool_std_stats.sh
TAP version 13
1..1
# timeout set to 0
# selftests: drivers/net/hw: ethtool_std_stats.sh
# TAP version 13
# 1..26
# ok 1 ethtool_std_stats.eth-ctrl-MACControlFramesTransmitted
# ok 2 ethtool_std_stats.eth-ctrl-MACControlFramesReceived
# ok 3 ethtool_std_stats.eth-mac-FrameCheckSequenceErrors
# ok 4 ethtool_std_stats.eth-mac-AlignmentErrors
# ok 5 ethtool_std_stats.eth-mac-FramesLostDueToIntMACXmitError
# ok 6 ethtool_std_stats.eth-mac-CarrierSenseErrors # SKIP
# ok 7 ethtool_std_stats.eth-mac-FramesLostDueToIntMACRcvError
# ok 8 ethtool_std_stats.eth-mac-InRangeLengthErrors # SKIP
# ok 9 ethtool_std_stats.eth-mac-OutOfRangeLengthField # SKIP
# ok 10 ethtool_std_stats.eth-mac-FrameTooLongErrors # SKIP
# ok 11 ethtool_std_stats.eth-mac-FramesAbortedDueToXSColls # SKIP
# ok 12 ethtool_std_stats.eth-mac-SingleCollisionFrames # SKIP
# ok 13 ethtool_std_stats.eth-mac-MultipleCollisionFrames # SKIP
# ok 14 ethtool_std_stats.eth-mac-FramesWithDeferredXmissions # SKIP
# ok 15 ethtool_std_stats.eth-mac-LateCollisions # SKIP
# ok 16 ethtool_std_stats.eth-mac-FramesWithExcessiveDeferral # SKIP
# ok 17 ethtool_std_stats.eth-mac-BroadcastFramesXmittedOK
# ok 18 ethtool_std_stats.eth-mac-OctetsTransmittedOK
# ok 19 ethtool_std_stats.eth-mac-BroadcastFramesReceivedOK
# ok 20 ethtool_std_stats.eth-mac-OctetsReceivedOK
# ok 21 ethtool_std_stats.eth-mac-FramesTransmittedOK
# ok 22 ethtool_std_stats.eth-mac-MulticastFramesXmittedOK
# ok 23 ethtool_std_stats.eth-mac-FramesReceivedOK
# ok 24 ethtool_std_stats.eth-mac-MulticastFramesReceivedOK
# ok 25 ethtool_std_stats.pause-tx_pause_frames
# ok 26 ethtool_std_stats.pause-rx_pause_frames
# # 10 skipped test(s) detected. Consider enabling relevant config options to improve coverage.
# # Totals: pass:16 fail:0 xfail:0 xpass:0 skip:10 error:0
ok 1 selftests: drivers/net/hw: ethtool_std_stats.sh
Please note that not all MACs are counting the software injected pause
frames as real Tx pause. For example, on a LS1028ARDB the selftest
output will reflect the fact that neither the ENETC MAC, nor the Felix
switch MAC are able to detect Tx pause frames injected by software.
$ ./run_kselftest.sh -t drivers/net/hw:ethtool_std_stats.sh
(...)
# # software sent pause frames not detected
# ok 25 ethtool_std_stats.pause-tx_pause_frames # XFAIL
# ok 26 ethtool_std_stats.pause-rx_pause_frames
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
---
Changes in v4:
- move to a the KTAP format output by using ktap_helpers.sh
- update commit message to reflect the current output
- use DRIVER_TEST_CONFORMANT
Changes in v3:
- none
Changes in v2:
- Use the new run_on helper
- No longer checking that each counter has a 1% tolerance against the
target. The only upper limit is UINT32_MAX.
- Check that both the error counters and the collision related ones are
zero since this is the most probable scenario (we don't expect errors
with the traffic that we are sending).
- Removed any checks performed on the remot interface counters since
that is being used only as a traffic generator.
.../testing/selftests/drivers/net/hw/Makefile | 1 +
.../drivers/net/hw/ethtool_std_stats.sh | 206 ++++++++++++++++++
2 files changed, 207 insertions(+)
create mode 100755 tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 3c97dac9baaa..442dba3d6a03 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -26,6 +26,7 @@ TEST_PROGS = \
ethtool_extended_state.sh \
ethtool_mm.sh \
ethtool_rmon.sh \
+ ethtool_std_stats.sh \
gro_hw.py \
hw_stats_l3.sh \
hw_stats_l3_gre.sh \
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
new file mode 100755
index 000000000000..c085d2a4c989
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
@@ -0,0 +1,206 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#shellcheck disable=SC2034 # SC does not see the global variables
+#shellcheck disable=SC2317,SC2329 # unused functions
+
+ALL_TESTS="
+ test_eth_ctrl_stats
+ test_eth_mac_stats
+ test_pause_stats
+"
+: "${DRIVER_TEST_CONFORMANT:=yes}"
+STABLE_MAC_ADDRS=yes
+NUM_NETIFS=2
+lib_dir=$(dirname "$0")
+# shellcheck source=./../../../net/forwarding/lib.sh
+source "$lib_dir"/../../../net/forwarding/lib.sh
+# shellcheck source=./../../../kselftest/ktap_helpers.sh
+source "$lib_dir"/../../../kselftest/ktap_helpers.sh
+
+UINT32_MAX=$((2**32 - 1))
+SUBTESTS=0
+TEST_NAME=$(basename "$0" .sh)
+
+traffic_test()
+{
+ local iface=$1; shift
+ local neigh=$1; shift
+ local num_tx=$1; shift
+ local pkt_format="$1"; shift
+ local -a counters=("$@")
+ local int grp cnt target exact_check
+ local before after delta
+ local num_rx=$((num_tx * 2))
+ local xfail_message
+ local src="aggregate"
+ local i
+
+ for i in "${!counters[@]}"; do
+ read -r int grp cnt target exact_check xfail_message \
+ <<< "${counters[$i]}"
+
+ before[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src")
+ done
+
+ # shellcheck disable=SC2086 # needs split options
+ run_on "$iface" "$MZ" "$iface" -q -c "$num_tx" $pkt_format
+
+ # shellcheck disable=SC2086 # needs split options
+ run_on "$neigh" "$MZ" "$neigh" -q -c "$num_rx" $pkt_format
+
+ for i in "${!counters[@]}"; do
+ read -r int grp cnt target exact_check xfail_message \
+ <<< "${counters[$i]}"
+
+ after[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src")
+ if [[ "${after[$i]}" == "null" ]]; then
+ ktap_test_skip "$TEST_NAME.$grp-$cnt"
+ continue;
+ fi
+
+ delta=$((after[i] - before[i]))
+
+ if [ "$exact_check" -ne 0 ]; then
+ [ "$delta" -eq "$target" ]
+ else
+ [ "$delta" -ge "$target" ] && \
+ [ "$delta" -le "$UINT32_MAX" ]
+ fi
+ err="$?"
+
+ if [[ $err != 0 ]] && [[ -n $xfail_message ]]; then
+ ktap_print_msg "$xfail_message"
+ ktap_test_xfail "$TEST_NAME.$grp-$cnt"
+ continue;
+ fi
+
+ if [[ $err != 0 ]]; then
+ ktap_print_msg "$grp-$cnt is not valid on $int (expected $target, got $delta)"
+ ktap_test_fail "$TEST_NAME.$grp-$cnt"
+ else
+ ktap_test_pass "$TEST_NAME.$grp-$cnt"
+ fi
+ done
+}
+
+test_eth_ctrl_stats()
+{
+ local pkt_format="-a own -b bcast 88:08 -p 64"
+ local num_pkts=1000
+ local -a counters
+
+ counters=("$h1 eth-ctrl MACControlFramesTransmitted $num_pkts 0")
+ traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 eth-ctrl MACControlFramesReceived $num_pkts 0")
+ traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \
+ "${counters[@]}"
+}
+SUBTESTS=$((SUBTESTS + 2))
+
+test_eth_mac_stats()
+{
+ local pkt_size=100
+ local pkt_size_fcs=$((pkt_size + 4))
+ local bcast_pkt_format="-a own -b bcast -p $pkt_size"
+ local mcast_pkt_format="-a own -b 01:00:5E:00:00:01 -p $pkt_size"
+ local num_pkts=2000
+ local octets=$((pkt_size_fcs * num_pkts))
+ local -a counters error_cnt collision_cnt
+
+ # Error counters should be exactly zero
+ counters=("$h1 eth-mac FrameCheckSequenceErrors 0 1"
+ "$h1 eth-mac AlignmentErrors 0 1"
+ "$h1 eth-mac FramesLostDueToIntMACXmitError 0 1"
+ "$h1 eth-mac CarrierSenseErrors 0 1"
+ "$h1 eth-mac FramesLostDueToIntMACRcvError 0 1"
+ "$h1 eth-mac InRangeLengthErrors 0 1"
+ "$h1 eth-mac OutOfRangeLengthField 0 1"
+ "$h1 eth-mac FrameTooLongErrors 0 1"
+ "$h1 eth-mac FramesAbortedDueToXSColls 0 1")
+ traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
+ "${counters[@]}"
+
+ # Collision related counters should also be zero
+ counters=("$h1 eth-mac SingleCollisionFrames 0 1"
+ "$h1 eth-mac MultipleCollisionFrames 0 1"
+ "$h1 eth-mac FramesWithDeferredXmissions 0 1"
+ "$h1 eth-mac LateCollisions 0 1"
+ "$h1 eth-mac FramesWithExcessiveDeferral 0 1")
+ traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 eth-mac BroadcastFramesXmittedOK $num_pkts 0"
+ "$h1 eth-mac OctetsTransmittedOK $octets 0")
+ traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 eth-mac BroadcastFramesReceivedOK $num_pkts 0"
+ "$h1 eth-mac OctetsReceivedOK $octets 0")
+ traffic_test "$h2" "$h1" "$num_pkts" "$bcast_pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 eth-mac FramesTransmittedOK $num_pkts 0"
+ "$h1 eth-mac MulticastFramesXmittedOK $num_pkts 0")
+ traffic_test "$h1" "$h2" "$num_pkts" "$mcast_pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 eth-mac FramesReceivedOK $num_pkts 0"
+ "$h1 eth-mac MulticastFramesReceivedOK $num_pkts 0")
+ traffic_test "$h2" "$h1" "$num_pkts" "$mcast_pkt_format" \
+ "${counters[@]}"
+}
+SUBTESTS=$((SUBTESTS + 22))
+
+test_pause_stats()
+{
+ local pkt_format="-a own -b 01:80:c2:00:00:01 88:08:00:01:00:01"
+ local xfail_message="software sent pause frames not detected"
+ local num_pkts=2000
+ local -a counters
+ local int
+ local i
+
+ # Check that there is pause frame support
+ for ((i = 1; i <= NUM_NETIFS; ++i)); do
+ int="${NETIFS[p$i]}"
+ if ! run_on "$int" ethtool -I --json -a "$int" > /dev/null 2>&1; then
+ ktap_test_skip "$TEST_NAME.tx_pause_frames"
+ ktap_test_skip "$TEST_NAME.rx_pause_frames"
+ return
+ fi
+ done
+
+ counters=("$h1 pause tx_pause_frames $num_pkts 0 $xfail_message")
+ traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \
+ "${counters[@]}"
+
+ counters=("$h1 pause rx_pause_frames $num_pkts 0")
+ traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \
+ "${counters[@]}"
+}
+SUBTESTS=$((SUBTESTS + 2))
+
+setup_prepare()
+{
+ local iface
+
+ h1=${NETIFS[p1]}
+ h2=${NETIFS[p2]}
+
+ h2_mac=$(mac_get "$h2")
+}
+
+ktap_print_header
+ktap_set_plan $SUBTESTS
+
+check_ethtool_counter_group_support
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+ktap_finished
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 08/10] selftests: drivers: hw: move to KTAP output
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Update the ethtool_rmon.sh test so that it uses the KTAP format for its
output. This is achieved by using the helpers found in ktap_helpers.sh.
An example output can be found below.
$ ./ethtool_rmon.sh endpmac3 endpmac4
TAP version 13
1..14
ok 1 ethtool_rmon.rx-pkts64to64
ok 2 ethtool_rmon.rx-pkts65to127
ok 3 ethtool_rmon.rx-pkts128to255
ok 4 ethtool_rmon.rx-pkts256to511
ok 5 ethtool_rmon.rx-pkts512to1023
ok 6 ethtool_rmon.rx-pkts1024to1518
ok 7 ethtool_rmon.rx-pkts1519to10240
ok 8 ethtool_rmon.tx-pkts64to64
ok 9 ethtool_rmon.tx-pkts65to127
ok 10 ethtool_rmon.tx-pkts128to255
ok 11 ethtool_rmon.tx-pkts256to511
ok 12 ethtool_rmon.tx-pkts512to1023
ok 13 ethtool_rmon.tx-pkts1024to1518
ok 14 ethtool_rmon.tx-pkts1519to10240
# Totals: pass:14 fail:0 xfail:0 xpass:0 skip:0 error:0
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
---
Changes in v4:
- patch is added in this version so that ethtool_rmon.sh is converted to
KTAP output
.../selftests/drivers/net/hw/ethtool_rmon.sh | 24 ++++++++++++-------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index f290ce1832f1..ed81bdc33536 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -11,10 +11,12 @@ ALL_TESTS="
NUM_NETIFS=2
lib_dir=$(dirname "$0")
source "$lib_dir"/../../../net/forwarding/lib.sh
+source "$lib_dir"/../../../kselftest/ktap_helpers.sh
UINT32_MAX=$((2**32 - 1))
ETH_FCS_LEN=4
ETH_HLEN=$((6+6+2))
+TEST_NAME=$(basename "$0" .sh)
declare -A netif_mtu
@@ -76,29 +78,28 @@ rmon_histogram()
local nbuckets=0
local step=
- RET=0
-
while read -r -a bucket; do
- step="$set-pkts${bucket[0]}to${bucket[1]} on $iface"
+ step="$set-pkts${bucket[0]}to${bucket[1]}"
for if in "$iface" "$neigh"; do
if ! ensure_mtu "$if" "${bucket[0]}"; then
- log_test_xfail "$if does not support the required MTU for $step"
+ ktap_print_msg "$if does not support the required MTU for $step"
+ ktap_test_xfail "$TEST_NAME.$step"
return
fi
done
if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then
- check_err 1 "$step failed"
+ ktap_test_fail "$TEST_NAME.$step"
return 1
fi
- log_test "$step"
+ ktap_test_pass "$TEST_NAME.$step"
nbuckets=$((nbuckets + 1))
done < <(ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
if [ "$nbuckets" -eq 0 ]; then
- log_test_xfail "$iface does not support $set histogram counters"
+ ktap_print_msg "$iface does not support $set histogram counters"
return
fi
}
@@ -139,9 +140,16 @@ cleanup()
check_ethtool_counter_group_support
trap cleanup EXIT
+bucket_count=$(ethtool --json -S "${NETIFS[p1]}" --groups rmon | \
+ jq -r '.[0].rmon |
+ "\((."rx-pktsNtoM" | length) +
+ (."tx-pktsNtoM" | length))"')
+ktap_print_header
+ktap_set_plan "$bucket_count"
+
setup_prepare
setup_wait
tests_run
-exit "$EXIT_STATUS"
+ktap_finished
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 07/10] selftests: drivers: hw: replace counter upper limit with UINT32_MAX in rmon test
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
The ethtool_rmon.sh script checks that the number of packets sent /
received during a test matches the expected value with a 1% tolerance.
Since in the next patches this test will gain the capability to also be
run on systems with a single interface where the traffic generator is
accesible through ssh, use the UINT32_MAX as the upper limit. This is
necessary since the same interface will be used also for control traffic
(the ssh commands) as well as the mausezahn generated one.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
---
Changes in v4:
- none
Changes in v3:
- none
Changes in v2:
- patch is new
tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index 80e75b9b40fd..f290ce1832f1 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -12,6 +12,7 @@ NUM_NETIFS=2
lib_dir=$(dirname "$0")
source "$lib_dir"/../../../net/forwarding/lib.sh
+UINT32_MAX=$((2**32 - 1))
ETH_FCS_LEN=4
ETH_HLEN=$((6+6+2))
@@ -64,8 +65,7 @@ bucket_test()
expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx")
- # Allow some extra tolerance for other packets sent by the stack
- [ "$delta" -ge "$expected" ] && [ "$delta" -le $((expected + 100)) ]
+ [ "$delta" -ge "$expected" ] && [ "$delta" -le "$UINT32_MAX" ]
}
rmon_histogram()
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 05/10] selftests: drivers: hw: cleanup shellcheck warnings in the rmon test
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
If run on the ethtool_rmon.sh script, shellcheck generates a bunch of
false positive errors. Suppress those checks that generate them.
Also cleanup the remaining warnings by using double quoting around the
used variables.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
---
Changes in v4:
- split one line to 80 chars
Changes in v3:
- none
Changes in v2:
- patch is new
.../selftests/drivers/net/hw/ethtool_rmon.sh | 54 ++++++++++---------
1 file changed, 29 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index 8f60c1685ad4..13b3760e3a40 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -1,5 +1,7 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
+#shellcheck disable=SC2034 # SC does not see the global variables
+#shellcheck disable=SC2317,SC2329 # unused functions
ALL_TESTS="
rmon_rx_histogram
@@ -19,11 +21,12 @@ ensure_mtu()
{
local iface=$1; shift
local len=$1; shift
- local current=$(ip -j link show dev $iface | jq -r '.[0].mtu')
local required=$((len - ETH_HLEN - ETH_FCS_LEN))
+ local current
- if [ $current -lt $required ]; then
- ip link set dev $iface mtu $required || return 1
+ current=$(ip -j link show dev "$iface" | jq -r '.[0].mtu')
+ if [ "$current" -lt "$required" ]; then
+ ip link set dev "$iface" mtu "$required" || return 1
fi
}
@@ -46,23 +49,23 @@ bucket_test()
len=$((len - ETH_FCS_LEN))
len=$((len > 0 ? len : 0))
- before=$(ethtool --json -S $iface --groups rmon | \
+ before=$(ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
# Send 10k one way and 20k in the other, to detect counters
# mapped to the wrong direction
- $MZ $neigh -q -c $num_rx -p $len -a own -b bcast -d 10us
- $MZ $iface -q -c $num_tx -p $len -a own -b bcast -d 10us
+ "$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us
+ "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
- after=$(ethtool --json -S $iface --groups rmon | \
+ after=$(ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
delta=$((after - before))
- expected=$([ $set = rx ] && echo $num_rx || echo $num_tx)
+ expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx")
# Allow some extra tolerance for other packets sent by the stack
- [ $delta -ge $expected ] && [ $delta -le $((expected + 100)) ]
+ [ "$delta" -ge "$expected" ] && [ "$delta" -le $((expected + 100)) ]
}
rmon_histogram()
@@ -78,23 +81,23 @@ rmon_histogram()
while read -r -a bucket; do
step="$set-pkts${bucket[0]}to${bucket[1]} on $iface"
- for if in $iface $neigh; do
- if ! ensure_mtu $if ${bucket[0]}; then
+ for if in "$iface" "$neigh"; do
+ if ! ensure_mtu "$if" "${bucket[0]}"; then
log_test_xfail "$if does not support the required MTU for $step"
return
fi
done
- if ! bucket_test $iface $neigh $set $nbuckets ${bucket[0]}; then
+ if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then
check_err 1 "$step failed"
return 1
fi
log_test "$step"
nbuckets=$((nbuckets + 1))
- done < <(ethtool --json -S $iface --groups rmon | \
+ done < <(ethtool --json -S "$iface" --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
- if [ $nbuckets -eq 0 ]; then
+ if [ "$nbuckets" -eq 0 ]; then
log_test_xfail "$iface does not support $set histogram counters"
return
fi
@@ -102,14 +105,14 @@ rmon_histogram()
rmon_rx_histogram()
{
- rmon_histogram $h1 $h2 rx
- rmon_histogram $h2 $h1 rx
+ rmon_histogram "$h1" "$h2" rx
+ rmon_histogram "$h2" "$h1" rx
}
rmon_tx_histogram()
{
- rmon_histogram $h1 $h2 tx
- rmon_histogram $h2 $h1 tx
+ rmon_histogram "$h1" "$h2" tx
+ rmon_histogram "$h2" "$h1" tx
}
setup_prepare()
@@ -117,9 +120,10 @@ setup_prepare()
h1=${NETIFS[p1]}
h2=${NETIFS[p2]}
- for iface in $h1 $h2; do
- netif_mtu[$iface]=$(ip -j link show dev $iface | jq -r '.[0].mtu')
- ip link set dev $iface up
+ for iface in "$h1" "$h2"; do
+ netif_mtu["$iface"]=$(ip -j link show dev "$iface" | \
+ jq -r '.[0].mtu')
+ ip link set dev "$iface" up
done
}
@@ -127,9 +131,9 @@ cleanup()
{
pre_cleanup
- for iface in $h2 $h1; do
- ip link set dev $iface \
- mtu ${netif_mtu[$iface]} \
+ for iface in "$h2" "$h1"; do
+ ip link set dev "$iface" \
+ mtu "${netif_mtu[$iface]}" \
down
done
}
@@ -142,4 +146,4 @@ setup_wait
tests_run
-exit $EXIT_STATUS
+exit "$EXIT_STATUS"
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 06/10] selftests: drivers: hw: test rmon counters only on first interface
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
The selftests in drivers/net are slowly transitioning to being able to
be used on systems with a single network interface. The first step for the
ethtool_rmon.sh test is to only validate that the rmon counters are
properly exported on the first interface supplied as an argument.
Remove the rmon_histogram calls which intend to test also the rmon
counters on the 2nd interface. This also removes the need for the remote
system, which should be used only to inject traffic, to also support
rmon counters.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
---
Changes in v4:
- none
Changes in v3:
- none
Changes in v2:
- patch is new
tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh | 2 --
1 file changed, 2 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index 13b3760e3a40..80e75b9b40fd 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -106,13 +106,11 @@ rmon_histogram()
rmon_rx_histogram()
{
rmon_histogram "$h1" "$h2" rx
- rmon_histogram "$h2" "$h1" rx
}
rmon_tx_histogram()
{
rmon_histogram "$h1" "$h2" tx
- rmon_histogram "$h2" "$h1" tx
}
setup_prepare()
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 04/10] selftests: net: update some helpers to use run_on
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Update some helpers so that they are capable to run commands on
different targets than the local one. This patch makes the necesasy
modification for those helpers / sections of code which are needed for
the ethtool_rmon.sh test that will be converted in the next patches.
For example, mac_addr_prepare() and mac_addr_restore() used when
STABLE_MAC_ADDRS=yes need to ensure stable MAC addresses on interfaces
located even in other namespaces. In order to do that, append the 'ip
link' commands with a 'run_on $dev' tag.
The same run_on is necessary also when verifying if all the interfaces
listed in NETIFS are indeed available.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
---
Changes in v4:
- split some lines to 80 chars
Changes in v3:
- added some more double quotes
Changes in v2:
- patch is new
tools/testing/selftests/net/forwarding/lib.sh | 19 ++++++++++++-------
tools/testing/selftests/net/lib.sh | 3 ++-
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index 93b865681840..98434da6e36b 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -506,10 +506,11 @@ mac_addr_prepare()
dev=${NETIFS[p$i]}
new_addr=$(printf "00:01:02:03:04:%02x" $i)
- MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
+ MAC_ADDR_ORIG["$dev"]=$(run_on "$dev" \
+ ip -j link show dev "$dev" | jq -e '.[].address')
# Strip quotes
MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
- ip link set dev $dev address $new_addr
+ run_on "$dev" ip link set dev "$dev" address $new_addr
done
}
@@ -519,7 +520,8 @@ mac_addr_restore()
for ((i = 1; i <= NUM_NETIFS; ++i)); do
dev=${NETIFS[p$i]}
- ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
+ run_on "$dev" \
+ ip link set dev "$dev" address ${MAC_ADDR_ORIG["$dev"]}
done
}
@@ -532,7 +534,9 @@ if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
fi
for ((i = 1; i <= NUM_NETIFS; ++i)); do
- ip link show dev ${NETIFS[p$i]} &> /dev/null
+ int="${NETIFS[p$i]}"
+
+ run_on "$int" ip link show dev "$int" &> /dev/null
if [[ $? -ne 0 ]]; then
echo "SKIP: could not find all required interfaces"
exit $ksft_skip
@@ -615,7 +619,7 @@ setup_wait_dev_with_timeout()
local i
for ((i = 1; i <= $max_iterations; ++i)); do
- ip link show dev $dev up \
+ run_on "$dev" ip link show dev "$dev" up \
| grep 'state UP' &> /dev/null
if [[ $? -ne 0 ]]; then
sleep 1
@@ -920,12 +924,13 @@ ethtool_std_stats_get()
local src=$1; shift
if [[ "$grp" == "pause" ]]; then
- ethtool -I --json -a "$dev" --src "$src" | \
+ run_on "$dev" ethtool -I --json -a "$dev" --src "$src" | \
jq --arg name "$name" '.[].statistics[$name]'
return
fi
- ethtool --json -S "$dev" --groups "$grp" -- --src "$src" | \
+ run_on "$dev" \
+ ethtool --json -S "$dev" --groups "$grp" -- --src "$src" | \
jq --arg grp "$grp" --arg name "$name" '.[][$grp][$name]'
}
diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
index 6c0d613a4de5..ed2291588a67 100644
--- a/tools/testing/selftests/net/lib.sh
+++ b/tools/testing/selftests/net/lib.sh
@@ -514,7 +514,8 @@ mac_get()
{
local if_name=$1
- ip -j link show dev $if_name | jq -r '.[]["address"]'
+ run_on "$if_name" \
+ ip -j link show dev "$if_name" | jq -r '.[]["address"]'
}
kill_process()
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 03/10] selftests: net: extend lib.sh to parse drivers/net/net.config
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Extend lib.sh so that it's able to parse driver/net/net.config and
environment variables such as NETIF, REMOTE_TYPE, LOCAL_V4 etc described
in drivers/net/README.rst.
In order to make the transition towards running with a single local
interface smoother for the bash networking driver tests, beside sourcing
the net.config file also translate the new env variables into the old
style based on the NETIFS array. Since the NETIFS array only holds the
network interface names, also add a new array - TARGETS - which keeps
track of the target on which a specific interfaces resides - local,
netns or accesible through an ssh command.
For example, a net.config which looks like below:
NETIF=eth0
LOCAL_V4=192.168.1.1
REMOTE_V4=192.168.1.2
REMOTE_TYPE=ssh
REMOTE_ARGS=root@192.168.1.2
will generate the NETIFS and TARGETS arrays with the following data.
NETIFS[p1]="eth0"
NETIFS[p2]="eth2"
TARGETS[eth0]="local:"
TARGETS[eth2]="ssh:root@192.168.1.2"
The above will be true if on the remote target, the interface which has
the 192.168.1.2 address is named eth2.
Since the TARGETS array is indexed by the network interface name,
document a new restriction README.rst which states that the remote
interface cannot have the same name as the local one.
Also keep the old way of populating the NETIFS variable based on the
command line arguments. This will be invoked in case NETIF is not
defined.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
---
Changes in v4:
- reword the entry in README.rst to mention that the different interface
names is only a bash restriction and the python infrastructure does
not have the same problem.
- only declare the TARGETS array when necessary
- add a new flags - DRIVER_TEST_CONFORMANT - that needs to be set by the
test
- rework the check_env() function so that its logic is simpler
- source drivers/net/net.config only if DRIVER_TEST_CONFORMANT == yes
- check that NETIF and the remote netif have different names and abort
test is not
Changes in v3:
- s/TARGET/CUR_TARGET
- this used to be patch #2/9 in v2. Swapped the two patches so that the
run_cmd used in this patch is defined earlier, not later.
Changes in v2:
- patch is new
.../testing/selftests/drivers/net/README.rst | 4 +
tools/testing/selftests/net/forwarding/lib.sh | 106 ++++++++++++++++--
2 files changed, 101 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/README.rst b/tools/testing/selftests/drivers/net/README.rst
index c94992acf10b..1897aa1583ec 100644
--- a/tools/testing/selftests/drivers/net/README.rst
+++ b/tools/testing/selftests/drivers/net/README.rst
@@ -26,6 +26,10 @@ The netdevice against which tests will be run must exist, be running
Refer to list of :ref:`Variables` later in this file to set up running
the tests against a real device.
+The current support for bash tests restricts the use of the same interface name
+on the local system and the remote one and will bail if this case is
+encountered.
+
Both modes required
~~~~~~~~~~~~~~~~~~~
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index 3009ce00c5dc..93b865681840 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -3,6 +3,7 @@
##############################################################################
# Topology description. p1 looped back to p2, p3 to p4 and so on.
+#shellcheck disable=SC2034 # SC doesn't see our uses of global variables
declare -A NETIFS=(
[p1]=veth0
@@ -85,6 +86,9 @@ declare -A NETIFS=(
# e.g. a low-power board.
: "${KSFT_MACHINE_SLOW:=no}"
+# Whether the test is conforming to the requirements and usage described in
+# drivers/net/README.rst.
+: "${DRIVER_TEST_CONFORMANT:=no}"
##############################################################################
# Find netifs by test-specified driver name
@@ -340,17 +344,101 @@ fi
##############################################################################
# Command line options handling
-count=0
+check_env() {
+ if [[ ! (( -n "$LOCAL_V4" && -n "$REMOTE_V4") ||
+ ( -n "$LOCAL_V6" && -n "$REMOTE_V6" )) ]]; then
+ echo "SKIP: Invalid environment, missing or inconsistent LOCAL_V4/REMOTE_V4/LOCAL_V6/REMOTE_V6"
+ echo "Please see tools/testing/selftests/drivers/net/README.rst"
+ exit "$ksft_skip"
+ fi
-while [[ $# -gt 0 ]]; do
- if [[ "$count" -eq "0" ]]; then
- unset NETIFS
- declare -A NETIFS
+ if [[ -z "$REMOTE_TYPE" ]]; then
+ echo "SKIP: Invalid environment, missing REMOTE_TYPE"
+ exit "$ksft_skip"
fi
- count=$((count + 1))
- NETIFS[p$count]="$1"
- shift
-done
+
+ if [[ -z "$REMOTE_ARGS" ]]; then
+ echo "SKIP: Invalid environment, missing REMOTE_ARGS"
+ exit "$ksft_skip"
+ fi
+}
+
+get_ifname_by_ip()
+{
+ local target=$1; shift
+ local ip_addr=$1; shift
+
+ __run_on "$target" ip -j addr show to "$ip_addr" | jq -r '.[].ifname'
+}
+
+# Based on DRIVER_TEST_CONFORMANT, decide if to source drivers/net/net.config
+# or not. In the "yes" case, the test expects to pass the arguments through the
+# variables specified in drivers/net/README.rst file. If not, fallback on
+# parsing the script arguments for interface names.
+if [ "${DRIVER_TEST_CONFORMANT}" = "yes" ]; then
+ if [[ -f $net_forwarding_dir/../../drivers/net/net.config ]]; then
+ source "$net_forwarding_dir/../../drivers/net/net.config"
+ fi
+
+ if (( NUM_NETIFS > 2)); then
+ echo "SKIP: DRIVER_TEST_CONFORMANT=yes and NUM_NETIFS is bigger than 2"
+ exit "$ksft_skip"
+ fi
+
+ check_env
+
+ # Populate the NETIFS and TARGETS arrays automatically based on the
+ # environment variables. The TARGETS array is indexed by the network
+ # interface name keeping track of the target on which the interface
+ # resides. Values will be strings of the following format -
+ # <type>:<args>.
+ #
+ # TARGETS[eth0]="local:" - meaning that the eth0 interface is
+ # accessible locally
+ # TARGETS[eth1]="netns:foo" - eth1 is in the foo netns
+ # TARGETS[eth2]="ssh:root@10.0.0.2" - eth2 is accessible through
+ # running the 'ssh root@10.0.0.2' command.
+
+ unset NETIFS
+ declare -A NETIFS
+ declare -A TARGETS
+
+ NETIFS[p1]="$NETIF"
+ TARGETS[$NETIF]="local:"
+
+ # Locate the name of the remote interface
+ remote_target="$REMOTE_TYPE:$REMOTE_ARGS"
+ if [[ -v REMOTE_V4 ]]; then
+ remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V4")
+ else
+ remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V6")
+ fi
+ if [[ ! -n "$remote_netif" ]]; then
+ echo "SKIP: cannot find remote interface"
+ exit "$ksft_skip"
+ fi
+
+ if [[ "$NETIF" == "$remote_netif" ]]; then
+ echo "SKIP: local and remote interfaces cannot have the same name"
+ exit "$ksft_skip"
+ fi
+
+ NETIFS[p2]="$remote_netif"
+ TARGETS[$remote_netif]="$REMOTE_TYPE:$REMOTE_ARGS"
+else
+ count=0
+
+ while [[ $# -gt 0 ]]; do
+ if [[ "$count" -eq "0" ]]; then
+ unset NETIFS
+ declare -A NETIFS
+ fi
+ count=$((count + 1))
+ NETIFS[p$count]="$1"
+ TARGETS[$1]="local:"
+ shift
+ done
+fi
##############################################################################
# Network interfaces configuration
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 02/10] selftests: net: add helpers for running a command on other targets
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Add a couple of helpers which can be used by tests which need to run a
specific bash command on a different target than the local system, be it
either another netns or a remote system accessible through ssh.
The __run_on() function is passed through $1 the target on which the
command should be executed while run_on() is passed the name of the
interface that is then used to retrieve the target from the TARGETS
array.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
---
Changes in v4:
- reworked the helpers so that no global variable is used and
information is passed only through parameters
Changes in v3:
- s/TARGET/CUR_TARGET
- always fallback on running a command locally when either TARGETS is
not declared or there is no entry for a specific interface
Changes in v2:
- patch is new
tools/testing/selftests/net/lib.sh | 38 ++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
index b40694573f4c..6c0d613a4de5 100644
--- a/tools/testing/selftests/net/lib.sh
+++ b/tools/testing/selftests/net/lib.sh
@@ -670,3 +670,41 @@ cmd_jq()
# return success only in case of non-empty output
[ ! -z "$output" ]
}
+
+__run_on()
+{
+ local target=$1; shift
+ local type args
+
+ IFS=':' read -r type args <<< "$target"
+
+ case "$type" in
+ netns)
+ # Execute command in network namespace
+ # args contains the namespace name
+ ip netns exec "$args" "$@"
+ ;;
+ ssh)
+ # Execute command via SSH args contains user@host
+ ssh -n "$args" "$@"
+ ;;
+ local|*)
+ # Execute command locally. This is also the fallback
+ # case for when the interface's target is not found in
+ # the TARGETS array.
+ "$@"
+ ;;
+ esac
+}
+
+run_on()
+{
+ local iface=$1; shift
+ local target="local:"
+
+ if declare -p TARGETS &>/dev/null; then
+ target="${TARGETS[$iface]}"
+ fi
+
+ __run_on "$target" "$@"
+}
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 01/10] selftests: forwarding: extend ethtool_std_stats_get with pause statistics
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
In-Reply-To: <20260326132828.805703-1-ioana.ciornei@nxp.com>
Even though pause frame statistics are not exported through the same
ethtool command, there is no point in adding another helper just for
them. Extent the ethtool_std_stats_get() function so that we are able to
interrogate using the same helper all the standard statistics.
And since we are touching the function, convert the initial ethtool call
as well to the jq --arg form in order to be easier to read.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
---
Changes in v4:
- wrap the lines to max 80 chars
- replace the if-else with a simple if and return in order to be easier
to maintain the 80 chars limit.
Changes in v3:
- none
Changes in v2:
- convert jq to the --arg usage form
tools/testing/selftests/net/forwarding/lib.sh | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index a9034f0bb58b..3009ce00c5dc 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -831,8 +831,14 @@ ethtool_std_stats_get()
local name=$1; shift
local src=$1; shift
- ethtool --json -S $dev --groups $grp -- --src $src | \
- jq '.[]."'"$grp"'"."'$name'"'
+ if [[ "$grp" == "pause" ]]; then
+ ethtool -I --json -a "$dev" --src "$src" | \
+ jq --arg name "$name" '.[].statistics[$name]'
+ return
+ fi
+
+ ethtool --json -S "$dev" --groups "$grp" -- --src "$src" | \
+ jq --arg grp "$grp" --arg name "$name" '.[][$grp][$name]'
}
qdisc_stats_get()
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v4 00/10] selftests: drivers: bash support for remote traffic generators
From: Ioana Ciornei @ 2026-03-26 13:28 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, linux-kernel, petrm, willemb,
linux-kselftest
This patch set aims to add the necessary support so that bash written
selftests are also able to easily run with a remote traffic generator
system, either be it in another netns or one accessible through ssh.
This patch set is a result of the discussion from v1:
https://lore.kernel.org/all/20260303084330.340b6459@kernel.org/
Even though the python infrastructure is already established, some
things are easier in bash and it would be a shame to leave behind the
bash tests that we already have.
This support is based on the requirements described in the
tools/testing/selftests/drivers/net/README.rst file.
Mainly, the drivers/net selftests should be able to run on a interface
specified through the NETIF env variable. On top of that, variables such
as REMOTE_TYPE and REMOTE_ARGS define how the remote traffic generator
can be accessed. Patch 3/10 parses these env variables and constructs the
NETIFS array that bash tests are accustomed to. This is with the
intention of enabling already written tests to incur minimal changes.
The second patch also defines the TARGETS array which will hold the
necessary information about the target on which a specific interface
is located.
For example, a net.config which looks like below:
NETIF=eth0
LOCAL_V4=192.168.1.1
REMOTE_V4=192.168.1.2
REMOTE_TYPE=ssh
REMOTE_ARGS=root@192.168.1.2
will generate the NETIFS and TARGETS arrays with the following data.
NETIFS[p1]="eth0"
NETIFS[p2]="eth2"
TARGETS[eth0]="local:"
TARGETS[eth2]="ssh:root@192.168.1.2"
The above will be true if on the remote target, the interface which has
the 192.168.1.2 address is named eth2.
The values held in the TARGETS array will be used by the new 'run_on'
helper added in patch 2/10 to know how to run a specific command, on the
local system, on another netns or by using ssh. Patch 4/10 updates some
helpers to use run_on so that, for example, lib.sh is able to ensure
stable MAC addresses even with the remote interface located in another
netns.
The next 5 patches, 5/10-9/10 update the ethtool_rmon.sh script so that it
can work with the kselftest infrastructure and the new
NETIF/REMOTE_TYPE etc way of working. Beside updating each ip link or
ethtool command to use the run_on helper, the patches also remove any
testing done on the remote interface.
The last patch adds a new test which checks the standard counters -
eth-ctrl, eth-mac and pause - and uses the new infrastructure put in
place by the first patches.
With this patch set, both tests can be run using a net.config file and
run_kselftest.sh as shown below.
$ make -C tools/testing/selftests/ TARGETS="drivers/net drivers/net/hw" \
install INSTALL_PATH=/tmp/ksft-net-drv
$ cd /tmp/ksft-net-drv/
$ cat > ./drivers/net/net.config <<EOF
NETIF=endpmac17
LOCAL_V4=17.0.0.1
REMOTE_V4=17.0.0.2
REMOTE_TYPE=ssh
REMOTE_ARGS=root@192.168.5.200
EOF
$ ./run_kselftest.sh -t drivers/net/hw:ethtool_rmon.sh
TAP version 13
1..1
# timeout set to 0
# selftests: drivers/net/hw: ethtool_rmon.sh
# TAP version 13
# 1..14
# ok 1 ethtool_rmon.rx-pkts64to64
# ok 2 ethtool_rmon.rx-pkts65to127
# ok 3 ethtool_rmon.rx-pkts128to255
# ok 4 ethtool_rmon.rx-pkts256to511
# ok 5 ethtool_rmon.rx-pkts512to1023
# ok 6 ethtool_rmon.rx-pkts1024to1518
# ok 7 ethtool_rmon.rx-pkts1519to10240
# ok 8 ethtool_rmon.tx-pkts64to64
# ok 9 ethtool_rmon.tx-pkts65to127
# ok 10 ethtool_rmon.tx-pkts128to255
# ok 11 ethtool_rmon.tx-pkts256to511
# ok 12 ethtool_rmon.tx-pkts512to1023
# ok 13 ethtool_rmon.tx-pkts1024to1518
# ok 14 ethtool_rmon.tx-pkts1519to10240
# # Totals: pass:14 fail:0 xfail:0 xpass:0 skip:0 error:0
ok 1 selftests: drivers/net/hw: ethtool_rmon.sh
$ ./run_kselftest.sh -t drivers/net/hw:ethtool_std_stats.sh
TAP version 13
1..1
# timeout set to 0
# selftests: drivers/net/hw: ethtool_std_stats.sh
# TAP version 13
# 1..26
# ok 1 ethtool_std_stats.eth-ctrl-MACControlFramesTransmitted
# ok 2 ethtool_std_stats.eth-ctrl-MACControlFramesReceived
# ok 3 ethtool_std_stats.eth-mac-FrameCheckSequenceErrors
# ok 4 ethtool_std_stats.eth-mac-AlignmentErrors
# ok 5 ethtool_std_stats.eth-mac-FramesLostDueToIntMACXmitError
# ok 6 ethtool_std_stats.eth-mac-CarrierSenseErrors # SKIP
# ok 7 ethtool_std_stats.eth-mac-FramesLostDueToIntMACRcvError
# ok 8 ethtool_std_stats.eth-mac-InRangeLengthErrors # SKIP
# ok 9 ethtool_std_stats.eth-mac-OutOfRangeLengthField # SKIP
# ok 10 ethtool_std_stats.eth-mac-FrameTooLongErrors # SKIP
# ok 11 ethtool_std_stats.eth-mac-FramesAbortedDueToXSColls # SKIP
# ok 12 ethtool_std_stats.eth-mac-SingleCollisionFrames # SKIP
# ok 13 ethtool_std_stats.eth-mac-MultipleCollisionFrames # SKIP
# ok 14 ethtool_std_stats.eth-mac-FramesWithDeferredXmissions # SKIP
# ok 15 ethtool_std_stats.eth-mac-LateCollisions # SKIP
# ok 16 ethtool_std_stats.eth-mac-FramesWithExcessiveDeferral # SKIP
# ok 17 ethtool_std_stats.eth-mac-BroadcastFramesXmittedOK
# ok 18 ethtool_std_stats.eth-mac-OctetsTransmittedOK
# ok 19 ethtool_std_stats.eth-mac-BroadcastFramesReceivedOK
# ok 20 ethtool_std_stats.eth-mac-OctetsReceivedOK
# ok 21 ethtool_std_stats.eth-mac-FramesTransmittedOK
# ok 22 ethtool_std_stats.eth-mac-MulticastFramesXmittedOK
# ok 23 ethtool_std_stats.eth-mac-FramesReceivedOK
# ok 24 ethtool_std_stats.eth-mac-MulticastFramesReceivedOK
# ok 25 ethtool_std_stats.pause-tx_pause_frames
# ok 26 ethtool_std_stats.pause-rx_pause_frames
# # 10 skipped test(s) detected. Consider enabling relevant config options to improve coverage.
# # Totals: pass:16 fail:0 xfail:0 xpass:0 skip:10 error:0
ok 1 selftests: drivers/net/hw: ethtool_std_stats.sh
Changes in v4:
- 1/10: wrap the lines to max 80 chars
- 1/10: replace the if-else with a simple if and return in order to be
easier to maintain the 80 chars limit.
- 2/10: reworked the helpers so that no global variable is used and
information is passed only through parameters
- 3/10: reword the entry in README.rst to mention that the different
interface names is only a bash restriction and the python
infrastructure does not have the same problem.
- 3/10: only declare the TARGETS array when necessary
- 3/10: add a new flags - DRIVER_TEST_CONFORMANT - that needs to be set
by the test
- 3/10: rework the check_env() function so that its logic is simpler
- 3/10: source drivers/net/net.config only if DRIVER_TEST_CONFORMANT ==
yes
- 3/10: check that NETIF and the remote netif have different names and
abort test is not
- 4/10: split some lines to 80 chars
- 5/10: split one line to 80 chars
- 8/10: patch is added in this version so that ethtool_rmon.sh is
converted to KTAP output
- 9/10: set DRIVER_TEST_CONFORMANT to yes
- 9/10: update the commit message to reflect the current output
- 9/10: split some more lines to 80 chars
- 10/10: move to a the KTAP format output by using ktap_helpers.sh
- 10/10: update commit message to reflect the current output
- 10/10: use DRIVER_TEST_CONFORMANT
Changes in v3:
- Change the TARGET variable into CUR_TARGET
- Always fallback on running a command locally when either TARGETS is
not declared or there is no entry for a specific interface
- Swap patches 2 & 3 between them so that the run_cmd used in now patch
#2 is defined in patch #2
- Add some more double quoting
Changes in v2:
- 1/9: Convert jq to the --arg usage form
- Patches 2/9-8/9 are new in this version
- 9/9: Use the new run_on helper
- 9/9: No longer checking that each counter has a 1% tolerance against the
target. The only upper limit is UINT32_MAX.
- 9/9: Check that both the error counters and the collision related ones are
zero since this is the most probable scenario (we don't expect errors
with the traffic that we are sending).
- 9/9: Removed any checks performed on the remot interface counters since
that is being used only as a traffic generator.
Ioana Ciornei (10):
selftests: forwarding: extend ethtool_std_stats_get with pause
statistics
selftests: net: add helpers for running a command on other targets
selftests: net: extend lib.sh to parse drivers/net/net.config
selftests: net: update some helpers to use run_on
selftests: drivers: hw: cleanup shellcheck warnings in the rmon test
selftests: drivers: hw: test rmon counters only on first interface
selftests: drivers: hw: replace counter upper limit with UINT32_MAX in
rmon test
selftests: drivers: hw: move to KTAP output
selftests: drivers: hw: update ethtool_rmon to work with a single
local interface
selftests: drivers: hw: add test for the ethtool standard counters
.../testing/selftests/drivers/net/README.rst | 4 +
.../testing/selftests/drivers/net/hw/Makefile | 1 +
.../selftests/drivers/net/hw/ethtool_rmon.sh | 82 ++++---
.../drivers/net/hw/ethtool_std_stats.sh | 206 ++++++++++++++++++
tools/testing/selftests/net/forwarding/lib.sh | 131 +++++++++--
tools/testing/selftests/net/lib.sh | 41 +++-
6 files changed, 414 insertions(+), 51 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
--
2.25.1
^ permalink raw reply
* RE: [PATCH net-next v4 3/3] r8152: add helper functions for PHY OCP registers
From: Hayes Wang @ 2026-03-26 13:19 UTC (permalink / raw)
To: Chih Kai Hsu, kuba@kernel.org, davem@davemloft.net
Cc: netdev@vger.kernel.org, nic_swsd, linux-kernel@vger.kernel.org,
linux-usb@vger.kernel.org, edumazet@google.com, bjorn@mork.no,
pabeni@redhat.com, Chih Kai Hsu
In-Reply-To: <20260326073925.32976-456-nic_swsd@realtek.com>
Chih Kai Hsu <hsu.chih.kai@realtek.com>
> Sent: Thursday, March 26, 2026 3:39 PM
> To: kuba@kernel.org; davem@davemloft.net
> Cc: netdev@vger.kernel.org; nic_swsd <nic_swsd@realtek.com>;
> linux-kernel@vger.kernel.org; linux-usb@vger.kernel.org;
> edumazet@google.com; bjorn@mork.no; pabeni@redhat.com; Chih Kai Hsu
> <hsu.chih.kai@realtek.com>
> Subject: [PATCH net-next v4 3/3] r8152: add helper functions for PHY OCP
> registers
>
> Add the following bitwise operation functions for PHY OCP registers to simplify
> the code.
>
> - ocp_reg_w0w1()
> - ocp_reg_clr_bits()
> - ocp_reg_set_bits()
> - sram_write_w0w1()
> - sram_clr_bits()
> - sram_set_bits()
> - r8152_mdio_clr_bit()
> - r8152_mdio_set_bit()
> - r8152_mdio_test_and_clr_bit()
>
> In addition, remove variable set but not used from r8153_init(),
> r8153b_init() and r8153c_init().
>
> Signed-off-by: Chih Kai Hsu <hsu.chih.kai@realtek.com>
Reviewed-by: Hayes Wang <hayeswang@realtek.com>
Best Regards,
Hayes
^ permalink raw reply
* [PATCH net v3 11/11] rxrpc: Fix to request an ack if window is limited
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Marc Dionne,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Marc Dionne <marc.c.dionne@gmail.com>
Peers may only send immediate acks for every 2 UDP packets received.
When sending a jumbogram, it is important to check that there is
sufficient window space to send another same sized jumbogram following
the current one, and request an ack if there isn't. Failure to do so may
cause the call to stall waiting for an ack until the resend timer fires.
Where jumbograms are in use this causes a very significant drop in
performance.
Fixes: fe24a5494390 ("rxrpc: Send jumbo DATA packets")
Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/ar-internal.h | 2 +-
net/rxrpc/output.c | 2 ++
net/rxrpc/proc.c | 5 +++--
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 5edad6a624ad..792d0f944fc2 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -521,6 +521,7 @@
#define rxrpc_req_ack_traces \
EM(rxrpc_reqack_ack_lost, "ACK-LOST ") \
EM(rxrpc_reqack_app_stall, "APP-STALL ") \
+ EM(rxrpc_reqack_jumbo_win, "JUMBO-WIN ") \
EM(rxrpc_reqack_more_rtt, "MORE-RTT ") \
EM(rxrpc_reqack_no_srv_last, "NO-SRVLAST") \
EM(rxrpc_reqack_old_rtt, "OLD-RTT ") \
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 36d6ca0d1089..96ecb83c9071 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -117,7 +117,7 @@ struct rxrpc_net {
atomic_t stat_tx_jumbo[10];
atomic_t stat_rx_jumbo[10];
- atomic_t stat_why_req_ack[8];
+ atomic_t stat_why_req_ack[9];
atomic_t stat_io_loop;
};
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index d70db367e358..870e59bf06af 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -479,6 +479,8 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call,
why = rxrpc_reqack_old_rtt;
else if (!last && !after(READ_ONCE(call->send_top), txb->seq))
why = rxrpc_reqack_app_stall;
+ else if (call->tx_winsize <= (2 * req->n) || call->cong_cwnd <= (2 * req->n))
+ why = rxrpc_reqack_jumbo_win;
else
goto dont_set_request_ack;
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 59292f7f9205..7755fca5beb8 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -518,11 +518,12 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]),
atomic_read(&rxnet->stat_rx_acks[0]));
seq_printf(seq,
- "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u\n",
+ "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u jwin=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]),
- atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]));
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]),
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_jumbo_win]));
seq_printf(seq,
"Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]),
^ permalink raw reply related
* [PATCH net v3 10/11] rxrpc: Fix key reference count leak from call->key
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Anderson Nascimento, Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Anderson Nascimento <anderson@allelesecurity.com>
When creating a client call in rxrpc_alloc_client_call(), the code obtains
a reference to the key. This is never cleaned up and gets leaked when the
call is destroyed.
Fix this by freeing call->key in rxrpc_destroy_call().
Before the patch, it shows the key reference counter elevated:
$ cat /proc/keys | grep afs@54321
1bffe9cd I--Q--i 8053480 4169w 3b010000 1000 1000 rxrpc afs@54321: ka
$
After the patch, the invalidated key is removed when the code exits:
$ cat /proc/keys | grep afs@54321
$
Fixes: f3441d4125fc ("rxrpc: Copy client call parameters into rxrpc_call earlier")
Signed-off-by: Anderson Nascimento <anderson@allelesecurity.com>
Co-developed-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/call_object.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 0e47751d5937..57c15aa1e9b5 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -694,6 +694,7 @@ static void rxrpc_destroy_call(struct work_struct *work)
rxrpc_put_bundle(call->bundle, rxrpc_bundle_put_call);
rxrpc_put_peer(call->peer, rxrpc_peer_put_call);
rxrpc_put_local(call->local, rxrpc_local_put_call);
+ key_put(call->key);
call_rcu(&call->rcu, rxrpc_rcu_free_call);
}
^ permalink raw reply related
* [PATCH net v3 09/11] rxrpc: Fix keyring reference count leak in rxrpc_setsockopt()
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Anderson Nascimento, Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Anderson Nascimento <anderson@allelesecurity.com>
In rxrpc_setsockopt(), the code checks 'rx->key' when handling the
RXRPC_SECURITY_KEYRING option. However, this appears to be a logic error.
The code should be checking 'rx->securities' to determine if a keyring has
already been defined for the socket.
Currently, if a user calls setsockopt(RXRPC_SECURITY_KEYRING) multiple
times on the same socket, the check 'if (rx->key)' fails to block
subsequent calls because 'rx->key' has not been defined by the function.
This results in a reference count leak on the keyring.
This patch changes the check to 'rx->securities' to correctly identify if
the socket security keyring has already been configured, returning -EINVAL
on subsequent attempts.
Before the patch:
It shows the keyring reference counter elevated.
$ cat /proc/keys | grep AFSkeys1
27aca8ae I--Q--- 24469721 perm 3f010000 1000 1000 keyring AFSkeys1: empty
$
After the patch:
The keyring reference counter remains stable and subsequent calls return an
error:
$ ./poc
setsockopt: Invalid argument
$
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Signed-off-by: Anderson Nascimento <anderson@allelesecurity.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/af_rxrpc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0f90272ac254..0b7ed99a3025 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -665,7 +665,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
case RXRPC_SECURITY_KEYRING:
ret = -EINVAL;
- if (rx->key)
+ if (rx->securities)
goto error;
ret = -EISCONN;
if (rx->sk.sk_state != RXRPC_UNBOUND)
^ permalink raw reply related
* [PATCH net v3 08/11] rxrpc: Fix rack timer warning to report unexpected mode
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Alok Tiwari,
Simon Horman, Jeffrey Altman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Alok Tiwari <alok.a.tiwari@oracle.com>
rxrpc_rack_timer_expired() clears call->rack_timer_mode to OFF before
the switch. The default case warning therefore always prints OFF and
doesn't identify the unexpected timer mode.
Log the saved mode value instead so the warning reports the actual
unexpected rack timer mode.
Fixes: 7c482665931b ("rxrpc: Implement RACK/TLP to deal with transmission stalls [RFC8985]")
Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/input_rack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/input_rack.c b/net/rxrpc/input_rack.c
index 13c371261e0a..9eb109ffba56 100644
--- a/net/rxrpc/input_rack.c
+++ b/net/rxrpc/input_rack.c
@@ -413,6 +413,6 @@ void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by)
break;
//case RXRPC_CALL_RACKTIMER_ZEROWIN:
default:
- pr_warn("Unexpected rack timer %u", call->rack_timer_mode);
+ pr_warn("Unexpected rack timer %u", mode);
}
}
^ permalink raw reply related
* [PATCH net v3 07/11] rxrpc: Fix use of wrong skb when comparing queued RESP challenge serial
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Alok Tiwari,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Alok Tiwari <alok.a.tiwari@oracle.com>
In rxrpc_post_response(), the code should be comparing the challenge serial
number from the cached response before deciding to switch to a newer
response, but looks at the newer packet private data instead, rendering the
comparison always false.
Fix this by switching to look at the older packet.
Fix further[1] to substitute the new packet in place of the old one if
newer and also to release whichever we don't use.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
Link: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com [1]
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/conn_event.c | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 869f97c9bf73..5edad6a624ad 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -185,6 +185,7 @@
EM(rxrpc_skb_put_input, "PUT input ") \
EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \
EM(rxrpc_skb_put_oob, "PUT oob ") \
+ EM(rxrpc_skb_put_old_response, "PUT old-resp ") \
EM(rxrpc_skb_put_purge, "PUT purge ") \
EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \
EM(rxrpc_skb_put_response, "PUT response ") \
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 98ad9b51ca2c..c50cbfc5a313 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -557,11 +557,11 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
spin_lock_irq(&local->lock);
old = conn->tx_response;
if (old) {
- struct rxrpc_skb_priv *osp = rxrpc_skb(skb);
+ struct rxrpc_skb_priv *osp = rxrpc_skb(old);
/* Always go with the response to the most recent challenge. */
if (after(sp->resp.challenge_serial, osp->resp.challenge_serial))
- conn->tx_response = old;
+ conn->tx_response = skb;
else
old = skb;
} else {
@@ -569,4 +569,5 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
}
spin_unlock_irq(&local->lock);
rxrpc_poke_conn(conn, rxrpc_conn_get_poke_response);
+ rxrpc_free_skb(old, rxrpc_skb_put_old_response);
}
^ permalink raw reply related
* RE: [PATCH net-next v4 2/3] r8152: add helper functions for PLA/USB OCP registers
From: Hayes Wang @ 2026-03-26 13:19 UTC (permalink / raw)
To: Chih Kai Hsu, kuba@kernel.org, davem@davemloft.net
Cc: netdev@vger.kernel.org, nic_swsd, linux-kernel@vger.kernel.org,
linux-usb@vger.kernel.org, edumazet@google.com, bjorn@mork.no,
pabeni@redhat.com, Chih Kai Hsu
In-Reply-To: <20260326073925.32976-455-nic_swsd@realtek.com>
Chih Kai Hsu <hsu.chih.kai@realtek.com>
> Sent: Thursday, March 26, 2026 3:39 PM
> To: kuba@kernel.org; davem@davemloft.net
> Cc: netdev@vger.kernel.org; nic_swsd <nic_swsd@realtek.com>;
> linux-kernel@vger.kernel.org; linux-usb@vger.kernel.org;
> edumazet@google.com; bjorn@mork.no; pabeni@redhat.com; Chih Kai Hsu
> <hsu.chih.kai@realtek.com>
> Subject: [PATCH net-next v4 2/3] r8152: add helper functions for PLA/USB OCP
> registers
>
> Add the following bitwise operation functions for PLA/USB OCP registers
> to simplify the code.
>
> - ocp_dword_w0w1()
> - ocp_word_w0w1()
> - ocp_byte_w0w1()
> - ocp_dword_clr_bits()
> - ocp_dword_set_bits()
> - ocp_word_clr_bits()
> - ocp_word_set_bits()
> - ocp_word_test_and_clr_bits()
> - ocp_byte_clr_bits()
> - ocp_byte_set_bits()
>
> Signed-off-by: Chih Kai Hsu <hsu.chih.kai@realtek.com>
Reviewed-by: Hayes Wang <hayeswang@realtek.com>
Best Regards,
Hayes
^ permalink raw reply
* [PATCH net v3 06/11] rxrpc: Fix RxGK token loading to check bounds
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Oleh Konko,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
From: Oleh Konko <security@1seal.org>
rxrpc_preparse_xdr_yfs_rxgk() reads the raw key length and ticket length
from the XDR token as u32 values and passes each through round_up(x, 4)
before using the rounded value for validation and allocation. When the raw
length is >= 0xfffffffd, round_up() wraps to 0, so the bounds check and
kzalloc both use 0 while the subsequent memcpy still copies the original
~4 GiB value, producing a heap buffer overflow reachable from an
unprivileged add_key() call.
Fix this by:
(1) Rejecting raw key lengths above AFSTOKEN_GK_KEY_MAX and raw ticket
lengths above AFSTOKEN_GK_TOKEN_MAX before rounding, consistent with
the caps that the RxKAD path already enforces via AFSTOKEN_RK_TIX_MAX.
(2) Sizing the flexible-array allocation from the validated raw key
length via struct_size_t() instead of the rounded value.
(3) Caching the raw lengths so that the later field assignments and
memcpy calls do not re-read from the token, eliminating a class of
TOCTOU re-parse.
The control path (valid token with lengths within bounds) is unaffected.
Fixes: 0ca100ff4df6 ("rxrpc: Add YFS RxGK (GSSAPI) security class")
Signed-off-by: Oleh Konko <security@1seal.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/key.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 26d4336a4a02..77237a82be3b 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -13,6 +13,7 @@
#include <crypto/skcipher.h>
#include <linux/module.h>
#include <linux/net.h>
+#include <linux/overflow.h>
#include <linux/skbuff.h>
#include <linux/key-type.h>
#include <linux/ctype.h>
@@ -171,7 +172,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
size_t plen;
const __be32 *ticket, *key;
s64 tmp;
- u32 tktlen, keylen;
+ size_t raw_keylen, raw_tktlen, keylen, tktlen;
_enter(",{%x,%x,%x,%x},%x",
ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -181,18 +182,22 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
goto reject;
key = xdr + (6 * 2 + 1);
- keylen = ntohl(key[-1]);
- _debug("keylen: %x", keylen);
- keylen = round_up(keylen, 4);
+ raw_keylen = ntohl(key[-1]);
+ _debug("keylen: %zx", raw_keylen);
+ if (raw_keylen > AFSTOKEN_GK_KEY_MAX)
+ goto reject;
+ keylen = round_up(raw_keylen, 4);
if ((6 * 2 + 2) * 4 + keylen > toklen)
goto reject;
ticket = xdr + (6 * 2 + 1 + (keylen / 4) + 1);
- tktlen = ntohl(ticket[-1]);
- _debug("tktlen: %x", tktlen);
- tktlen = round_up(tktlen, 4);
+ raw_tktlen = ntohl(ticket[-1]);
+ _debug("tktlen: %zx", raw_tktlen);
+ if (raw_tktlen > AFSTOKEN_GK_TOKEN_MAX)
+ goto reject;
+ tktlen = round_up(raw_tktlen, 4);
if ((6 * 2 + 2) * 4 + keylen + tktlen != toklen) {
- kleave(" = -EKEYREJECTED [%x!=%x, %x,%x]",
+ kleave(" = -EKEYREJECTED [%zx!=%x, %zx,%zx]",
(6 * 2 + 2) * 4 + keylen + tktlen, toklen,
keylen, tktlen);
goto reject;
@@ -206,7 +211,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
if (!token)
goto nomem;
- token->rxgk = kzalloc(sizeof(*token->rxgk) + keylen, GFP_KERNEL);
+ token->rxgk = kzalloc(struct_size_t(struct rxgk_key, _key, raw_keylen), GFP_KERNEL);
if (!token->rxgk)
goto nomem_token;
@@ -221,9 +226,9 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
token->rxgk->enctype = tmp = xdr_dec64(xdr + 5 * 2);
if (tmp < 0 || tmp > UINT_MAX)
goto reject_token;
- token->rxgk->key.len = ntohl(key[-1]);
+ token->rxgk->key.len = raw_keylen;
token->rxgk->key.data = token->rxgk->_key;
- token->rxgk->ticket.len = ntohl(ticket[-1]);
+ token->rxgk->ticket.len = raw_tktlen;
if (token->rxgk->endtime != 0) {
expiry = rxrpc_s64_to_time64(token->rxgk->endtime);
@@ -236,8 +241,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
memcpy(token->rxgk->key.data, key, token->rxgk->key.len);
/* Pad the ticket so that we can use it directly in XDR */
- token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
- GFP_KERNEL);
+ token->rxgk->ticket.data = kzalloc(tktlen, GFP_KERNEL);
if (!token->rxgk->ticket.data)
goto nomem_yrxgk;
memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
^ permalink raw reply related
* [PATCH net v3 05/11] rxrpc: Fix call removal to use RCU safe deletion
From: David Howells @ 2026-03-26 13:18 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260326131838.634095-1-dhowells@redhat.com>
Fix rxrpc call removal from the rxnet->calls list to use list_del_rcu()
rather than list_del_init() to prevent stuffing up reading
/proc/net/rxrpc/calls from potentially getting into an infinite loop.
Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/call_object.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 918f41d97a2f..0e47751d5937 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -654,9 +654,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)
if (dead) {
ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE);
- if (!list_empty(&call->link)) {
+ if (on_list_rcu(&call->link)) {
spin_lock(&rxnet->call_lock);
- list_del_init(&call->link);
+ list_del_rcu(&call->link);
spin_unlock(&rxnet->call_lock);
}
@@ -738,7 +738,7 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
_debug("Zapping call %p", call);
rxrpc_see_call(call, rxrpc_call_see_zap);
- list_del_init(&call->link);
+ list_del_rcu(&call->link);
pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
call, refcount_read(&call->ref),
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox