HSR/PRP requires per-wire-frame tags/RCTs and sequence numbers, and
duplicate discard is per frame. RX GRO and TX GSO can present multiple
frames as one skb and violate that assumption: a super-skb is either
rejected by a constrained lower device, or forwarded without valid
per-frame trailers and sequence numbers. An oversized PRP aggregate
can also truncate the RCT's 12-bit LSDU size field.
Patch 1 keeps software GRO off while devices are direct HSR/PRP
members, in the requested as well as in the active features. Fixed-on
or driver-required GRO_HW may remain enabled.
Patch 2 refuses bridge, bond, team, OVS, macvlan and MACsec devices,
and devices without an RX handler such as ipvlan and VRF, as HSR/PRP
ports. This closes the syzbot report of recursive seqnr_lock locking
through a bridge whose port is a second HSR master. seqnr_lock stays as
it is.
Patch 3 segments valid GSO before per-frame processing, so each wire
frame gets its own tag/RCT and sequence number; segmentation runs
outside seqnr_lock. Patch 4 tests member GRO policy, port refusal, GSO
forwarding and local submission order.
A typical GSO source is a container connected to a PRP RedBox
interlink through veth. An existing TCP/UDP GSO skb can reach the
interlink with GRO disabled:
container/netns host PRP RedBox
prp0-peer ---- veth ---- prp0-int (interlink RX)
|
split GSO into frames
|
sequence number + RCT
/ \
LAN A LAN B
Compatibility with older PRP senders:
Valid PRP frames from older senders remain supported. Some old Linux
PRP senders incorrectly append one RCT to an entire GSO skb. This
violates the per-frame PRP requirement. Patch 3 drops such intact
aggregates when trailing bytes extend past a known, nonzero IP length;
zero lengths and GSO_PARTIAL are not covered by that check.
On virtio-net/TAP paths, disabling GRO_HW in patch 1 can make the host
segment an old sender's malformed aggregate before it reaches the
receiving VM. The RCT then becomes transport payload, which the
receiver cannot reliably identify or remove. Upgrade the sender or
disable GSO/TSO on its HSR/PRP master.
Validation:
On a lockdep kernel with the series, the GRO selftest passed 15/15
and the ordered selftest 5/5. The syzbot reproducer reports recursive
locking on the base kernel and nothing on the series in five minutes.
It needed one adjusted ifindex, because the caif device it counts on
no longer exists. Down/up of an attached veth and detach of a veth
attached while down hang or hit BUG_ON with v7 and pass with this
series.
W=1 allmodconfig and allyesconfig builds show no new warnings against
the base.
Based on net fafbc4051123 (2026-11-05). The series applies without
conflicts to net 30c71476d842 and net-next fa5196392691, where net/hsr
is identical. The net-next conflicts reported for v7 came from the
sequence-number changes in v7's patch 2, which this version drops.
No stable backport is requested here. The remaining HSR dev->stats
races are left to a separate series, as Paolo suggested [1].
Pre-existing shared-skb mutations are also handled separately.
[1] https://lore.kernel.org/netdev/4fc3b9f1-4bef-4b34-ae7a-e89037cce829@redhat.com/ (local)
Changes since v7:
- Patch 1: also clear GRO and configurable GRO_HW from wanted_features.
veth adds and deletes its NAPI instances according to the request, so
the v7 split between requested and active GRO could hang
"ip link set down" or hit the BUG_ON() in napi_enable() (the critical
NIPA finding on patch 1). GRO is no longer restored when a port leaves,
as for LRO; the comments only claim GRO off for direct members.
- Patch 2: replace the ordered forwarding consumer with a check of the
port type, as Sebastian suggested [2]; seqnr_lock is unchanged. The
rule is by device type rather than "no lower devices" as I wrote in
the thread, because DSA user ports are uppers of their conduit.
Dropping the consumer also drops the review points on its admission
limit, supervision budget and PREEMPT_RT behavior. Narrowing
seqnr_lock is left to a separate net-next change, where Hangbin's
patch fits [3]. Ports whose RX handler is in use or not supported are
refused before any state change too, so a refused device keeps its
GRO request.
- Patch 3: segment before taking seqnr_lock and number each segment
under it; the lock moves from the callers into the per-frame helper.
A still-shared GSO input is unshared before segmentation. New gate
drops are counted once on the entry device.
- Patch 4: the GRO checks follow the new policy, including the
requested state. New cases cover down/up while attached, attach while
down then up and detach, a request while attached, and port refusal.
From the NIPA review: CONFIG_MACVLAN and CONFIG_BONDING in config,
captures scoped to their case, read-back instead of ethtool output
matching, PRP trailers decoded only on PRP LANs with the kernel's
fallback, capture sockets bound before they receive, producer errors
not hidden by the barrier, INT/TERM blocked while namespaces or
handlers switch, completion on the expected frames rather than a quiet
period, and only the common prefix compared where supervision runs
through the lane cutoff. Unused code is removed. The helper stays
standalone instead of using net/lib/py, which has no in-process,
namespace-bound AF_PACKET capture or stop-after-failure TAP handling.
The remaining low-severity remarks are addressed or went away with
the consumer.
[2] https://lore.kernel.org/netdev/20261014151838.6RyMIRVM@linutronix.de/ (local)
[3] https://lore.kernel.org/netdev/20260805-hsr_deadlock-v1-1-d8a6f06fc5a8@kylinos.cn/ (local)
Previous postings (earlier design, newest first):
v7: https://lore.kernel.org/netdev/20261009201324.17-1-xiexinet@gmail.com/ (local)
v6: https://lore.kernel.org/netdev/20260809121455.1745-1-xiexinet@gmail.com/ (local)
v5: https://lore.kernel.org/netdev/20260807140751.1351-1-xiexinet@gmail.com/ (local)
v4: https://lore.kernel.org/netdev/20260803222211.877-1-xiexinet@gmail.com/ (local)
v3: https://lore.kernel.org/netdev/20260731090224.18-1-xiexinet@gmail.com/ (local)
v2: https://lore.kernel.org/netdev/20260724161253.79-1-xiexinet@gmail.com/ (local)
v1: https://lore.kernel.org/netdev/20260722171836.196-1-xiexinet@gmail.com/ (local)
Xin Xie (4):
net: hsr: keep GRO disabled on HSR/PRP ports
net: hsr: refuse forwarding devices as HSR/PRP ports
net: hsr: segment GSO before per-frame forwarding
selftests: net: hsr: verify GRO policy and ordered forwarding
.../networking/net_cachelines/net_device.rst | 1 +
include/linux/netdevice.h | 7 +
net/core/dev.c | 15 +
net/hsr/hsr_device.c | 6 +-
net/hsr/hsr_forward.c | 154 ++
net/hsr/hsr_forward.h | 1 +
net/hsr/hsr_slave.c | 94 +-
tools/testing/selftests/net/hsr/Makefile | 7 +-
tools/testing/selftests/net/hsr/config | 4 +
.../selftests/net/hsr/hsr_gro_superpacket.py | 1376 +++++++++++++++++
.../selftests/net/hsr/hsr_gro_superpacket.sh | 9 +
.../net/hsr/hsr_ordered_forwarding.sh | 9 +
12 files changed, 1668 insertions(+), 15 deletions(-)
create mode 100755 tools/testing/selftests/net/hsr/hsr_gro_superpacket.py
create mode 100755 tools/testing/selftests/net/hsr/hsr_gro_superpacket.sh
create mode 100755 tools/testing/selftests/net/hsr/hsr_ordered_forwarding.sh
base-commit: fafbc4051123d5459ea6950899cec08ed946e278
--
2.53.0