* Re: [PATCH v4 0/9] driver core: Fix some race conditions
From: Greg Kroah-Hartman @ 2026-04-05 5:27 UTC (permalink / raw)
To: Douglas Anderson
Cc: Rafael J . Wysocki, Danilo Krummrich, Alan Stern, Saravana Kannan,
Christoph Hellwig, Eric Dumazet, Johan Hovold, Leon Romanovsky,
Alexander Lobakin, Alexey Kardashevskiy, Robin Murphy,
Andrew Morton, Frank.Li, Jason Gunthorpe, alex, alexander.stein,
andre.przywara, andrew, andrew, andriy.shevchenko, aou, ardb,
bhelgaas, brgl, broonie, catalin.marinas, chleroy, davem, david,
devicetree, dmaengine, driver-core, gbatra, gregory.clement,
hkallweit1, iommu, jirislaby, joel, joro, kees, kevin.brodsky,
kuba, lenb, lgirdwood, linux-acpi, linux-arm-kernel, linux-aspeed,
linux-cxl, linux-kernel, linux-mips, linux-mm, linux-pci,
linux-riscv, linux-serial, linux-snps-arc, linux-usb, linux,
linuxppc-dev, m.szyprowski, maddy, mani, maz, miko.lenczewski,
mpe, netdev, npiggin, osalvador, oupton, pabeni, palmer,
peter.ujfalusi, peterz, pjw, robh, sebastian.hesselbarth, tglx,
tsbogend, vgupta, vkoul, will, willy, yangyicong, yeoreum.yun
In-Reply-To: <20260404000644.522677-1-dianders@chromium.org>
On Fri, Apr 03, 2026 at 05:04:54PM -0700, Douglas Anderson wrote:
> NOTE: one potentially "controversial" choice I made in some patches
> was to always reserve a flag ID even if a flag is only used under
> certain CONFIG_ settings. This is a change from how things were
> before. Keeping the numbering consistent and allowing easy
> compile-testing of both CONFIG settings seemed worth it, especially
> since it won't take up any extra space until we've added a lot more
> flags.
Nah, this is fine, I don't see any problems with this as the original
code kind of was doing the same thing with the "hole" in the structure
if those options were not enabled.
> I only marked the first patch as a "Fix" since it is the only one
> fixing observed problems. Other patches could be considered fixes too
> if folks want.
>
> I tested the first patch in the series backported to kernel 6.6 on the
> Pixel phone that was experiencing the race. I added extra printouts to
> make sure that the problem was hitting / addressed. The rest of the
> patches are tested with allmodconfig with arm32, arm64, ppc, and
> x86. I boot tested on an arm64 Chromebook running mainline.
I'm guessing your tests passed? :)
Anyway, this looks great, unless there are any objections, other than
the "needs to be undefined", which a follow-on patch can handle, I'll
queue them up next week for 7.1-rc1.
thanks,
greg k-h
^ permalink raw reply
* [PATCH net 1/1] tipc: validate Gap ACK blocks in STATE message
From: Ren Wei @ 2026-04-05 4:54 UTC (permalink / raw)
To: netdev
Cc: jmaloy, davem, edumazet, kuba, pabeni, horms, ying.xue,
tuong.t.lien, yifanwucs, tomapufckgml, yuantan098, bird,
enjou1224z, caoruide123, n05ec
In-Reply-To: <cover.1775269941.git.caoruide123@gmail.com>
From: Ruide Cao <caoruide123@gmail.com>
tipc_get_gap_ack_blks() reads len, ugack_cnt and bgack_cnt directly from
msg_data(hdr) before verifying that a STATE message actually contains the
fixed Gap ACK block header in its logical data area.
A peer that negotiates TIPC_GAP_ACK_BLOCK can send a short STATE message
with a declared TIPC payload shorter than struct tipc_gap_ack_blks and
still append a few physical bytes after the header. The helper then trusts
those bytes as Gap ACK metadata, and the forged bgack_cnt/len values can
drive the broadcast receive path into kmemdup() beyond the skb boundary.
Fix this by rejecting Gap ACK parsing unless the logical STATE payload is
large enough to cover the fixed header, and by rejecting declared Gap ACK
lengths that are smaller than the fixed header or larger than the logical
payload. Return 0 for invalid lengths so callers do not treat malformed Gap
ACK data as monitor payload offset, while preserving the declared size for
valid but unused Gap ACK records. This keeps malformed Gap ACK data ignored
without misaligning monitor payload parsing in unicast STATE messages.
Fixes: d7626b5acff9 ("tipc: introduce Gap ACK blocks for broadcast link")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Ruide Cao <caoruide123@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/tipc/link.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 49dfc098d89b..a364822c1cd8 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1415,12 +1415,20 @@ u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l,
struct tipc_msg *hdr, bool uc)
{
struct tipc_gap_ack_blks *p;
- u16 sz = 0;
+ u16 sz = 0, dlen = msg_data_sz(hdr);
/* Does peer support the Gap ACK blocks feature? */
if (l->peer_caps & TIPC_GAP_ACK_BLOCK) {
+ if (dlen < sizeof(*p))
+ goto ignore;
+
p = (struct tipc_gap_ack_blks *)msg_data(hdr);
sz = ntohs(p->len);
+ if (sz < sizeof(*p) || sz > dlen) {
+ sz = 0;
+ goto ignore;
+ }
+
/* Sanity check */
if (sz == struct_size(p, gacks, size_add(p->ugack_cnt, p->bgack_cnt))) {
/* Good, check if the desired type exists */
@@ -1434,6 +1442,8 @@ u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l,
}
}
}
+
+ignore:
/* Other cases: ignore! */
p = NULL;
--
2.34.1
^ permalink raw reply related
* [PATCH net v1 2/2] net/rds: Restrict use of RDS/IB to the initial network namespace
From: Allison Henderson @ 2026-04-05 4:16 UTC (permalink / raw)
To: netdev; +Cc: pabeni, edumazet, rds-devel, kuba, horms, linux-rdma, achender
In-Reply-To: <20260405041613.309958-1-achender@kernel.org>
From: Greg Jumper <greg.jumper@oracle.com>
Prevent using RDS/IB in network namespaces other than the initial one.
The existing RDS/IB code will not work properly in non-initial network
namespaces, and there are currently no plans to support such use.
Fixes: d5a8ac28a7ff ("RDS-TCP: Make RDS-TCP work correctly when it is set up in a netns other than init_net")
Reported-by: syzbot+da8e060735ae02c8f3d1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=da8e060735ae02c8f3d1
Signed-off-by: Greg Jumper <greg.jumper@oracle.com>
Signed-off-by: Allison Henderson <achender@kernel.org>
---
net/rds/af_rds.c | 10 ++++++++--
net/rds/ib.c | 7 ++++++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index b396c673dfaf..896d4cfda5c3 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -357,7 +357,8 @@ static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen)
return ret;
}
-static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)
+static int rds_set_transport(struct net *net, struct rds_sock *rs,
+ sockptr_t optval, int optlen)
{
int t_type;
@@ -373,6 +374,10 @@ static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)
if (t_type < 0 || t_type >= RDS_TRANS_COUNT)
return -EINVAL;
+ /* Only RDS/TCP supports non-initial network namespaces */
+ if (t_type != RDS_TRANS_TCP && !net_eq(net, &init_net))
+ return -EPROTOTYPE;
+
rs->rs_transport = rds_trans_get(t_type);
return rs->rs_transport ? 0 : -ENOPROTOOPT;
@@ -433,6 +438,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
struct rds_sock *rs = rds_sk_to_rs(sock->sk);
+ struct net *net = sock_net(sock->sk);
int ret;
if (level != SOL_RDS) {
@@ -461,7 +467,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
break;
case SO_RDS_TRANSPORT:
lock_sock(sock->sk);
- ret = rds_set_transport(rs, optval, optlen);
+ ret = rds_set_transport(net, rs, optval, optlen);
release_sock(sock->sk);
break;
case SO_TIMESTAMP_OLD:
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 73e01984ee9a..1bdbe8eaf3fc 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -490,8 +490,13 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
__u32 scope_id)
{
- struct rds_ib_device *rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]);
+ struct rds_ib_device *rds_ibdev;
+
+ /* RDS/IB is only supported in the initial network namespace */
+ if (!net_eq(net, &init_net))
+ return -EPROTOTYPE;
+ rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]);
if (rds_ibdev) {
rds_ib_dev_put(rds_ibdev);
--
2.43.0
^ permalink raw reply related
* [PATCH net v1 1/2] net/rds: Optimize rds_ib_laddr_check
From: Allison Henderson @ 2026-04-05 4:16 UTC (permalink / raw)
To: netdev; +Cc: pabeni, edumazet, rds-devel, kuba, horms, linux-rdma, achender
In-Reply-To: <20260405041613.309958-1-achender@kernel.org>
From: Håkon Bugge <haakon.bugge@oracle.com>
rds_ib_laddr_check() creates a CM_ID and attempts to bind the address
in question to it. This in order to qualify the allegedly local
address as a usable IB/RoCE address.
In the field, ExaWatcher runs rds-ping to all ports in the fabric from
all local ports. This using all active ToS'es. In a full rack system,
we have 14 cell servers and eight db servers. Typically, 6 ToS'es are
used. This implies 528 rds-ping invocations per ExaWatcher's "RDSinfo"
interval.
Adding to this, each rds-ping invocation creates eight sockets and
binds the local address to them:
socket(AF_RDS, SOCK_SEQPACKET, 0) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 4
bind(4, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 5
bind(5, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 6
bind(6, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 7
bind(7, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 8
bind(8, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 9
bind(9, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 10
bind(10, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
So, at every interval ExaWatcher executes rds-ping's, 4224 CM_IDs are
allocated, considering this full-rack system. After the a CM_ID has
been allocated, rdma_bind_addr() is called, with the port number being
zero. This implies that the CMA will attempt to search for an un-used
ephemeral port. Simplified, the algorithm is to start at a random
position in the available port space, and then if needed, iterate
until an un-used port is found.
The book-keeping of used ports uses the idr system, which again uses
slab to allocate new struct idr_layer's. The size is 2092 bytes and
slab tries to reduce the wasted space. Hence, it chooses an order:3
allocation, for which 15 idr_layer structs will fit and only 1388
bytes are wasted per the 32KiB order:3 chunk.
Although this order:3 allocation seems like a good space/speed
trade-off, it does not resonate well with how it used by the CMA. The
combination of the randomized starting point in the port space (which
has close to zero spatial locality) and the close proximity in time of
the 4224 invocations of the rds-ping's, creates a memory hog for
order:3 allocations.
These costly allocations may need reclaims and/or compaction. At
worst, they may fail and produce a stack trace such as (from uek4):
[<ffffffff811a72d5>] __inc_zone_page_state+0x35/0x40
[<ffffffff811c2e97>] page_add_file_rmap+0x57/0x60
[<ffffffffa37ca1df>] remove_migration_pte+0x3f/0x3c0 [ksplice_6cn872bt_vmlinux_new]
[<ffffffff811c3de8>] rmap_walk+0xd8/0x340
[<ffffffff811e8860>] remove_migration_ptes+0x40/0x50
[<ffffffff811ea83c>] migrate_pages+0x3ec/0x890
[<ffffffff811afa0d>] compact_zone+0x32d/0x9a0
[<ffffffff811b00ed>] compact_zone_order+0x6d/0x90
[<ffffffff811b03b2>] try_to_compact_pages+0x102/0x270
[<ffffffff81190e56>] __alloc_pages_direct_compact+0x46/0x100
[<ffffffff8119165b>] __alloc_pages_nodemask+0x74b/0xaa0
[<ffffffff811d8411>] alloc_pages_current+0x91/0x110
[<ffffffff811e3b0b>] new_slab+0x38b/0x480
[<ffffffffa41323c7>] __slab_alloc+0x3b7/0x4a0 [ksplice_s0dk66a8_vmlinux_new]
[<ffffffff811e42ab>] kmem_cache_alloc+0x1fb/0x250
[<ffffffff8131fdd6>] idr_layer_alloc+0x36/0x90
[<ffffffff8132029c>] idr_get_empty_slot+0x28c/0x3d0
[<ffffffff813204ad>] idr_alloc+0x4d/0xf0
[<ffffffffa051727d>] cma_alloc_port+0x4d/0xa0 [rdma_cm]
[<ffffffffa0517cbe>] rdma_bind_addr+0x2ae/0x5b0 [rdma_cm]
[<ffffffffa09d8083>] rds_ib_laddr_check+0x83/0x2c0 [ksplice_6l2xst5i_rds_rdma_new]
[<ffffffffa05f892b>] rds_trans_get_preferred+0x5b/0xa0 [rds]
[<ffffffffa05f09f2>] rds_bind+0x212/0x280 [rds]
[<ffffffff815b4016>] SYSC_bind+0xe6/0x120
[<ffffffff815b4d3e>] SyS_bind+0xe/0x10
[<ffffffff816b031a>] system_call_fastpath+0x18/0xd4
To avoid these excessive calls to rdma_bind_addr(), we optimize
rds_ib_laddr_check() by simply checking if the address in question has
been used before. The rds_rdma module keeps track of addresses
associated with IB devices, and the function rds_ib_get_device() is
used to determine if the address already has been qualified as a valid
local address. If not found, we call the legacy rds_ib_laddr_check(),
now renamed to rds_ib_laddr_check_cm().
Signed-off-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com>
Signed-off-by: Allison Henderson <achender@kernel.org>
---
net/rds/ib.c | 18 ++++++++++++++++--
net/rds/ib.h | 1 +
net/rds/ib_rdma.c | 2 +-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/net/rds/ib.c b/net/rds/ib.c
index ac6affa33ce7..73e01984ee9a 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -401,8 +401,8 @@ static void rds6_ib_ic_info(struct socket *sock, unsigned int len,
* allowed to influence which paths have priority. We could call userspace
* asserting this policy "routing".
*/
-static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
- __u32 scope_id)
+static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
+ __u32 scope_id)
{
int ret;
struct rdma_cm_id *cm_id;
@@ -487,6 +487,20 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
return ret;
}
+static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
+ __u32 scope_id)
+{
+ struct rds_ib_device *rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]);
+
+ if (rds_ibdev) {
+ rds_ib_dev_put(rds_ibdev);
+
+ return 0;
+ }
+
+ return rds_ib_laddr_check_cm(net, addr, scope_id);
+}
+
static void rds_ib_unregister_client(void)
{
ib_unregister_client(&rds_ib_client);
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 8ef3178ed4d6..5ff346a1e8ba 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -381,6 +381,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn,
__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
/* ib_rdma.c */
+struct rds_ib_device *rds_ib_get_device(__be32 ipaddr);
int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
struct in6_addr *ipaddr);
void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 2cfec252eeac..9594ea245f7f 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -43,7 +43,7 @@ struct workqueue_struct *rds_ib_mr_wq;
static void rds_ib_odp_mr_worker(struct work_struct *work);
-static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
+struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
{
struct rds_ib_device *rds_ibdev;
struct rds_ib_ipaddr *i_ipaddr;
--
2.43.0
^ permalink raw reply related
* [PATCH net v1 0/2] net/rds: Fix use-after-free in RDS/IB for non-init namespaces
From: Allison Henderson @ 2026-04-05 4:16 UTC (permalink / raw)
To: netdev; +Cc: pabeni, edumazet, rds-devel, kuba, horms, linux-rdma, achender
This series fixes syzbot bug da8e060735ae02c8f3d1
https://syzkaller.appspot.com/bug?extid=da8e060735ae02c8f3d1
The report finds a use-after-free bug where ib connections access an
invalid network namespace after it has been freed. The stack is:
rds_rdma_cm_event_handler_cmn
rds_conn_path_drop
rds_destroy_pending
check_net() <-- use-after-free
This is initially introduced in:
d5a8ac28a7ff ("RDS-TCP: Make RDS-TCP work correctly when it is set up
in a netns other than init_net").
Here, we made RDS aware of the namespace by storing a net pointer in
each connection. But it is not explicitly restricted to init_net in
the case of ib. The RDS/TCP transport has its own pernet exit handler
(rds_tcp_exit_net) that destroys connections when a namespace is torn
down. But RDS/IB does not support more than the initial namespace and
has no such handler. The initial namespace is statically allocated,
and never torn down, so it always has at least one reference.
Allowing non init namespaces that do not have a persistent reference
means that when their refcounts drop to zero, they are released through
cleanup_net(). Which would call any registered pernet clean up handlers
if it had any, but since they don't in this case, the extra
rds_connections remain with stale c_net pointers. Which are then
accessed later causing the use-after-free bug.
So, the simple fix is to disallow more than the initial namespace
to be created in the case of ib connections.
Fixes are ported from UEK patches found here:
https://github.com/oracle/linux-uek/commit/8ed9a82376b7
Patch 1 is a prerequisite optimization to rds_ib_laddr_check() that
avoids excessive rdma_bind_addr() calls during transport probing by
first checking rds_ib_get_device(). This is needed because patch 2
adds a namespace check at the top of the same function.
UEK: 8ed9a82376b7 ("rds: ib: Optimize rds_ib_laddr_check")
https://github.com/oracle/linux-uek/commit/bd9489a08004
Patch 2 restricts RDS/IB to the initial network namespace. It adds
checks in both rds_ib_laddr_check() and rds_set_transport() to reject
IB use from non-init namespaces with -EPROTOTYPE. This prevents the
use-after-free by ensuring IB connections cannot exist in namespaces
that may be torn down.
UEK: bd9489a08004 ("net/rds: Restrict use of RDS/IB to the initial
network namespace")
Questions, comments and feedback appreciated!
Thank you!
Allison
Greg Jumper (1):
net/rds: Restrict use of RDS/IB to the initial network namespace
Håkon Bugge (1):
net/rds: Optimize rds_ib_laddr_check
net/rds/af_rds.c | 10 ++++++++--
net/rds/ib.c | 23 +++++++++++++++++++++--
net/rds/ib.h | 1 +
net/rds/ib_rdma.c | 2 +-
4 files changed, 31 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH net-next v5 2/2] net: mana: force full-page RX buffers via ethtool private flag
From: Dipayaan Roy @ 2026-04-05 3:47 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
On some ARM64 platforms with 4K PAGE_SIZE, page_pool fragment
allocation in the RX refill path can cause 15-20% throughput
regression under high connection counts (>16 TCP streams).
Add an ethtool private flag "full-page-rx" that allows the user to
force one RX buffer per page, bypassing the page_pool fragment path.
This restores line-rate (180+ Gbps) performance on affected platforms.
Usage:
ethtool --set-priv-flags ethx full-page-rx on
There is no behavioral change by default. The flag must be explicitly
enabled by the user or udev rule.
The existing single-buffer-per-page logic for XDP and jumbo frames is
consolidated into a new helper mana_use_single_rxbuf_per_page() which
is now the single decision point for both the automatic and
user-controlled paths.
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 22 ++++-
.../ethernet/microsoft/mana/mana_ethtool.c | 89 +++++++++++++++++++
include/net/mana/mana.h | 8 ++
3 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 49c65cc1697c..59a1626c2be1 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -744,6 +744,25 @@ static void *mana_get_rxbuf_pre(struct mana_rxq *rxq, dma_addr_t *da)
return va;
}
+static bool
+mana_use_single_rxbuf_per_page(struct mana_port_context *apc, u32 mtu)
+{
+ /* On some platforms with 4K PAGE_SIZE, page_pool fragment allocation
+ * in the RX refill path (~2kB buffer) can cause significant throughput
+ * regression under high connection counts. Allow user to force one RX
+ * buffer per page via ethtool private flag to bypass the fragment
+ * path.
+ */
+ if (apc->priv_flags & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF))
+ return true;
+
+ /* For xdp and jumbo frames make sure only one packet fits per page. */
+ if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc))
+ return true;
+
+ return false;
+}
+
/* Get RX buffer's data size, alloc size, XDP headroom based on MTU */
static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
int mtu, u32 *datasize, u32 *alloc_size,
@@ -754,8 +773,7 @@ static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
/* Calculate datasize first (consistent across all cases) */
*datasize = mtu + ETH_HLEN;
- /* For xdp and jumbo frames make sure only one packet fits per page */
- if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc)) {
+ if (mana_use_single_rxbuf_per_page(apc, mtu)) {
if (mana_xdp_get(apc)) {
*headroom = XDP_PACKET_HEADROOM;
*alloc_size = PAGE_SIZE;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index a28ca461c135..0547c903f613 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -133,6 +133,10 @@ static const struct mana_stats_desc mana_phy_stats[] = {
{ "hc_tc7_tx_pause_phy", offsetof(struct mana_ethtool_phy_stats, tx_pause_tc7_phy) },
};
+static const char mana_priv_flags[MANA_PRIV_FLAG_MAX][ETH_GSTRING_LEN] = {
+ [MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF] = "full-page-rx"
+};
+
static int mana_get_sset_count(struct net_device *ndev, int stringset)
{
struct mana_port_context *apc = netdev_priv(ndev);
@@ -144,6 +148,10 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
ARRAY_SIZE(mana_phy_stats) +
ARRAY_SIZE(mana_hc_stats) +
num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+
+ case ETH_SS_PRIV_FLAGS:
+ return MANA_PRIV_FLAG_MAX;
+
default:
return -EINVAL;
}
@@ -192,6 +200,14 @@ static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
}
}
+static void mana_get_strings_priv_flags(u8 **data)
+{
+ int i;
+
+ for (i = 0; i < MANA_PRIV_FLAG_MAX; i++)
+ ethtool_puts(data, mana_priv_flags[i]);
+}
+
static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct mana_port_context *apc = netdev_priv(ndev);
@@ -200,6 +216,9 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
case ETH_SS_STATS:
mana_get_strings_stats(apc, &data);
break;
+ case ETH_SS_PRIV_FLAGS:
+ mana_get_strings_priv_flags(&data);
+ break;
default:
break;
}
@@ -590,6 +609,74 @@ static int mana_get_link_ksettings(struct net_device *ndev,
return 0;
}
+static u32 mana_get_priv_flags(struct net_device *ndev)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+
+ return apc->priv_flags;
+}
+
+static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+ u32 changed = apc->priv_flags ^ priv_flags;
+ u32 old_priv_flags = apc->priv_flags;
+ bool schedule_port_reset = false;
+ int err = 0;
+
+ if (!changed)
+ return 0;
+
+ /* Reject unknown bits */
+ if (priv_flags & ~GENMASK(MANA_PRIV_FLAG_MAX - 1, 0))
+ return -EINVAL;
+
+ if (changed & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF)) {
+ apc->priv_flags = priv_flags;
+
+ if (!apc->port_is_up) {
+ /* Port is down, flag updated to apply on next up
+ * so just return.
+ */
+ return 0;
+ }
+
+ /* Pre-allocate buffers to prevent failure in mana_attach
+ * later
+ */
+ err = mana_pre_alloc_rxbufs(apc, ndev->mtu, apc->num_queues);
+ if (err) {
+ netdev_err(ndev,
+ "Insufficient memory for new allocations\n");
+ apc->priv_flags = old_priv_flags;
+ return err;
+ }
+
+ err = mana_detach(ndev, false);
+ if (err) {
+ netdev_err(ndev, "mana_detach failed: %d\n", err);
+ apc->priv_flags = old_priv_flags;
+ goto out;
+ }
+
+ err = mana_attach(ndev);
+ if (err) {
+ netdev_err(ndev, "mana_attach failed: %d\n", err);
+ apc->priv_flags = old_priv_flags;
+ schedule_port_reset = true;
+ }
+ }
+
+out:
+ mana_pre_dealloc_rxbufs(apc);
+
+ if (err && schedule_port_reset)
+ queue_work(apc->ac->per_port_queue_reset_wq,
+ &apc->queue_reset_work);
+
+ return err;
+}
+
const struct ethtool_ops mana_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES,
.get_ethtool_stats = mana_get_ethtool_stats,
@@ -608,4 +695,6 @@ const struct ethtool_ops mana_ethtool_ops = {
.set_ringparam = mana_set_ringparam,
.get_link_ksettings = mana_get_link_ksettings,
.get_link = ethtool_op_get_link,
+ .get_priv_flags = mana_get_priv_flags,
+ .set_priv_flags = mana_set_priv_flags,
};
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 3336688fed5e..fd87e3d6c1f4 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -30,6 +30,12 @@ enum TRI_STATE {
TRI_STATE_TRUE = 1
};
+/* MANA ethtool private flag bit positions */
+enum mana_priv_flag_bits {
+ MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF = 0,
+ MANA_PRIV_FLAG_MAX,
+};
+
/* Number of entries for hardware indirection table must be in power of 2 */
#define MANA_INDIRECT_TABLE_MAX_SIZE 512
#define MANA_INDIRECT_TABLE_DEF_SIZE 64
@@ -531,6 +537,8 @@ struct mana_port_context {
u32 rxbpre_headroom;
u32 rxbpre_frag_count;
+ u32 priv_flags;
+
struct bpf_prog *bpf_prog;
/* Create num_queues EQs, SQs, SQ-CQs, RQs and RQ-CQs, respectively. */
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 1/2] net: mana: refactor mana_get_strings() and mana_get_sset_count() to use switch
From: Dipayaan Roy @ 2026-04-05 3:44 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
Refactor mana_get_strings() and mana_get_sset_count() from if/else to
switch statements in preparation for adding ethtool private flags
support which requires handling ETH_SS_PRIV_FLAGS.
No functional change.
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
.../ethernet/microsoft/mana/mana_ethtool.c | 75 ++++++++++++-------
1 file changed, 46 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 6a4b42fe0944..a28ca461c135 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -138,53 +138,70 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
- if (stringset != ETH_SS_STATS)
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(mana_eth_stats) +
+ ARRAY_SIZE(mana_phy_stats) +
+ ARRAY_SIZE(mana_hc_stats) +
+ num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+ default:
return -EINVAL;
-
- return ARRAY_SIZE(mana_eth_stats) + ARRAY_SIZE(mana_phy_stats) + ARRAY_SIZE(mana_hc_stats) +
- num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+ }
}
-static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
{
- struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
int i, j;
- if (stringset != ETH_SS_STATS)
- return;
for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
- ethtool_puts(&data, mana_eth_stats[i].name);
+ ethtool_puts(data, mana_eth_stats[i].name);
for (i = 0; i < ARRAY_SIZE(mana_hc_stats); i++)
- ethtool_puts(&data, mana_hc_stats[i].name);
+ ethtool_puts(data, mana_hc_stats[i].name);
for (i = 0; i < ARRAY_SIZE(mana_phy_stats); i++)
- ethtool_puts(&data, mana_phy_stats[i].name);
+ ethtool_puts(data, mana_phy_stats[i].name);
for (i = 0; i < num_queues; i++) {
- ethtool_sprintf(&data, "rx_%d_packets", i);
- ethtool_sprintf(&data, "rx_%d_bytes", i);
- ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
- ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
- ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
- ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
+ ethtool_sprintf(data, "rx_%d_packets", i);
+ ethtool_sprintf(data, "rx_%d_bytes", i);
+ ethtool_sprintf(data, "rx_%d_xdp_drop", i);
+ ethtool_sprintf(data, "rx_%d_xdp_tx", i);
+ ethtool_sprintf(data, "rx_%d_xdp_redirect", i);
+ ethtool_sprintf(data, "rx_%d_pkt_len0_err", i);
for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
- ethtool_sprintf(&data, "rx_%d_coalesced_cqe_%d", i, j + 2);
+ ethtool_sprintf(data,
+ "rx_%d_coalesced_cqe_%d",
+ i,
+ j + 2);
}
for (i = 0; i < num_queues; i++) {
- ethtool_sprintf(&data, "tx_%d_packets", i);
- ethtool_sprintf(&data, "tx_%d_bytes", i);
- ethtool_sprintf(&data, "tx_%d_xdp_xmit", i);
- ethtool_sprintf(&data, "tx_%d_tso_packets", i);
- ethtool_sprintf(&data, "tx_%d_tso_bytes", i);
- ethtool_sprintf(&data, "tx_%d_tso_inner_packets", i);
- ethtool_sprintf(&data, "tx_%d_tso_inner_bytes", i);
- ethtool_sprintf(&data, "tx_%d_long_pkt_fmt", i);
- ethtool_sprintf(&data, "tx_%d_short_pkt_fmt", i);
- ethtool_sprintf(&data, "tx_%d_csum_partial", i);
- ethtool_sprintf(&data, "tx_%d_mana_map_err", i);
+ ethtool_sprintf(data, "tx_%d_packets", i);
+ ethtool_sprintf(data, "tx_%d_bytes", i);
+ ethtool_sprintf(data, "tx_%d_xdp_xmit", i);
+ ethtool_sprintf(data, "tx_%d_tso_packets", i);
+ ethtool_sprintf(data, "tx_%d_tso_bytes", i);
+ ethtool_sprintf(data, "tx_%d_tso_inner_packets", i);
+ ethtool_sprintf(data, "tx_%d_tso_inner_bytes", i);
+ ethtool_sprintf(data, "tx_%d_long_pkt_fmt", i);
+ ethtool_sprintf(data, "tx_%d_short_pkt_fmt", i);
+ ethtool_sprintf(data, "tx_%d_csum_partial", i);
+ ethtool_sprintf(data, "tx_%d_mana_map_err", i);
+ }
+}
+
+static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ mana_get_strings_stats(apc, &data);
+ break;
+ default:
+ break;
}
}
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 0/2] net: mana: add ethtool private flag for full-page RX buffers
From: Dipayaan Roy @ 2026-04-05 3:42 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
On some ARM64 platforms with 4K PAGE_SIZE, utilizing page_pool
fragments for allocation in the RX refill path (~2kB buffer per fragment)
causes 15-20% throughput regression under high connection counts
(>16 TCP streams at 180+ Gbps). Using full-page buffers on these
platforms shows no regression and restores line-rate performance.
This behavior is observed on a single platform; other platforms
perform better with page_pool fragments, indicating this is not a
page_pool issue but platform-specific.
This series adds an ethtool private flag "full-page-rx" to let the
user opt in to one RX buffer per page:
ethtool --set-priv-flags eth0 full-page-rx on
There is no behavioral change by default. The flag can be persisted
via udev rule for affected platforms.
Changes in v5:
- Split prep refactor into separate patch (patch 1/2)
Changes in v4:
- Dropping the smbios string parsing and add ethtool priv flag
to reconfigure the queues with full page rx buffers.
Changes in v3:
- changed u8* to char*
Changes in v2:
- separate reading string index and the string, remove inline.
Dipayaan Roy (2):
net: mana: refactor mana_get_strings() and mana_get_sset_count() to
use switch
net: mana: force full-page RX buffers via ethtool private flag
drivers/net/ethernet/microsoft/mana/mana_en.c | 22 ++-
.../ethernet/microsoft/mana/mana_ethtool.c | 164 ++++++++++++++----
include/net/mana/mana.h | 8 +
3 files changed, 163 insertions(+), 31 deletions(-)
--
2.43.0
^ permalink raw reply
* Re: [net-next v2 3/3] selftests/net: Test PACKET_AUXDATA
From: Willem de Bruijn @ 2026-04-05 3:30 UTC (permalink / raw)
To: Willem de Bruijn, Joe Damato, netdev, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Shuah Khan, dalias
Cc: andrew+netdev, linux-kernel, willemb, Joe Damato, linux-kselftest
In-Reply-To: <willemdebruijn.kernel.400d24decd7d@gmail.com>
Willem de Bruijn wrote:
> Joe Damato wrote:
> > Extend the packet socket selftest, adding a recvmsg path, to test
> > PACKET_AUXDATA. Check basic attributes of tpacket_auxdata.
> >
> > Signed-off-by: Joe Damato <joe@dama.to>
> > ---
> > tools/testing/selftests/net/psock_snd.c | 67 ++++++++++++++++++++++--
> > tools/testing/selftests/net/psock_snd.sh | 5 ++
> > 2 files changed, 67 insertions(+), 5 deletions(-)
> >
> > v2:
> > - Add is_psock bool argument to do_rx.
> > - Factor out aux data check into its own function for readability.
> >
> > diff --git a/tools/testing/selftests/net/psock_snd.c b/tools/testing/selftests/net/psock_snd.c
> > index 81096df5cffc..5464317c1764 100644
> > --- a/tools/testing/selftests/net/psock_snd.c
> > +++ b/tools/testing/selftests/net/psock_snd.c
> > @@ -40,6 +40,7 @@ static bool cfg_use_qdisc_bypass;
> > static bool cfg_use_vlan;
> > static bool cfg_use_vnet;
> > static bool cfg_drop;
> > +static bool cfg_aux_data;
> >
> > static char *cfg_ifname = "lo";
> > static int cfg_mtu = 1500;
> > @@ -279,11 +280,54 @@ static int setup_rx(void)
> > return fd;
> > }
> >
> > -static void do_rx(int fd, int expected_len, char *expected)
> > +static void check_aux_data(struct cmsghdr *cmsg, int expected_len)
> > {
> > + struct tpacket_auxdata *adata;
> > +
> > + if (!cmsg)
> > + error(1, 0, "auxdata null");
> > +
> > + if (cmsg->cmsg_level != SOL_PACKET)
> > + error(1, 0, "cmsg_level != SOL_PACKET");
> > +
> > + if (cmsg->cmsg_type != PACKET_AUXDATA)
> > + error(1, 0, "cmsg_type != PACKET_AUXDATA");
> > +
> > + adata = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
>
> Sashiko had another interesting observation that this access may be
> unaligned, as cmsg_buf[1024] has 1-byte alignment.
>
> That is not new in this patch. Indeed most tests in this dir just
> deference msg_control as struct cmsghdr * and CMSG_DATA as whatever
> domain specific type.
>
> The man page also warns about this and suggests using memcpy to
> access CMSG_DATA. Not sure why it does not warn about the other
> cmsg_.. fields.
The commit that introduced that has more context
https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/man/man3/cmsg.3?id=36d25246b4333513fefdbec7f78f29d193cf5d9a
It points out 32-bit platforms where cmsghdr is 12 bytes.
At least one example given, ptpd, uses a union to ensure alignment
union {
struct cmsghdr cm;
char control[256];
} cmsg_un;
But at least one other example, ssmping, does not. So I think not even
the 4B (on 32-bit archs) of cmsghdr fields can be depended on.
> Indeed I can trigger this, e.g., with ipv6_flowlabel.c with
>
> - char control[CMSG_SPACE(sizeof(flowlabel))] = {0};
> + char control[1 + CMSG_SPACE(sizeof(flowlabel))] = {0};
>
> - cm = (void *)control;
> + cm = (void *)control + 1;
>
> and compiling with -fsanitize=alignment. That triggers warnings for
> all fields, starting from cmsg_len on line 78.
>
> In practice this does not cause issues, because the compiler appears
> to align char[] to 16B, even though __alignof__(control) shows 1. This
> seems true for x86_64, but I am not aware that it is true across all
> archs, especially those that cannot handle unaligned access.
>
> I think the x86_64 source is the AMD64 ABI Draft, e.g., v 0.99.6
>
> An array uses the same alignment as its elements, except that
> a local or global array variable of length at least 16 bytes
> or a C99 variable-length array variable always has alignment
> of at least 16 bytes(4)
>
> (4) The alignment requirement allows the use of SSE instructions
> when operating on the array. [..]
>
> Makes sense as sizeof struct cmsghdr == 16.
>
> cmsg_len has length 8 (size_t). We'll be hardpressed to find a
> CMSG_DATA example with a larger alignment requirement. Indeed I did
> not in this directory. So satisfying 8-byte alignment for msg_control
> will suffice for all tests in this directory.
>
> Unless we're certain that 8B alignment for stack aligned char[] is
> guaranteed across platforms, one safe approach it to add explicit
> alignment:
>
> - char control[CMSG_SPACE(sizeof(flowlabel))] = {0};
> + char control[CMSG_SPACE(sizeof(flowlabel))] __attribute__((aligned(8))) = {0};
>
> I can update the (other) tests. Unless someone knows that this is
> indeed not needed in practice on any platform.
>
> > +
> > + if (adata->tp_net != ETH_HLEN)
> > + error(1, 0, "cmsg tp_net != ETH_HLEN");
> > +
> > + if (adata->tp_len != expected_len)
> > + error(1, 0, "cmsg tp_len != %u", expected_len);
> > +
> > + if (adata->tp_snaplen != expected_len)
> > + error(1, 0, "cmsg tp_snaplen != %u", expected_len);
> > +}
> > +
> > +static void do_rx(int fd, int expected_len, char *expected, bool is_psock)
> > +{
> > + bool aux = is_psock && cfg_aux_data;
> > + char cmsg_buf[1024] = {};
> > + struct msghdr msg = {};
> > + struct iovec iov[1];
> > int ret;
> >
> > - ret = recv(fd, rbuf, sizeof(rbuf), 0);
> > + if (aux) {
> > + iov[0].iov_base = rbuf;
> > + iov[0].iov_len = sizeof(rbuf);
> > +
> > + msg.msg_iov = iov;
> > + msg.msg_iovlen = 1;
> > +
> > + msg.msg_control = cmsg_buf;
> > + msg.msg_controllen = sizeof(cmsg_buf);
> > +
> > + ret = recvmsg(fd, &msg, 0);
> > + } else {
> > + ret = recv(fd, rbuf, sizeof(rbuf), 0);
> > + }
> > +
^ permalink raw reply
* Re: [PATCH net-next,v4] net: mana: Force full-page RX buffers via ethtool private flag
From: Dipayaan Roy @ 2026-04-05 3:14 UTC (permalink / raw)
To: Jakub Kicinski
Cc: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
pabeni, leon, longli, kotaranov, horms, shradhagupta, ssengar,
ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, leitao, kees, dipayanroy
In-Reply-To: <20260330154755.6a8c73a6@kernel.org>
On Mon, Mar 30, 2026 at 03:47:55PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Mar 2026 14:01:54 -0700 Dipayaan Roy wrote:
> > On some ARM64 platforms with 4K PAGE_SIZE, page_pool fragment
> > allocation in the RX refill path can cause 15-20% throughput
> > regression under high connection counts (>16 TCP streams).
>
> Did you investigate what makes such a difference exactly?
> As I said I suspect there are some improvements we could
> make in the page pool fragmentation logic that could yield
> similar wins without bothering the user.
>
I collected the perf numbers, shared the analysis below.
> > Add an ethtool private flag "full-page-rx" that allows the user to
> > force one RX buffer per page, bypassing the page_pool fragment path.
> > This restores line-rate(180+ Gbps) performance on affected platforms.
> >
> > Usage:
> > ethtool --set-priv-flags eth0 full-page-rx on
> >
> > There is no behavioral change by default. The flag must be explicitly
> > enabled by the user or udev rule.
> >
> > The existing single-buffer-per-page logic for XDP and jumbo frames is
> > consolidated into a new helper mana_use_single_rxbuf_per_page().
>
> ethtool -g rx-buf-len could also fit the bill but I guess this is more
> of a hack / workaround than legit config so no strong preference.
>
ok, want to stay with private flag.
> > -static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
> > +static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
> > {
> > - struct mana_port_context *apc = netdev_priv(ndev);
> > unsigned int num_queues = apc->num_queues;
> > int i, j;
> >
> > - if (stringset != ETH_SS_STATS)
> > - return;
> > for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
> > - ethtool_puts(&data, mana_eth_stats[i].name);
> > + ethtool_puts(data, mana_eth_stats[i].name);
> >
> > for (i = 0; i < ARRAY_SIZE(mana_hc_stats); i++)
> > - ethtool_puts(&data, mana_hc_stats[i].name);
> > + ethtool_puts(data, mana_hc_stats[i].name);
> >
> > for (i = 0; i < ARRAY_SIZE(mana_phy_stats); i++)
> > - ethtool_puts(&data, mana_phy_stats[i].name);
> > + ethtool_puts(data, mana_phy_stats[i].name);
> >
> > for (i = 0; i < num_queues; i++) {
> > - ethtool_sprintf(&data, "rx_%d_packets", i);
> > - ethtool_sprintf(&data, "rx_%d_bytes", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
> > - ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
> > + ethtool_sprintf(data, "rx_%d_packets", i);
>
> Please factor out the noisy, no-op prep work into a separate patch for
> ease of review
Ack, will split it out in 2 separate patches in v5.
> --
> pw-bot: cr
Hi Jakub,
I did some perf analysis on the ARM64 platform for which we want to
have this work around of full page rx buffers:
test: ntttcp with 48 tcp connections
perf: perf record -ag --call-graph dwarf -C 0-33 -- sleep 32
Page pool overhead summary:
(framgment based rx buff vs full page rx buff on the same ARM64
platform)
Function Fragment Full-page Delta
─---------------------------- ─------- --------- -----
napi_pp_put_page 3.93% 0.85% +3.08%
page_pool_alloc_frag_netmem 1.93% — +1.93%
Total page_pool overhead 5.86% 0.85% +5.01%
In fragment mode, napi_pp_put_page performs an atomic decrement of
the shared page refcount on every packet free. This single operation
accounts for ~3% more CPU than in full-page mode, where the page is
sole-owned and the atomic is skipped entirely. Additionally,
page_pool_alloc_frag_netmem adds ~2% overhead on the allocation
path for fragments.
Further annotation of the hot page pool functions in fragment mode
shows:
napi_pp_put_page:
0.09 : ffff80008117c240: b ffff80008117c268
<napi_pp_put_page+0x68>
: 64 ATOMIC64_FETCH_OP( , al, op, asm_op,
"memory")
:
: 66 ATOMIC64_FETCH_OPS(andnot, ldclr)
: 67 ATOMIC64_FETCH_OPS(or, ldset)
: 68 ATOMIC64_FETCH_OPS(xor, ldeor)
: 69 ATOMIC64_FETCH_OPS(add, ldadd)
0.00 : ffff80008117c244: mov x3, #0xffffffffffffffff
// #-1
0.08 : ffff80008117c248: add x0, x2, #0x28
0.06 : ffff80008117c24c: ldaddal x3, x3, [x0]
: 73 }
:
: 75 ATOMIC64_OP_ADD_SUB_RETURN(_relaxed)
: 76 ATOMIC64_OP_ADD_SUB_RETURN(_acquire)
: 77 ATOMIC64_OP_ADD_SUB_RETURN(_release)
: 78 ATOMIC64_OP_ADD_SUB_RETURN( )
88.09 : ffff80008117c250: sub x3, x3, #0x1
:
: 81 return 0;
: 82 }
88% of this function's cycles stall on the sub that depends on
ldaddal.
page_pool_alloc_frag_netmem:
: 151 ATOMIC64_FETCH_OPS(add, ldadd)
0.00 : ffff8000811fd40c: add x1, x21, #0x28
0.14 : ffff8000811fd410: ldaddal x0, x1, [x1]
: 154 }
:
: 156 ATOMIC64_OP_ADD_SUB_RETURN(_relaxed)
: 157 ATOMIC64_OP_ADD_SUB_RETURN(_acquire)
: 158 ATOMIC64_OP_ADD_SUB_RETURN(_release)
: 159 ATOMIC64_OP_ADD_SUB_RETURN( )
75.09 : ffff8000811fd414: add x0, x0, x1
: 161 WARN_ON(ret < 0);
0.16 : ffff8000811fd418: cmp x0, #0x0
0.00 : ffff8000811fd41c: b.lt ffff8000811fd394
<page_pool_alloc_frag_netmem+0xb4> // b.tstop
75% of this function's cycles stall on the same pattern.
Full comparison (top functions, >0.5%):
Fragment mode: Full-page mode:
------------- --------------
15.88% __wake_up_sync_key 13.66% __wake_up_sync_key
9.66% default_idle_call 10.41% default_idle_call
8.38% handle_softirqs 8.89% handle_softirqs
3.93% napi_pp_put_page ← 0.85% napi_pp_put_page
3.18% tcp_gro_receive 3.43% tcp_gro_receive
1.93% page_pool_alloc_frag ← —
— 1.14%
page_pool_recycle_in_cache
— 1.06%
page_pool_put_unrefed_netmem
0.93% napi_build_skb 1.24% napi_build_skb
0.56% __build_skb_around 1.46% __build_skb_around
In full page rx buffers mode 'napi_pp_put_page' took just 0.85% on
the same ARM64 platform.
Comparing with another platform(x86):
To confirm this behaviour is specific to this ARM64 platform, I
collected the same data on a x86 Vm (Intel, 192 vCPUs, same MANA NIC 200Gbps)
Here both full page rx buff mode and fragment modes rx buffs achieves identical
~182 Gbps on x86.
x86 fragment mode: x86 full-page mode:
─----------------- ─------------------
61.69% pv_native_safe_halt 50.91% pv_native_safe_halt
4.17% _raw_spin_unlock_irqrestore 6.19%
_raw_spin_unlock_irqrestore
3.95% handle_softirqs 4.02% handle_softirqs
2.51% _copy_to_iter 2.53% _copy_to_iter
0.60% napi_pp_put_page — napi_pp_put_page (<0.5%)
On x86, napi_pp_put_page is only 0.60% in fragment mode (vs 3.93%
on the ARM64 platform data shared earlier).
Note: I did not had a different arm64 platform available to run and compare
it with.
From the above data, seems to be an issue specific to this ARM64
platform.
Regards
^ permalink raw reply
* Re: [net-next v2 3/3] selftests/net: Test PACKET_AUXDATA
From: Willem de Bruijn @ 2026-04-05 3:04 UTC (permalink / raw)
To: Joe Damato, netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: andrew+netdev, linux-kernel, willemb, Joe Damato, linux-kselftest
In-Reply-To: <20260403233240.178948-4-joe@dama.to>
Joe Damato wrote:
> Extend the packet socket selftest, adding a recvmsg path, to test
> PACKET_AUXDATA. Check basic attributes of tpacket_auxdata.
>
> Signed-off-by: Joe Damato <joe@dama.to>
> ---
> tools/testing/selftests/net/psock_snd.c | 67 ++++++++++++++++++++++--
> tools/testing/selftests/net/psock_snd.sh | 5 ++
> 2 files changed, 67 insertions(+), 5 deletions(-)
>
> v2:
> - Add is_psock bool argument to do_rx.
> - Factor out aux data check into its own function for readability.
>
> diff --git a/tools/testing/selftests/net/psock_snd.c b/tools/testing/selftests/net/psock_snd.c
> index 81096df5cffc..5464317c1764 100644
> --- a/tools/testing/selftests/net/psock_snd.c
> +++ b/tools/testing/selftests/net/psock_snd.c
> @@ -40,6 +40,7 @@ static bool cfg_use_qdisc_bypass;
> static bool cfg_use_vlan;
> static bool cfg_use_vnet;
> static bool cfg_drop;
> +static bool cfg_aux_data;
>
> static char *cfg_ifname = "lo";
> static int cfg_mtu = 1500;
> @@ -279,11 +280,54 @@ static int setup_rx(void)
> return fd;
> }
>
> -static void do_rx(int fd, int expected_len, char *expected)
> +static void check_aux_data(struct cmsghdr *cmsg, int expected_len)
> {
> + struct tpacket_auxdata *adata;
> +
> + if (!cmsg)
> + error(1, 0, "auxdata null");
> +
> + if (cmsg->cmsg_level != SOL_PACKET)
> + error(1, 0, "cmsg_level != SOL_PACKET");
> +
> + if (cmsg->cmsg_type != PACKET_AUXDATA)
> + error(1, 0, "cmsg_type != PACKET_AUXDATA");
> +
> + adata = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
Sashiko had another interesting observation that this access may be
unaligned, as cmsg_buf[1024] has 1-byte alignment.
That is not new in this patch. Indeed most tests in this dir just
deference msg_control as struct cmsghdr * and CMSG_DATA as whatever
domain specific type.
The man page also warns about this and suggests using memcpy to
access CMSG_DATA. Not sure why it does not warn about the other
cmsg_.. fields.
Indeed I can trigger this, e.g., with ipv6_flowlabel.c with
- char control[CMSG_SPACE(sizeof(flowlabel))] = {0};
+ char control[1 + CMSG_SPACE(sizeof(flowlabel))] = {0};
- cm = (void *)control;
+ cm = (void *)control + 1;
and compiling with -fsanitize=alignment. That triggers warnings for
all fields, starting from cmsg_len on line 78.
In practice this does not cause issues, because the compiler appears
to align char[] to 16B, even though __alignof__(control) shows 1. This
seems true for x86_64, but I am not aware that it is true across all
archs, especially those that cannot handle unaligned access.
I think the x86_64 source is the AMD64 ABI Draft, e.g., v 0.99.6
An array uses the same alignment as its elements, except that
a local or global array variable of length at least 16 bytes
or a C99 variable-length array variable always has alignment
of at least 16 bytes(4)
(4) The alignment requirement allows the use of SSE instructions
when operating on the array. [..]
Makes sense as sizeof struct cmsghdr == 16.
cmsg_len has length 8 (size_t). We'll be hardpressed to find a
CMSG_DATA example with a larger alignment requirement. Indeed I did
not in this directory. So satisfying 8-byte alignment for msg_control
will suffice for all tests in this directory.
Unless we're certain that 8B alignment for stack aligned char[] is
guaranteed across platforms, one safe approach it to add explicit
alignment:
- char control[CMSG_SPACE(sizeof(flowlabel))] = {0};
+ char control[CMSG_SPACE(sizeof(flowlabel))] __attribute__((aligned(8))) = {0};
I can update the (other) tests. Unless someone knows that this is
indeed not needed in practice on any platform.
> +
> + if (adata->tp_net != ETH_HLEN)
> + error(1, 0, "cmsg tp_net != ETH_HLEN");
> +
> + if (adata->tp_len != expected_len)
> + error(1, 0, "cmsg tp_len != %u", expected_len);
> +
> + if (adata->tp_snaplen != expected_len)
> + error(1, 0, "cmsg tp_snaplen != %u", expected_len);
> +}
> +
> +static void do_rx(int fd, int expected_len, char *expected, bool is_psock)
> +{
> + bool aux = is_psock && cfg_aux_data;
> + char cmsg_buf[1024] = {};
> + struct msghdr msg = {};
> + struct iovec iov[1];
> int ret;
>
> - ret = recv(fd, rbuf, sizeof(rbuf), 0);
> + if (aux) {
> + iov[0].iov_base = rbuf;
> + iov[0].iov_len = sizeof(rbuf);
> +
> + msg.msg_iov = iov;
> + msg.msg_iovlen = 1;
> +
> + msg.msg_control = cmsg_buf;
> + msg.msg_controllen = sizeof(cmsg_buf);
> +
> + ret = recvmsg(fd, &msg, 0);
> + } else {
> + ret = recv(fd, rbuf, sizeof(rbuf), 0);
> + }
> +
^ permalink raw reply
* Re: [PATCH net-next v2] selftests/net: convert so_txtime to drv-net
From: Willem de Bruijn @ 2026-04-05 2:20 UTC (permalink / raw)
To: Willem de Bruijn, netdev
Cc: davem, kuba, edumazet, pabeni, horms, Willem de Bruijn
In-Reply-To: <20260405014458.1038165-1-willemdebruijn.kernel@gmail.com>
Willem de Bruijn wrote:
> From: Willem de Bruijn <willemb@google.com>
>
> In preparation for extending to pacing hardware offload, convert the
> so_txtime.sh test to a drv-net test that can be run against netdevsim
> and real hardware.
>
> Also update so_txtime.c to not exit on first failure, but run to
> completion and report exit code there. This helps with debugging
> unexpected results, especially when processing multiple packets,
> as in the "reverse_order" testcase.
>
> Signed-off-by: Willem de Bruijn <willemb@google.com>
>
> ----
>
> v1 -> v2
> - move so_txtime.c for net/lib to drivers/net (Jakub)
> - fix drivers/net/config order (Jakub)
> - detect passing when failure is expected (Jakub, Sashiko)
> - pass pylint --disable=R (Jakub)
> - only call ksft_run once (Jakub)
> - do not sleep if waiting time is negative (Sashiko)
> - add \n when converting error() to fprintf() (Sashiko)
> - 4 space indentation, instead of 2 space
> - increase sync delay from 100 to 200ms, to fix rare vng flakes
>
> v1: https://lore.kernel.org/netdev/20260403175047.152646-1-willemdebruijn.kernel@gmail.com/
> ---
> .../testing/selftests/drivers/net/.gitignore | 1 +
> tools/testing/selftests/drivers/net/Makefile | 5 +-
> tools/testing/selftests/drivers/net/config | 2 +
> .../selftests/{ => drivers}/net/so_txtime.c | 24 +++-
> .../selftests/drivers/net/so_txtime.py | 88 ++++++++++++++
> tools/testing/selftests/net/.gitignore | 1 -
> tools/testing/selftests/net/Makefile | 2 -
> tools/testing/selftests/net/so_txtime.sh | 110 ------------------
> 8 files changed, 114 insertions(+), 119 deletions(-)
> rename tools/testing/selftests/{ => drivers}/net/so_txtime.c (96%)
> create mode 100755 tools/testing/selftests/drivers/net/so_txtime.py
> delete mode 100755 tools/testing/selftests/net/so_txtime.sh
>
> diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore
> index 585ecb4d5dc4..e5314ce4bb2d 100644
> --- a/tools/testing/selftests/drivers/net/.gitignore
> +++ b/tools/testing/selftests/drivers/net/.gitignore
> @@ -1,3 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> napi_id_helper
> psp_responder
> +so_txtime
> diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
> index 7c7fa75b80c2..85d6a7e26627 100644
> --- a/tools/testing/selftests/drivers/net/Makefile
> +++ b/tools/testing/selftests/drivers/net/Makefile
> @@ -20,12 +20,15 @@ TEST_PROGS := \
> queues.py \
> ring_reconfig.py \
> shaper.py \
> + so_txtime.py \
> stats.py \
> xdp.py \
> # end of TEST_PROGS
>
> # YNL files, must be before "include ..lib.mk"
> -YNL_GEN_FILES := psp_responder
> +YNL_GEN_FILES := \
> + psp_responder \
> + so_txtime
This should just go under TEST_GEN_FILES (sashiko)
I don't quite understand the check_selftest check_new_files_makefile
failure.
^ permalink raw reply
* [PATCH net v2] nfc: pn533: allocate rx skb before consuming bytes
From: Pengpeng Hou @ 2026-04-05 0:40 UTC (permalink / raw)
To: netdev
Cc: Lars Poeschel, Duoming Zhou, Rikard Falkeborn, linux-kernel,
pengpeng, stable
In-Reply-To: <20260402042148.65251-1-pengpeng@iscas.ac.cn>
pn532_receive_buf() reports the number of accepted bytes to the serdev
core. The current code consumes bytes into recv_skb and may already hand
a complete frame to pn533_recv_frame() before allocating a fresh receive
buffer.
If that alloc_skb() fails, the callback returns 0 even though it has
already consumed bytes, and it leaves recv_skb as NULL for the next
receive callback. That breaks the receive_buf() accounting contract and
can also lead to a NULL dereference on the next skb_put_u8().
Allocate the receive skb lazily before consuming the next byte instead.
If allocation fails, return the number of bytes already accepted.
Fixes: c656aa4c27b1 ("nfc: pn533: add UART phy driver")
Cc: stable@vger.kernel.org
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
Changes since v1:
- rebase on `net/main`
- keep the same fix shape on top of the current tailroom handling
drivers/nfc/pn533/uart.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
index 1b82b7b2..e0d67cd2 100644
--- a/drivers/nfc/pn533/uart.c
+++ b/drivers/nfc/pn533/uart.c
@@ -211,6 +211,13 @@ static size_t pn532_receive_buf(struct serdev_device *serdev,
timer_delete(&dev->cmd_timeout);
for (i = 0; i < count; i++) {
+ if (!dev->recv_skb) {
+ dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN,
+ GFP_KERNEL);
+ if (!dev->recv_skb)
+ return i;
+ }
+
if (unlikely(!skb_tailroom(dev->recv_skb)))
skb_trim(dev->recv_skb, 0);
@@ -219,9 +226,7 @@ static size_t pn532_receive_buf(struct serdev_device *serdev,
continue;
pn533_recv_frame(dev->priv, dev->recv_skb, 0);
- dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL);
- if (!dev->recv_skb)
- return 0;
+ dev->recv_skb = NULL;
}
return i;
--
2.50.1
^ permalink raw reply related
* [PATCH net-next v2] selftests/net: convert so_txtime to drv-net
From: Willem de Bruijn @ 2026-04-05 1:44 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, edumazet, pabeni, horms, Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
In preparation for extending to pacing hardware offload, convert the
so_txtime.sh test to a drv-net test that can be run against netdevsim
and real hardware.
Also update so_txtime.c to not exit on first failure, but run to
completion and report exit code there. This helps with debugging
unexpected results, especially when processing multiple packets,
as in the "reverse_order" testcase.
Signed-off-by: Willem de Bruijn <willemb@google.com>
----
v1 -> v2
- move so_txtime.c for net/lib to drivers/net (Jakub)
- fix drivers/net/config order (Jakub)
- detect passing when failure is expected (Jakub, Sashiko)
- pass pylint --disable=R (Jakub)
- only call ksft_run once (Jakub)
- do not sleep if waiting time is negative (Sashiko)
- add \n when converting error() to fprintf() (Sashiko)
- 4 space indentation, instead of 2 space
- increase sync delay from 100 to 200ms, to fix rare vng flakes
v1: https://lore.kernel.org/netdev/20260403175047.152646-1-willemdebruijn.kernel@gmail.com/
---
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/Makefile | 5 +-
tools/testing/selftests/drivers/net/config | 2 +
.../selftests/{ => drivers}/net/so_txtime.c | 24 +++-
.../selftests/drivers/net/so_txtime.py | 88 ++++++++++++++
tools/testing/selftests/net/.gitignore | 1 -
tools/testing/selftests/net/Makefile | 2 -
tools/testing/selftests/net/so_txtime.sh | 110 ------------------
8 files changed, 114 insertions(+), 119 deletions(-)
rename tools/testing/selftests/{ => drivers}/net/so_txtime.c (96%)
create mode 100755 tools/testing/selftests/drivers/net/so_txtime.py
delete mode 100755 tools/testing/selftests/net/so_txtime.sh
diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore
index 585ecb4d5dc4..e5314ce4bb2d 100644
--- a/tools/testing/selftests/drivers/net/.gitignore
+++ b/tools/testing/selftests/drivers/net/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
napi_id_helper
psp_responder
+so_txtime
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 7c7fa75b80c2..85d6a7e26627 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -20,12 +20,15 @@ TEST_PROGS := \
queues.py \
ring_reconfig.py \
shaper.py \
+ so_txtime.py \
stats.py \
xdp.py \
# end of TEST_PROGS
# YNL files, must be before "include ..lib.mk"
-YNL_GEN_FILES := psp_responder
+YNL_GEN_FILES := \
+ psp_responder \
+ so_txtime
TEST_GEN_FILES += $(YNL_GEN_FILES)
include ../../lib.mk
diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
index 77ccf83d87e0..2d39f263e03b 100644
--- a/tools/testing/selftests/drivers/net/config
+++ b/tools/testing/selftests/drivers/net/config
@@ -7,4 +7,6 @@ CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETCONSOLE_EXTENDED_LOG=y
CONFIG_NETDEVSIM=m
+CONFIG_NET_SCH_ETF=m
+CONFIG_NET_SCH_FQ=m
CONFIG_XDP_SOCKETS=y
diff --git a/tools/testing/selftests/net/so_txtime.c b/tools/testing/selftests/drivers/net/so_txtime.c
similarity index 96%
rename from tools/testing/selftests/net/so_txtime.c
rename to tools/testing/selftests/drivers/net/so_txtime.c
index b76df1efc2ef..7d144001ecf2 100644
--- a/tools/testing/selftests/net/so_txtime.c
+++ b/tools/testing/selftests/drivers/net/so_txtime.c
@@ -33,6 +33,8 @@
#include <unistd.h>
#include <poll.h>
+#include "kselftest.h"
+
static int cfg_clockid = CLOCK_TAI;
static uint16_t cfg_port = 8000;
static int cfg_variance_us = 4000;
@@ -43,6 +45,8 @@ static bool cfg_rx;
static uint64_t glob_tstart;
static uint64_t tdeliver_max;
+static int errors;
+
/* encode one timed transmission (of a 1B payload) */
struct timed_send {
char data;
@@ -131,13 +135,15 @@ static void do_recv_one(int fdr, struct timed_send *ts)
fprintf(stderr, "payload:%c delay:%lld expected:%lld (us)\n",
rbuf[0], (long long)tstop, (long long)texpect);
- if (rbuf[0] != ts->data)
- error(1, 0, "payload mismatch. expected %c", ts->data);
+ if (rbuf[0] != ts->data) {
+ fprintf(stderr, "payload mismatch. expected %c\n", ts->data);
+ errors++;
+ }
if (llabs(tstop - texpect) > cfg_variance_us) {
fprintf(stderr, "exceeds variance (%d us)\n", cfg_variance_us);
if (!getenv("KSFT_MACHINE_SLOW"))
- exit(1);
+ errors++;
}
}
@@ -255,8 +261,11 @@ static void start_time_wait(void)
return;
now = gettime_ns(CLOCK_REALTIME);
- if (cfg_start_time_ns < now)
+ if (cfg_start_time_ns < now) {
+ fprintf(stderr, "FAIL: start time already passed\n");
+ errors++;
return;
+ }
err = usleep((cfg_start_time_ns - now) / 1000);
if (err)
@@ -513,5 +522,10 @@ int main(int argc, char **argv)
else
do_test_tx((void *)&cfg_src_addr, cfg_alen);
- return 0;
+ if (errors) {
+ fprintf(stderr, "FAIL: %d errors\n", errors);
+ return KSFT_FAIL;
+ }
+
+ return KSFT_PASS;
}
diff --git a/tools/testing/selftests/drivers/net/so_txtime.py b/tools/testing/selftests/drivers/net/so_txtime.py
new file mode 100755
index 000000000000..31b95a7b5b8b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/so_txtime.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""Regression tests for the SO_TXTIME interface.
+
+Test delivery time in FQ and ETF qdiscs.
+"""
+
+import time
+
+from lib.py import ksft_exit, ksft_run, ksft_variants
+from lib.py import KsftNamedVariant, KsftSkipEx
+from lib.py import NetDrvEpEnv, bkg, cmd
+
+
+def test_so_txtime(cfg, clockid, ipver, args_tx, args_rx, expect_fail):
+ """Main function. Run so_txtime as sender and receiver."""
+ bin_path = cfg.test_dir / "so_txtime"
+
+ tstart = time.time_ns() + 200_000_000
+
+ cmd_addr = f"-S {cfg.addr_v[ipver]} -D {cfg.remote_addr_v[ipver]}"
+ cmd_base = f"{bin_path} -{ipver} -c {clockid} -t {tstart} {cmd_addr}"
+ cmd_rx = f"{cmd_base} {args_rx} -r"
+ cmd_tx = f"{cmd_base} {args_tx}"
+
+ with bkg(cmd_rx, host=cfg.remote, fail=(not expect_fail), exit_wait=True):
+ cmd(cmd_tx)
+
+
+def _test_variants_mono():
+ for ipver in ["4", "6"]:
+ for testcase in [
+ ["no_delay", "a,-1", "a,-1"],
+ ["zero_delay", "a,0", "a,0"],
+ ["one_pkt", "a,10", "a,10"],
+ ["in_order", "a,10,b,20", "a,10,b,20"],
+ ["reverse_order", "a,20,b,10", "b,20,a,20"],
+ ]:
+ name = f"_v{ipver}_{testcase[0]}"
+ yield KsftNamedVariant(name, ipver, testcase[1], testcase[2])
+
+
+@ksft_variants(_test_variants_mono())
+def test_so_txtime_mono(cfg, ipver, args_tx, args_rx):
+ """Run all variants of monotonic (fq) tests."""
+ cmd(f"tc qdisc replace dev {cfg.ifname} root fq")
+ test_so_txtime(cfg, "mono", ipver, args_tx, args_rx, False)
+
+
+def _test_variants_etf():
+ for ipver in ["4", "6"]:
+ for testcase in [
+ ["no_delay", "a,-1", "a,-1", True],
+ ["zero_delay", "a,0", "a,0", True],
+ ["one_pkt", "a,10", "a,10", False],
+ ["in_order", "a,10,b,20", "a,10,b,20", False],
+ ["reverse_order", "a,20,b,10", "b,10,a,20", False],
+ ]:
+ name = f"_v{ipver}_{testcase[0]}"
+ yield KsftNamedVariant(
+ name, ipver, testcase[1], testcase[2], testcase[3]
+ )
+
+
+@ksft_variants(_test_variants_etf())
+def test_so_txtime_etf(cfg, ipver, args_tx, args_rx, expect_fail):
+ """Run all variants of etf tests."""
+ try:
+ # ETF does not support change, so remove and re-add it instead.
+ cmd_prefix = f"tc qdisc replace dev {cfg.ifname} root"
+ cmd(f"{cmd_prefix} pfifo_fast")
+ cmd(f"{cmd_prefix} etf clockid CLOCK_TAI delta 400000")
+ except Exception as e:
+ raise KsftSkipEx("tc does not support qdisc etf. skipping") from e
+
+ test_so_txtime(cfg, "tai", ipver, args_tx, args_rx, expect_fail)
+
+
+def main() -> None:
+ """Boilerplate ksft main."""
+ with NetDrvEpEnv(__file__) as cfg:
+ ksft_run([test_so_txtime_mono, test_so_txtime_etf], args=(cfg,))
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 97ad4d551d44..02ad4c99a2b4 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -40,7 +40,6 @@ skf_net_off
socket
so_incoming_cpu
so_netns_cookie
-so_txtime
so_rcv_listener
stress_reuseport_listen
tap
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 6bced3ed798b..b7f51e8f190f 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -81,7 +81,6 @@ TEST_PROGS := \
rxtimestamp.sh \
sctp_vrf.sh \
skf_net_off.sh \
- so_txtime.sh \
srv6_end_dt46_l3vpn_test.sh \
srv6_end_dt4_l3vpn_test.sh \
srv6_end_dt6_l3vpn_test.sh \
@@ -154,7 +153,6 @@ TEST_GEN_FILES := \
skf_net_off \
so_netns_cookie \
so_rcv_listener \
- so_txtime \
socket \
stress_reuseport_listen \
tcp_fastopen_backup_key \
diff --git a/tools/testing/selftests/net/so_txtime.sh b/tools/testing/selftests/net/so_txtime.sh
deleted file mode 100755
index 5e861ad32a42..000000000000
--- a/tools/testing/selftests/net/so_txtime.sh
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# Regression tests for the SO_TXTIME interface
-
-set -e
-
-readonly ksft_skip=4
-readonly DEV="veth0"
-readonly BIN="./so_txtime"
-
-readonly RAND="$(mktemp -u XXXXXX)"
-readonly NSPREFIX="ns-${RAND}"
-readonly NS1="${NSPREFIX}1"
-readonly NS2="${NSPREFIX}2"
-
-readonly SADDR4='192.168.1.1'
-readonly DADDR4='192.168.1.2'
-readonly SADDR6='fd::1'
-readonly DADDR6='fd::2'
-
-cleanup() {
- ip netns del "${NS2}"
- ip netns del "${NS1}"
-}
-
-trap cleanup EXIT
-
-# Create virtual ethernet pair between network namespaces
-ip netns add "${NS1}"
-ip netns add "${NS2}"
-
-ip link add "${DEV}" netns "${NS1}" type veth \
- peer name "${DEV}" netns "${NS2}"
-
-# Bring the devices up
-ip -netns "${NS1}" link set "${DEV}" up
-ip -netns "${NS2}" link set "${DEV}" up
-
-# Set fixed MAC addresses on the devices
-ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
-ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
-
-# Add fixed IP addresses to the devices
-ip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}"
-ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}"
-ip -netns "${NS1}" addr add fd::1/64 dev "${DEV}" nodad
-ip -netns "${NS2}" addr add fd::2/64 dev "${DEV}" nodad
-
-run_test() {
- local readonly IP="$1"
- local readonly CLOCK="$2"
- local readonly TXARGS="$3"
- local readonly RXARGS="$4"
-
- if [[ "${IP}" == "4" ]]; then
- local readonly SADDR="${SADDR4}"
- local readonly DADDR="${DADDR4}"
- elif [[ "${IP}" == "6" ]]; then
- local readonly SADDR="${SADDR6}"
- local readonly DADDR="${DADDR6}"
- else
- echo "Invalid IP version ${IP}"
- exit 1
- fi
-
- local readonly START="$(date +%s%N --date="+ 0.1 seconds")"
-
- ip netns exec "${NS2}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${RXARGS}" -r &
- ip netns exec "${NS1}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${TXARGS}"
- wait "$!"
-}
-
-do_test() {
- run_test $@
- [ $? -ne 0 ] && ret=1
-}
-
-do_fail_test() {
- run_test $@
- [ $? -eq 0 ] && ret=1
-}
-
-ip netns exec "${NS1}" tc qdisc add dev "${DEV}" root fq
-set +e
-ret=0
-do_test 4 mono a,-1 a,-1
-do_test 6 mono a,0 a,0
-do_test 6 mono a,10 a,10
-do_test 4 mono a,10,b,20 a,10,b,20
-do_test 6 mono a,20,b,10 b,20,a,20
-
-if ip netns exec "${NS1}" tc qdisc replace dev "${DEV}" root etf clockid CLOCK_TAI delta 400000; then
- do_fail_test 4 tai a,-1 a,-1
- do_fail_test 6 tai a,0 a,0
- do_test 6 tai a,10 a,10
- do_test 4 tai a,10,b,20 a,10,b,20
- do_test 6 tai a,20,b,10 b,10,a,20
-else
- echo "tc ($(tc -V)) does not support qdisc etf. skipping"
- [ $ret -eq 0 ] && ret=$ksft_skip
-fi
-
-if [ $ret -eq 0 ]; then
- echo OK. All tests passed
-elif [[ $ret -ne $ksft_skip && -n "$KSFT_MACHINE_SLOW" ]]; then
- echo "Ignoring errors due to slow environment" 1>&2
- ret=0
-fi
-exit $ret
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply related
* [PATCH ipsec-next] xfrm: Drop support for HMAC-RIPEMD-160
From: Eric Biggers @ 2026-04-05 1:15 UTC (permalink / raw)
To: netdev, Steffen Klassert, Herbert Xu, David S. Miller
Cc: linux-crypto, linux-kernel, Eric Biggers
Drop support for HMAC-RIPEMD-160 from IPsec to reduce the UAPI surface
and simplify future maintenance. It's almost certainly unused.
RIPEMD-160 received some attention in the early 2000s when SHA-* weren't
quite as well established. But it never received much adoption outside
of certain niches such as Bitcoin.
It's actually unclear that Linux + IPsec + HMAC-RIPEMD-160 has *ever*
been used, even historically. When support for it was added in 2003, it
was done so in a "cleanup" commit without any justification [1]. It
didn't actually work until someone happened to fix it 5 years later [2].
That person didn't use or test it either [3]. Finally, also note that
"hmac(rmd160)" is by far the slowest of the algorithms in aalg_list[].
Of course, today IPsec is usually used with an AEAD, such as AES-GCM.
But even for IPsec users still using a dedicated auth algorithm, they
almost certainly aren't using, and shouldn't use, HMAC-RIPEMD-160.
Thus, let's just drop support for it. Note: no kconfig update is
needed, since CRYPTO_RMD160 wasn't actually being selected anyway.
References:
[1] linux-history commit d462985fc1941a47
("[IPSEC]: Clean up key manager algorithm handling.")
[2] linux commit a13366c632132bb9
("xfrm: xfrm_algo: correct usage of RIPEMD-160")
[3] https://lore.kernel.org/all/1212340578-15574-1-git-send-email-rueegsegger@swiss-it.ch
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
net/xfrm/xfrm_algo.c | 20 --------------------
tools/testing/selftests/net/ipsec.c | 8 ++------
2 files changed, 2 insertions(+), 26 deletions(-)
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 749011e031c0a..70434495f23f5 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -288,30 +288,10 @@ static struct xfrm_algo_desc aalg_list[] = {
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 512,
.sadb_alg_maxbits = 512
}
},
-{
- .name = "hmac(rmd160)",
- .compat = "rmd160",
-
- .uinfo = {
- .auth = {
- .icv_truncbits = 96,
- .icv_fullbits = 160,
- }
- },
-
- .pfkey_supported = 1,
-
- .desc = {
- .sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC,
- .sadb_alg_ivlen = 0,
- .sadb_alg_minbits = 160,
- .sadb_alg_maxbits = 160
- }
-},
{
.name = "xcbc(aes)",
.uinfo = {
.auth = {
diff --git a/tools/testing/selftests/net/ipsec.c b/tools/testing/selftests/net/ipsec.c
index f4afef51b9307..89c32c354c008 100644
--- a/tools/testing/selftests/net/ipsec.c
+++ b/tools/testing/selftests/net/ipsec.c
@@ -60,12 +60,10 @@
#define grchild_ip(nr) (4*nr + 2)
#define VETH_FMT "ktst-%d"
#define VETH_LEN 12
-#define XFRM_ALGO_NR_KEYS 29
-
static int nsfd_parent = -1;
static int nsfd_childa = -1;
static int nsfd_childb = -1;
static long page_size;
@@ -94,11 +92,10 @@ struct xfrm_key_entry xfrm_key_entries[] = {
{"cmac(aes)", 128},
{"xcbc(aes)", 128},
{"cbc(cast5)", 128},
{"cbc(serpent)", 128},
{"hmac(sha1)", 160},
- {"hmac(rmd160)", 160},
{"cbc(des3_ede)", 192},
{"hmac(sha256)", 256},
{"cbc(aes)", 256},
{"cbc(camellia)", 256},
{"cbc(twofish)", 256},
@@ -811,11 +808,11 @@ static int do_ping(int cmd_fd, char *buf, size_t buf_len, struct in_addr from,
static int xfrm_fill_key(char *name, char *buf,
size_t buf_len, unsigned int *key_len)
{
int i;
- for (i = 0; i < XFRM_ALGO_NR_KEYS; i++) {
+ for (i = 0; i < ARRAY_SIZE(xfrm_key_entries); i++) {
if (strncmp(name, xfrm_key_entries[i].algo_name, ALGO_LEN) == 0)
*key_len = xfrm_key_entries[i].key_len;
}
if (*key_len > buf_len) {
@@ -2059,12 +2056,11 @@ static int write_desc(int proto, int test_desc_fd,
}
int proto_list[] = { IPPROTO_AH, IPPROTO_COMP, IPPROTO_ESP };
char *ah_list[] = {
"digest_null", "hmac(md5)", "hmac(sha1)", "hmac(sha256)",
- "hmac(sha384)", "hmac(sha512)", "hmac(rmd160)",
- "xcbc(aes)", "cmac(aes)"
+ "hmac(sha384)", "hmac(sha512)", "xcbc(aes)", "cmac(aes)"
};
char *comp_list[] = {
"deflate",
#if 0
/* No compression backend realization */
base-commit: be14d13625c9b070c33c423026b598ed65695225
--
2.53.0
^ permalink raw reply related
* Re: [PATCH net] bridge: cfm: do not reschedule TX work when interval is zero
From: Xiang Mei @ 2026-04-05 0:04 UTC (permalink / raw)
To: Simon Horman
Cc: netdev, bridge, razor, idosch, davem, edumazet, pabeni, bestswngs
In-Reply-To: <20260327112056.GC567789@horms.kernel.org>
On Fri, Mar 27, 2026 at 4:21 AM Simon Horman <horms@kernel.org> wrote:
>
> On Wed, Mar 25, 2026 at 08:19:57PM -0700, Xiang Mei wrote:
> > ccm_tx_work_expired() uses interval_to_us() to convert the configured
> > exp_interval enum into a microsecond delay, then passes it to
> > queue_delayed_work() to schedule the next iteration. The ccm_tx_dwork
> > callback re-arms the same delayed_work struct at the end of each
> > invocation, forming a repeating timer.
> >
> > interval_to_us() returns 0 for BR_CFM_CCM_INTERVAL_NONE and any
> > out-of-range enum value. When this 0 is passed to queue_delayed_work()
> > as the delay, the work item fires immediately and re-arms itself with
> > zero delay again, creating an infinite tight loop. Each iteration
> > allocates an skb via ccm_frame_build() and queues it for transmission.
> > The skbs pile up faster than the network stack can free them because the
> > worker never yields the CPU, rapidly exhausting all kernel memory until
> > OOM deadlock panic.
> >
> > Since CC config and CCM TX are independent netlink commands that can be
> > issued in any order, there is no single configuration entry point where
> > rejecting interval=0 would cover all cases.
> >
> > Fix this by checking the interval at the start of ccm_tx_work_expired()
> > and stopping transmission immediately if it is zero. Set period to 0 so
> > that br_cfm_cc_ccm_tx() correctly sees transmission as stopped and can
> > restart it later if a valid interval is configured. This also avoids
> > transmitting a CCM frame with an invalid interval value.
>
> Hi,
>
> I think that the principle should be that code that doesn't need
> to be in the datapath shouldn't be in the datapath.
>
> So, with that in mind, I think it would be better to set a lower bound on
> exp_interval when the mep is:
>
> a) Created. It looks like that happens in br_cfm_mep_create
> b) Configured. It looks like that can be done by setting a policy on the
> minimum value of IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL
>
Thanks for the suggestion. You are right, it's better to move the
check out of the datapath. V2 has been sent, which blocks the invalid
interval in creation/configuration.
> >
> > Fixes: a806ad8ee2aa ("bridge: cfm: Kernel space implementation of CFM. CCM frame TX added.")
> > Reported-by: Weiming Shi <bestswngs@gmail.com>
> > Signed-off-by: Xiang Mei <xmei5@asu.edu>
>
> ...
^ permalink raw reply
* [PATCH net v2] bridge: cfm: reject invalid CCM interval at configuration time
From: Xiang Mei @ 2026-04-05 0:03 UTC (permalink / raw)
To: netdev
Cc: horms, bridge, razor, idosch, davem, edumazet, pabeni, bestswngs,
Xiang Mei
ccm_tx_work_expired() re-arms itself via queue_delayed_work() using
the configured exp_interval converted by interval_to_us(). When
exp_interval is BR_CFM_CCM_INTERVAL_NONE or out of range,
interval_to_us() returns 0, causing the worker to fire immediately in
a tight loop that allocates skbs until OOM.
Fix this by validating exp_interval at configuration time:
- Constrain IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL to [1, 7] in the
netlink policy so userspace cannot set an invalid value.
- Reject starting CCM TX in br_cfm_cc_ccm_tx() when exp_interval has
not yet been configured (defaults to 0 from kzalloc).
Fixes: a806ad8ee2aa ("bridge: cfm: Kernel space implementation of CFM. CCM frame TX added.")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
v2: Move validation out of the datapath and into configuration
net/bridge/br_cfm.c | 6 ++++++
net/bridge/br_cfm_netlink.c | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c
index 118c7ea48c35..dea56fffa1c1 100644
--- a/net/bridge/br_cfm.c
+++ b/net/bridge/br_cfm.c
@@ -805,6 +805,12 @@ int br_cfm_cc_ccm_tx(struct net_bridge *br, const u32 instance,
goto save;
}
+ if (!interval_to_us(mep->cc_config.exp_interval)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Invalid CCM interval");
+ return -EINVAL;
+ }
+
/* Start delayed work to transmit CCM frames. It is done with zero delay
* to send first frame immediately
*/
diff --git a/net/bridge/br_cfm_netlink.c b/net/bridge/br_cfm_netlink.c
index 2faab44652e7..1bb33c8f587b 100644
--- a/net/bridge/br_cfm_netlink.c
+++ b/net/bridge/br_cfm_netlink.c
@@ -34,7 +34,7 @@ br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
[IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT },
[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 },
[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 },
- [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
+ [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = NLA_POLICY_RANGE(NLA_U32, 1, 7),
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = {
.type = NLA_BINARY, .len = CFM_MAID_LENGTH },
};
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next v1] r8169: implement get_module functions for rtl8127atf
From: Fabio Baltieri @ 2026-04-04 23:05 UTC (permalink / raw)
To: Andrew Lunn
Cc: Heiner Kallweit, nic_swsd, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King - ARM Linux, netdev, linux-kernel
In-Reply-To: <368d3f30-b4af-4548-a4b9-f8e4e4f9a4cb@lunn.ch>
On Sun, Apr 05, 2026 at 12:46:41AM +0200, Andrew Lunn wrote:
> On Sat, Apr 04, 2026 at 11:55:25PM +0200, Heiner Kallweit wrote:
> > On 04.04.2026 22:13, Fabio Baltieri wrote:
> > > Implement get_module_info and get_module_eeprom for supported devices,
> > > right now that's the rtl8127atf.
> > >
> > > This enables using ethtool to retrieve the transceiver identification
> > > and diagnostic data.
> > >
> > > Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
> > > ---
> > >
> > > Hi,
> > >
> > > Realtek released a new out of tree driver for the rtl8127 and it
> > > includes some code that exposes the I2C controller connected to the SFP
> > > port.
> > >
> > > This patch implements get_module_info and get_module_eeprom based on the
> > > information found on that driver, it allows ethtool to fetch the SFP
> > > module information, which is useful both to identify the module and to
> > > track the health of fiber optic transceivers.
> > >
> > > The logic for the SFF standard and i2c address selection is borrowed
> > > directly from the aquantia/atlantic driver, I don't have a lot of stuff
> > > to test it but I was able to trigger all code paths from a fiber optic
> > > transceiver and an SFP cable I have available.
> > >
> >
> > Hi Fabio, thanks for the patch. Being able to access the SFP I2C bus is an
> > important step towards future phylink/SFP support.
> >
> > @Russell/@Andrew
> > I'm not really familiar with the phylink and sfp code. And I would like to have
> > the functionality being implemented here reusable once we do further steps
> > towards phylink support in r8169. So how shall the code be modeled, which
> > components are needed?
> > - Shall the SFP I2C bus be modeled as a struct i2c_adapter?
>
> Yes, that would be best. Call i2c_add_adapter() to add it to the I2C
> core. The SFP code in drivers/net/phy can then make use of it.
>
> > - Shall we (partially?) implement a struct sfp, so that functions like
> > sfp_module_eeprom() can be used (implicitly)?
> >
> > I assume this patch includes logic which duplicates what is available in
> > phylink/sfp already. I'd a appreciate any hints you can provide.
>
> No. phylink etc will end up populating netdev->sfp_bus, and then
> get_module_eeprom_by_page() should then just make the module work in
> ethtool.
>
> The interesting bit if gluing it all together, without DT. But
> txgbe_phy.c should be something you can copy from.
>
> Does the out of tree driver give access to GPIOs connected to the SFP
> cage pins? Ideally you want those as well, for loss of signal,
> transmitter disable, knowing when a module has been inserted into the
> cage, etc.
The current version does not seem to do that, maybe the Realtek folks
can chime in about it.
I'll look into the dw driver, thanks for the pointer.
> And you will need a PCS driver.
>
> But first step is probably to work with the existing Base-T devices
> and convert the driver to phylink.
^ permalink raw reply
* Re: [PATCH net v2] tg3: Add PowerEdge R740xd to AER quirk list
From: Andrew Lunn @ 2026-04-04 23:03 UTC (permalink / raw)
To: Oskar Ray-Frayssinet
Cc: pavan.chebbi, mchan, andrew+netdev, davem, edumazet, kuba, pabeni,
horms, lszubowi, netdev, linux-kernel
In-Reply-To: <20260404225023.1254-1-rayfraytech@gmail.com>
On Sun, Apr 05, 2026 at 12:50:23AM +0200, Oskar Ray-Frayssinet wrote:
> The PowerEdge R740xd is a variant of the R740 that also triggers
> a fatal PCIe AER event during system reboot. Add it to the DMI
> list to apply the same workaround.
>
> Fixes: e0efe83ed325 ("tg3: Disable tg3 PCIe AER on system reboot")
>
> Signed-off-by: Oskar Ray-Frayssinet <rayfraytech@gmail.com>
> ---
> v2: Also add "R740XD vSAN Ready Node" DMI name as reported in
> bugzilla #221279 by Thomas Berger
> v1: Add "PowerEdge R740xd" DMI name
https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html
says:
* don’t repost your patches within one 24h period
> @@ -18216,6 +18216,18 @@ static const struct dmi_system_id tg3_restart_aer_quirk_table[] = {
> DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740"),
> },
> },
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740xd"),
> + },
> + },
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "R740XD vSAN Ready Node"),
> + },
> + },
> {
> .matches = {
> DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
When you look at tg3_restart_aer_quirk_table[] they are all Dell. Are
there any Dell systems which actually work? Would it make sense to
mark all Dell systems as broken and enable the quirk? Then there is no
need to play whack-a-mole.
Andrew
^ permalink raw reply
* [PATCH net-next] selftests: drv-net: adjust to socat changes
From: Jakub Kicinski @ 2026-04-04 23:01 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, Jakub Kicinski,
leitao, shuah, hawk, john.fastabend, sdf, linux-kselftest
socat v1.8.1.0 now defaults to shut-null, it sends an extra
0-length UDP packet when sender disconnects. This breaks
our tests which expect the exact packet sequence.
Add shut-none which was the old default where necessary.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: leitao@debian.org
CC: shuah@kernel.org
CC: hawk@kernel.org
CC: john.fastabend@gmail.com
CC: sdf@fomichev.me
CC: linux-kselftest@vger.kernel.org
---
tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh | 6 +++---
tools/testing/selftests/drivers/net/xdp.py | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
index 02dcdeb723be..a9a01a64b7b3 100644
--- a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
+++ b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
@@ -251,7 +251,7 @@ function listen_port_and_save_to() {
# Just wait for 3 seconds
timeout 3 ip netns exec "${NAMESPACE}" \
- socat "${SOCAT_MODE}":"${PORT}",fork "${OUTPUT}" 2> /dev/null
+ socat "${SOCAT_MODE}":"${PORT}",fork,shut-none "${OUTPUT}" 2> /dev/null
}
# Only validate that the message arrived properly
@@ -360,8 +360,8 @@ function check_for_taskset() {
# This is necessary if running multiple tests in a row
function pkill_socat() {
- PROCESS_NAME4="socat UDP-LISTEN:6666,fork ${OUTPUT_FILE}"
- PROCESS_NAME6="socat UDP6-LISTEN:6666,fork ${OUTPUT_FILE}"
+ PROCESS_NAME4="socat UDP-LISTEN:6666,fork,shut-none ${OUTPUT_FILE}"
+ PROCESS_NAME6="socat UDP6-LISTEN:6666,fork,shut-none ${OUTPUT_FILE}"
# socat runs under timeout(1), kill it if it is still alive
# do not fail if socat doesn't exist anymore
set +e
diff --git a/tools/testing/selftests/drivers/net/xdp.py b/tools/testing/selftests/drivers/net/xdp.py
index d86446569f89..7e635487d517 100755
--- a/tools/testing/selftests/drivers/net/xdp.py
+++ b/tools/testing/selftests/drivers/net/xdp.py
@@ -70,7 +70,7 @@ from lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
cfg.require_cmd("socat", remote=True)
rx_udp_cmd = f"socat -{cfg.addr_ipver} -T 2 -u UDP-RECV:{port},reuseport STDOUT"
- tx_udp_cmd = f"echo -n {test_string} | socat -t 2 -u STDIN UDP:{cfg.baddr}:{port}"
+ tx_udp_cmd = f"echo -n {test_string} | socat -t 2 -u STDIN UDP:{cfg.baddr}:{port},shut-none"
with bkg(rx_udp_cmd, exit_wait=True) as nc:
wait_port_listen(port, proto="udp")
@@ -271,7 +271,7 @@ from lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
# Writing zero bytes to stdin gets ignored by socat,
# but with the shut-null flag socat generates a zero sized packet
# when the socket is closed.
- tx_cmd_suffix = ",shut-null" if payload_len == 0 else ""
+ tx_cmd_suffix = ",shut-null" if payload_len == 0 else ",shut-none"
tx_udp = f"echo -n {test_string} | socat -t 2 " + \
f"-u STDIN UDP:{cfg.baddr}:{port}{tx_cmd_suffix}"
--
2.53.0
^ permalink raw reply related
* Re: [PATCH net-next v1] r8169: implement get_module functions for rtl8127atf
From: Andrew Lunn @ 2026-04-04 22:57 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Heiner Kallweit, nic_swsd, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King - ARM Linux, netdev, linux-kernel
In-Reply-To: <adGSjRScv9tcYRoU@google.com>
> Yeah happy to hear any input on it, the controller actually seems to be
> a designware IP
Ah, interesting. Ideally you want to use the existing designware
driver. Take a look at txgbe_i2c_register().
Andrew
^ permalink raw reply
* [PATCH net v2] tg3: Add PowerEdge R740xd to AER quirk list
From: Oskar Ray-Frayssinet @ 2026-04-04 22:50 UTC (permalink / raw)
To: pavan.chebbi
Cc: mchan, andrew+netdev, davem, edumazet, kuba, pabeni, horms,
lszubowi, netdev, linux-kernel, Oskar Ray-Frayssinet
The PowerEdge R740xd is a variant of the R740 that also triggers
a fatal PCIe AER event during system reboot. Add it to the DMI
list to apply the same workaround.
Fixes: e0efe83ed325 ("tg3: Disable tg3 PCIe AER on system reboot")
Signed-off-by: Oskar Ray-Frayssinet <rayfraytech@gmail.com>
---
v2: Also add "R740XD vSAN Ready Node" DMI name as reported in
bugzilla #221279 by Thomas Berger
v1: Add "PowerEdge R740xd" DMI name
drivers/net/ethernet/broadcom/tg3.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 73a4b569b03e..2b95c97e8161 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -18216,6 +18216,18 @@ static const struct dmi_system_id tg3_restart_aer_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740"),
},
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740xd"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "R740XD vSAN Ready Node"),
+ },
+ },
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next v1] r8169: implement get_module functions for rtl8127atf
From: Andrew Lunn @ 2026-04-04 22:46 UTC (permalink / raw)
To: Heiner Kallweit
Cc: Fabio Baltieri, nic_swsd, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King - ARM Linux, netdev, linux-kernel
In-Reply-To: <4f8310c2-07be-452a-84fa-0ec87d985651@gmail.com>
On Sat, Apr 04, 2026 at 11:55:25PM +0200, Heiner Kallweit wrote:
> On 04.04.2026 22:13, Fabio Baltieri wrote:
> > Implement get_module_info and get_module_eeprom for supported devices,
> > right now that's the rtl8127atf.
> >
> > This enables using ethtool to retrieve the transceiver identification
> > and diagnostic data.
> >
> > Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
> > ---
> >
> > Hi,
> >
> > Realtek released a new out of tree driver for the rtl8127 and it
> > includes some code that exposes the I2C controller connected to the SFP
> > port.
> >
> > This patch implements get_module_info and get_module_eeprom based on the
> > information found on that driver, it allows ethtool to fetch the SFP
> > module information, which is useful both to identify the module and to
> > track the health of fiber optic transceivers.
> >
> > The logic for the SFF standard and i2c address selection is borrowed
> > directly from the aquantia/atlantic driver, I don't have a lot of stuff
> > to test it but I was able to trigger all code paths from a fiber optic
> > transceiver and an SFP cable I have available.
> >
>
> Hi Fabio, thanks for the patch. Being able to access the SFP I2C bus is an
> important step towards future phylink/SFP support.
>
> @Russell/@Andrew
> I'm not really familiar with the phylink and sfp code. And I would like to have
> the functionality being implemented here reusable once we do further steps
> towards phylink support in r8169. So how shall the code be modeled, which
> components are needed?
> - Shall the SFP I2C bus be modeled as a struct i2c_adapter?
Yes, that would be best. Call i2c_add_adapter() to add it to the I2C
core. The SFP code in drivers/net/phy can then make use of it.
> - Shall we (partially?) implement a struct sfp, so that functions like
> sfp_module_eeprom() can be used (implicitly)?
>
> I assume this patch includes logic which duplicates what is available in
> phylink/sfp already. I'd a appreciate any hints you can provide.
No. phylink etc will end up populating netdev->sfp_bus, and then
get_module_eeprom_by_page() should then just make the module work in
ethtool.
The interesting bit if gluing it all together, without DT. But
txgbe_phy.c should be something you can copy from.
Does the out of tree driver give access to GPIOs connected to the SFP
cage pins? Ideally you want those as well, for loss of signal,
transmitter disable, knowing when a module has been inserted into the
cage, etc.
And you will need a PCS driver.
But first step is probably to work with the existing Base-T devices
and convert the driver to phylink.
Andrew
---
pw-bot: cr
^ permalink raw reply
* Re: [PATCH net] net: avoid nul-deref trying to bind mp to incapable device
From: Daniel Borkmann @ 2026-04-04 22:43 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, sdf, almasrymina
In-Reply-To: <20260404001938.2425670-1-kuba@kernel.org>
On 4/4/26 2:19 AM, Jakub Kicinski wrote:
> Sashiko points out that we use qops in __net_mp_open_rxq()
> but never validate they are null. This was introduced when
> check was moved from netdev_rx_queue_restart().
>
> Look at ops directly instead of the locking config.
> qops imply netdev_need_ops_lock(). We used netdev_need_ops_lock()
> initially to signify that the real_num_rx_queues check below
> is safe without rtnl_lock, but I'm not sure if this is actually
> clear to most people, anyway.
>
> Fixes: da7772a2b4ad ("net: move mp->rx_page_size validation to __net_mp_open_rxq()")
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next v1] r8169: implement get_module functions for rtl8127atf
From: Fabio Baltieri @ 2026-04-04 22:37 UTC (permalink / raw)
To: Heiner Kallweit
Cc: nic_swsd, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King - ARM Linux,
Andrew Lunn, netdev, linux-kernel
In-Reply-To: <4f8310c2-07be-452a-84fa-0ec87d985651@gmail.com>
On Sat, Apr 04, 2026 at 11:55:25PM +0200, Heiner Kallweit wrote:
> On 04.04.2026 22:13, Fabio Baltieri wrote:
> > Implement get_module_info and get_module_eeprom for supported devices,
> > right now that's the rtl8127atf.
> >
> > This enables using ethtool to retrieve the transceiver identification
> > and diagnostic data.
> >
> > Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
> > ---
> >
> > Hi,
> >
> > Realtek released a new out of tree driver for the rtl8127 and it
> > includes some code that exposes the I2C controller connected to the SFP
> > port.
> >
> > This patch implements get_module_info and get_module_eeprom based on the
> > information found on that driver, it allows ethtool to fetch the SFP
> > module information, which is useful both to identify the module and to
> > track the health of fiber optic transceivers.
> >
> > The logic for the SFF standard and i2c address selection is borrowed
> > directly from the aquantia/atlantic driver, I don't have a lot of stuff
> > to test it but I was able to trigger all code paths from a fiber optic
> > transceiver and an SFP cable I have available.
> >
>
> Hi Fabio, thanks for the patch. Being able to access the SFP I2C bus is an
> important step towards future phylink/SFP support.
>
> @Russell/@Andrew
> I'm not really familiar with the phylink and sfp code. And I would like to have
> the functionality being implemented here reusable once we do further steps
> towards phylink support in r8169. So how shall the code be modeled, which
> components are needed?
> - Shall the SFP I2C bus be modeled as a struct i2c_adapter?
> - Shall we (partially?) implement a struct sfp, so that functions like
> sfp_module_eeprom() can be used (implicitly)?
Yeah happy to hear any input on it, the controller actually seems to be
a designware IP and there is some reusable code for it but what I've
seen done for other drivers for this functionality is to implement a
minimum i2c "read bulk" functionality in the driver itself, so that's
what I proposed here too, the code is fairly simple after all. However I
did borrow some logic much verbatim from the atlantis driver as I
mentioned, happy to hear if there's a path to reuse.
>
> I assume this patch includes logic which duplicates what is available in
> phylink/sfp already. I'd a appreciate any hints you can provide.
>
> Thanks, Heiner
^ permalink raw reply
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