linux/net
Felix Maurer 415e636751 hsr: Implement more robust duplicate discard for PRP
The PRP duplicate discard algorithm does not work reliably with certain
link faults. Especially with packet loss on one link, the duplicate discard
algorithm drops valid packets which leads to packet loss on the PRP
interface where the link fault should in theory be perfectly recoverable by
PRP. This happens because the algorithm opens the drop window on the lossy
link, covering received and lost sequence numbers. If the other, non-lossy
link receives the duplicate for a lost frame, it is within the drop window
of the lossy link and therefore dropped.

Since IEC 62439-3:2012, a node has one sequence number counter for frames
it sends, instead of one sequence number counter for each destination.
Therefore, a node can not expect to receive contiguous sequence numbers
from a sender. A missing sequence number can be totally normal (if the
sender intermittently communicates with another node) or mean a frame was
lost.

The algorithm, as previously implemented in commit 05fd00e5e7 ("net: hsr:
Fix PRP duplicate detection"), was part of IEC 62439-3:2010 (HSRv0/PRPv0)
but was removed with IEC 62439-3:2012 (HSRv1/PRPv1). Since that, no
algorithm is specified but up to implementers. It should be "designed such
that it never rejects a legitimate frame, while occasional acceptance of a
duplicate can be tolerated" (IEC 62439-3:2021).

For the duplicate discard algorithm, this means that 1) we need to track
the sequence numbers individually to account for non-contiguous sequence
numbers, and 2) we should always err on the side of accepting a duplicate
than dropping a valid frame.

The idea of the new algorithm is to store the seen sequence numbers in a
bitmap. To keep the size of the bitmap in control, we store it as a "sparse
bitmap" where the bitmap is split into blocks and not all blocks exist at
the same time. The sparse bitmap is implemented using an xarray that keeps
the references to the individual blocks and a backing ring buffer that
stores the actual blocks. New blocks are initialized in the buffer and
added to the xarray as needed when new frames arrive. Existing blocks are
removed in two conditions:
1. The block found for an arriving sequence number is old and therefore not
   relevant to the duplicate discard algorithm anymore, i.e., it has been
   added more than the entry forget time ago. In this case, the block is
   removed from the xarray and marked as forgotten (by setting its
   timestamp to 0).
2. Space is needed in the ring buffer for a new block. In this case, the
   block is removed from the xarray, if it hasn't already been forgotten
   (by 1.). Afterwards, the new block is initialized in its place.

This has the nice property that we can reliably track sequence numbers on
low traffic situations (where they expire based on their timestamp) and
more quickly forget sequence numbers in high traffic situations before they
potentially wrap over and repeat before they are expired.

When nodes are merged, the blocks are merged as well. The timestamp of a
merged block is set to the minimum of the two timestamps to never keep
around a seen sequence number for too long. The bitmaps are or'd to mark
all seen sequence numbers as seen.

All of this still happens under seq_out_lock, to prevent concurrent
access to the blocks.

The KUnit test for the algorithm is updated as well. The updates are done
in a way to match the original intends pretty closely. Currently, there is
much knowledge about the actual algorithm baked into the tests (especially
the expectations) which may need some redesign in the future.

