• O
    can: replace timestamp as unique skb attribute · d3b58c47
    Oliver Hartkopp 提交于
    Commit 514ac99c "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 commit 36c01245 "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: NOliver Hartkopp <socketcan@hartkopp.net>
    Cc: linux-stable <stable@vger.kernel.org>
    Signed-off-by: NMarc Kleine-Budde <mkl@pengutronix.de>
    d3b58c47
skb.h 1.9 KB
/*
 * 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 */
反馈
建议
客服 返回
顶部