mirror of
https://github.com/torvalds/linux.git
synced 2026-10-25 01:05:03 +02:00
Commitd4fb6514ff("can: use skb hash instead of private variable in headroom") moved the per-skb unique identifier used for raw_rcv() duplicate detection into skb->hash. With RPS enabled, get_rps_cpu() calls skb_get_hash() before the frame reaches the CAN subsystem. Since CAN skbs have no L3/L4 headers, the flow dissector assigns every CAN frame the same non-zero software hash. can_set_skb_uid() only generated a new identifier when skb->hash was 0, so it kept this constant hash. When the SLAB allocator later reused the same skb address, raw_rcv() mistook the next legitimate frame for a duplicate and dropped it. Fix this by storing the CAN UID in the CAN skb extension (struct can_skb_ext::can_skb_uid) instead of skb->hash, decoupling it from any hash the network stack may compute. can_set_skb_uid() keeps its "assign only if unset" behaviour, which preserves UIDs set before transmission (e.g. by isotp to identify echo frames) across the local loopback path. Frames whose extension is shared with another clone (e.g. via tc mirred or netem duplicate) are given a private extension copy before the UID is assigned, so that independently received skb clones from real CAN interfaces (can_skb_uid = 0) don't end up with the same UID. The limitation that tc mirred/netem skb duplicates might be dropped in raw_rcv for looped back isotp echo frame skbs is accepted. There is no valid use-case for tc mirred or netem together with isotp which is not capable to operate on different CAN interfaces simultaneously. For routing and modifying CAN frames together with isotp use can-gw. can-gw and vxcan additionally clear the UID of forwarded/duplicated frames so each newly routed frame gets its own unique identifier. Fixes:d4fb6514ff("can: use skb hash instead of private variable in headroom") Reported-by: Joerg Willmann <joe@clnt.de> Closes: https://lore.kernel.org/linux-can/2859AD3D-C805-41A0-9036-C5E8EE152419@clnt.de/ Cc: stable@vger.kernel.org Tested-by: Oliver Hartkopp <socketcan@hartkopp.net> Tested-by: Joerg Willmann <joe@clnt.de> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Link: https://patch.msgid.link/20261001115724.27192-1-socketcan@hartkopp.net Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
31 lines
746 B
C
31 lines
746 B
C
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
|
/*
|
|
* net/can.h
|
|
*
|
|
* Definitions for the CAN network socket buffer extensions
|
|
*
|
|
* Copyright (C) 2026 Oliver Hartkopp <socketcan@hartkopp.net>
|
|
*
|
|
*/
|
|
|
|
#ifndef _NET_CAN_H
|
|
#define _NET_CAN_H
|
|
|
|
/**
|
|
* struct can_skb_ext - skb extensions for CAN specific content
|
|
* @can_iif: ifindex of the first interface the CAN frame appeared on
|
|
* @can_framelen: cached echo CAN frame length for bql
|
|
* @can_gw_hops: can-gw CAN frame time-to-live counter
|
|
* @can_ext_flags: CAN skb extensions flags
|
|
* @can_skb_uid: CAN skb UID for raw_rcv and isotp echo handling
|
|
*/
|
|
struct can_skb_ext {
|
|
int can_iif;
|
|
u16 can_framelen;
|
|
u8 can_gw_hops;
|
|
u8 can_ext_flags;
|
|
u32 can_skb_uid;
|
|
};
|
|
|
|
#endif /* _NET_CAN_H */
|