Reported-by: Steffen Lindner <steffen.lindner@de.abb.com>
Signed-off-by: Felix Maurer <fmaurer@redhat.com>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Tested-by: Steffen Lindner <steffen.lindner@de.abb.com>
Link: https://patch.msgid.link/8ce15a996099df2df5b700969a39e7df400e8dbb.1770299429.git.fmaurer@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-02-10 12:02:28 +01:00
..
6lowpan net: replace ND_PRINTK with dynamic debug 2025-07-10 15:27:32 -07:00
9p - fix a bug with O_APPEND in cached mode causing data to be written multiple times on server 2025-12-07 08:29:09 -08:00
802 net: remove HIPPI support and RoadRunner HIPPI driver 2026-01-20 19:12:06 -08:00
8021q net: vlan: sync VLAN features with lower device 2025-10-31 17:42:35 -07:00
appletalk net: Convert proto_ops connect() callbacks to use sockaddr_unsized 2025-11-04 19:10:32 -08:00
atm Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-11-27 12:19:08 -08:00
ax25 net: ax25: remove plumbing for never-implemented DAMA Master support 2026-01-30 19:19:39 -08:00
batman-adv Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-10-31 06:46:03 -07:00
bluetooth Bluetooth: L2CAP: Fix not tracking outstanding TX ident 2026-01-29 13:36:35 -05:00
bpf bpf: Fix reference count leak in bpf_prog_test_run_xdp() 2026-01-12 16:37:40 -08:00
bridge net/ipv6: Introduce payload_len helpers 2026-02-06 20:50:03 -08:00
caif caif: fix integer underflow in cffrml_receive() 2025-12-11 01:35:41 -08:00
can can: gw: use can_gw_hops instead of sk_buff::csum_start 2026-02-05 11:58:40 +01:00
ceph libceph: make calc_target() set t->paused, not just clear it 2026-01-06 00:39:43 +01:00
core net/ipv6: Remove jumbo_remove step from TX path 2026-02-06 20:50:12 -08:00
dcb Revert "Documentation: net: add flow control guide and document ethtool API" 2025-10-01 09:48:21 +02:00
devlink devlink: Refactor devlink_rate_nodes_check 2026-02-02 20:05:51 -08:00
dns_resolver net/dns_resolver: use credential guards in dns_query() 2025-11-04 12:36:51 +01:00
dsa net: dsa: tag_yt921x: add priority support 2026-02-03 15:09:31 +01:00
ethernet net: optimize eth_type_trans() vs CONFIG_STACKPROTECTOR_STRONG=y 2025-11-24 19:27:31 -08:00
ethtool Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-02-05 09:54:08 -08:00
handshake net/handshake: Fix null-ptr-deref in handshake_complete() 2025-12-22 12:36:40 +01:00
hsr hsr: Implement more robust duplicate discard for PRP 2026-02-10 12:02:28 +01:00
ieee802154 net: Convert proto callbacks from sockaddr to sockaddr_unsized 2025-11-04 19:10:33 -08:00
ife
ipv4 tcp: inline tcp_filter() 2026-02-06 20:12:11 -08:00
ipv6 net/ipv6: Remove jumbo_remove step from TX path 2026-02-06 20:50:12 -08:00
iucv net/iucv: clean up iucv kernel-doc warnings 2026-02-04 20:39:58 -08:00
kcm Networking changes for 6.19. 2025-12-03 17:24:33 -08:00
key pfkey: Deprecate pfkey 2025-10-30 09:03:12 +01:00
l2tp l2tp: avoid one data-race in l2tp_tunnel_del_work() 2026-01-19 09:55:41 -08:00
l3mdev
lapb treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
llc net: Convert proto_ops connect() callbacks to use sockaddr_unsized 2025-11-04 19:10:32 -08:00
mac80211 wifi: mac80211: Add eMLSR/eMLMR action frame parsing support 2026-02-02 10:11:18 +01:00
mac802154
mctp net: mctp: test: move TX packetqueue from dst to dev 2025-12-01 13:52:13 -08:00
mpls mpls: Drop RTNL for RTM_NEWROUTE, RTM_DELROUTE, and RTM_GETROUTE. 2025-11-03 17:40:54 -08:00
mptcp mptcp: Change some dubious min_t(int, ...) to min() 2026-02-04 18:45:09 -08:00
ncsi net: ncsi: Fix buffer overflow in fetching version id 2025-06-12 18:21:59 -07:00
netfilter net/ipv6: Introduce payload_len helpers 2026-02-06 20:50:03 -08:00
netlabel audit: add record for multiple task security contexts 2025-08-30 10:15:30 -04:00
netlink net: Convert proto_ops connect() callbacks to use sockaddr_unsized 2025-11-04 19:10:32 -08:00
netrom netrom: fix double-free in nr_route_frame() 2026-01-20 19:15:40 -08:00
nfc nfc: nci: Fix race between rfkill and nci_unregister_device(). 2026-01-28 19:32:26 -08:00
nsh
openvswitch net: openvswitch: fix data race in ovs_vport_get_upcall_stats 2026-01-22 12:55:22 +01:00
packet net: add vlan_get_protocol_offset_inline() helper 2026-02-05 16:33:52 +01:00
phonet net: Convert proto callbacks from sockaddr to sockaddr_unsized 2025-11-04 19:10:33 -08:00
psample
psp tools: ynl-gen: add regeneration comment 2025-11-25 19:20:42 -08:00
qrtr net: Convert proto_ops connect() callbacks to use sockaddr_unsized 2025-11-04 19:10:32 -08:00
rds net/rds: Trigger rds_send_ping() more than once 2026-02-04 20:46:39 -08:00
rfkill net: replace use of system_wq with system_percpu_wq 2025-09-22 17:40:30 -07:00
rose net: rose: fix invalid array index in rose_kill_by_device() 2025-12-30 11:45:51 +01:00
rxrpc rxrpc: Fix data-race warning and potential load/store tearing 2026-01-21 19:59:29 -08:00
sched net/ipv6: Introduce payload_len helpers 2026-02-06 20:50:03 -08:00
sctp sctp: move SCTP_CMD_ASSOC_SHKEY right after SCTP_CMD_PEER_INIT 2026-01-17 15:10:34 -08:00
shaper tools: ynl-gen: add regeneration comment 2025-11-25 19:20:42 -08:00
smc Revert "net/smc: Introduce TCP ULP support" 2026-01-30 19:21:51 -08:00
strparser Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-11-13 12:35:38 -08:00
sunrpc nfsd-6.19 fixes: 2025-12-24 09:23:04 -08:00
switchdev
tipc tipc: use kfree_sensitive() for session key material 2026-02-02 17:46:51 -08:00
tls Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2025-10-31 06:46:03 -07:00
unix net: do not write to msg_get_inq in callee 2026-01-08 08:45:13 -08:00
vmw_vsock vmw_vsock: bypass false-positive Wnonnull warning with gcc-16 2026-02-04 18:40:31 -08:00
wireless wifi: cfg80211: add initial UHR support 2026-02-02 10:11:07 +01:00
x25 net: Convert proto_ops connect() callbacks to use sockaddr_unsized 2025-11-04 19:10:32 -08:00
xdp Revert "Merge branch 'netkit-support-for-io_uring-zero-copy-and-af_xdp'" 2026-01-20 18:06:01 -08:00
xfrm xfrm: set ipv4 no_pmtu_disc flag only on output sa when direction is set 2025-12-15 11:06:25 +01:00
compat.c socket: Unify getsockname and getpeername implementation 2025-11-26 13:45:23 -07:00
devres.c
Kconfig net: Kconfig: discourage drop_monitor enablement 2025-10-17 16:29:26 -07:00
Kconfig.debug
Makefile psp: base PSP device support 2025-09-18 12:32:06 +02:00
socket.c vfs-6.19-rc1.fixes 2025-12-05 15:52:30 -08:00
sysctl_net.c