mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 11:49:32 +00:00
![Oliver Hartkopp](/assets/img/avatar_default.png)
Commit514ac99c64
"can: fix multiple delivery of a single CAN frame for overlapping CAN filters" requires the skb->tstamp to be set to check for identical CAN skbs. Without timestamping to be required by user space applications this timestamp was not generated which lead to commit36c01245eb
"can: fix loss of CAN frames in raw_rcv" - which forces the timestamp to be set in all CAN related skbuffs by introducing several __net_timestamp() calls. This forces e.g. out of tree drivers which are not using alloc_can{,fd}_skb() to add __net_timestamp() after skbuff creation to prevent the frame loss fixed in mainline Linux. This patch removes the timestamp dependency and uses an atomic counter to create an unique identifier together with the skbuff pointer. Btw: the new skbcnt element introduced in struct can_skb_priv has to be initialized with zero in out-of-tree drivers which are not using alloc_can{,fd}_skb() too. Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Cc: linux-stable <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
80 lines
1.9 KiB
C
80 lines
1.9 KiB
C
/*
|
|
* linux/can/skb.h
|
|
*
|
|
* Definitions for the CAN network socket buffer
|
|
*
|
|
* Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net>
|
|
*
|
|
*/
|
|
|
|
#ifndef _CAN_SKB_H
|
|
#define _CAN_SKB_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/can.h>
|
|
#include <net/sock.h>
|
|
|
|
/*
|
|
* The struct can_skb_priv is used to transport additional information along
|
|
* with the stored struct can(fd)_frame that can not be contained in existing
|
|
* struct sk_buff elements.
|
|
* N.B. that this information must not be modified in cloned CAN sk_buffs.
|
|
* To modify the CAN frame content or the struct can_skb_priv content
|
|
* skb_copy() needs to be used instead of skb_clone().
|
|
*/
|
|
|
|
/**
|
|
* struct can_skb_priv - private additional data inside CAN sk_buffs
|
|
* @ifindex: ifindex of the first interface the CAN frame appeared on
|
|
* @skbcnt: atomic counter to have an unique id together with skb pointer
|
|
* @cf: align to the following CAN frame at skb->data
|
|
*/
|
|
struct can_skb_priv {
|
|
int ifindex;
|
|
int skbcnt;
|
|
struct can_frame cf[0];
|
|
};
|
|
|
|
static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)
|
|
{
|
|
return (struct can_skb_priv *)(skb->head);
|
|
}
|
|
|
|
static inline void can_skb_reserve(struct sk_buff *skb)
|
|
{
|
|
skb_reserve(skb, sizeof(struct can_skb_priv));
|
|
}
|
|
|
|
static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
|
|
{
|
|
if (sk) {
|
|
sock_hold(sk);
|
|
skb->destructor = sock_efree;
|
|
skb->sk = sk;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* returns an unshared skb owned by the original sock to be echo'ed back
|
|
*/
|
|
static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
|
|
{
|
|
if (skb_shared(skb)) {
|
|
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
if (likely(nskb)) {
|
|
can_skb_set_owner(nskb, skb->sk);
|
|
consume_skb(skb);
|
|
return nskb;
|
|
} else {
|
|
kfree_skb(skb);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* we can assume to have an unshared skb with proper owner */
|
|
return skb;
|
|
}
|
|
|
|
#endif /* !_CAN_SKB_H */
|