brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · 1abc25a Raw
160 lines · c
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */2/*3 * linux/can/skb.h4 *5 * Definitions for the CAN network socket buffer6 *7 * Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net>8 *9 */10 11#ifndef _CAN_SKB_H12#define _CAN_SKB_H13 14#include <linux/types.h>15#include <linux/skbuff.h>16#include <linux/can.h>17#include <net/sock.h>18 19void can_flush_echo_skb(struct net_device *dev);20int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,21		     unsigned int idx, unsigned int frame_len);22struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,23				   unsigned int *len_ptr,24				   unsigned int *frame_len_ptr);25unsigned int __must_check can_get_echo_skb(struct net_device *dev,26					   unsigned int idx,27					   unsigned int *frame_len_ptr);28void can_free_echo_skb(struct net_device *dev, unsigned int idx,29		       unsigned int *frame_len_ptr);30struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);31struct sk_buff *alloc_canfd_skb(struct net_device *dev,32				struct canfd_frame **cfd);33struct sk_buff *alloc_canxl_skb(struct net_device *dev,34				struct canxl_frame **cxl,35				unsigned int data_len);36struct sk_buff *alloc_can_err_skb(struct net_device *dev,37				  struct can_frame **cf);38bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);39 40/*41 * The struct can_skb_priv is used to transport additional information along42 * with the stored struct can(fd)_frame that can not be contained in existing43 * struct sk_buff elements.44 * N.B. that this information must not be modified in cloned CAN sk_buffs.45 * To modify the CAN frame content or the struct can_skb_priv content46 * skb_copy() needs to be used instead of skb_clone().47 */48 49/**50 * struct can_skb_priv - private additional data inside CAN sk_buffs51 * @ifindex:	ifindex of the first interface the CAN frame appeared on52 * @skbcnt:	atomic counter to have an unique id together with skb pointer53 * @frame_len:	length of CAN frame in data link layer54 * @cf:		align to the following CAN frame at skb->data55 */56struct can_skb_priv {57	int ifindex;58	int skbcnt;59	unsigned int frame_len;60	struct can_frame cf[];61};62 63static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)64{65	return (struct can_skb_priv *)(skb->head);66}67 68static inline void can_skb_reserve(struct sk_buff *skb)69{70	skb_reserve(skb, sizeof(struct can_skb_priv));71}72 73static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)74{75	/* If the socket has already been closed by user space, the76	 * refcount may already be 0 (and the socket will be freed77	 * after the last TX skb has been freed). So only increase78	 * socket refcount if the refcount is > 0.79	 */80	if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) {81		skb->destructor = sock_efree;82		skb->sk = sk;83	}84}85 86/*87 * returns an unshared skb owned by the original sock to be echo'ed back88 */89static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)90{91	struct sk_buff *nskb;92 93	nskb = skb_clone(skb, GFP_ATOMIC);94	if (unlikely(!nskb)) {95		kfree_skb(skb);96		return NULL;97	}98 99	can_skb_set_owner(nskb, skb->sk);100	consume_skb(skb);101	return nskb;102}103 104static inline bool can_is_can_skb(const struct sk_buff *skb)105{106	struct can_frame *cf = (struct can_frame *)skb->data;107 108	/* the CAN specific type of skb is identified by its data length */109	return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN);110}111 112static inline bool can_is_canfd_skb(const struct sk_buff *skb)113{114	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;115 116	/* the CAN specific type of skb is identified by its data length */117	return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);118}119 120static inline bool can_is_canxl_skb(const struct sk_buff *skb)121{122	const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;123 124	if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU)125		return false;126 127	/* this also checks valid CAN XL data length boundaries */128	if (skb->len != CANXL_HDR_SIZE + cxl->len)129		return false;130 131	return cxl->flags & CANXL_XLF;132}133 134/* get length element value from can[|fd|xl]_frame structure */135static inline unsigned int can_skb_get_len_val(struct sk_buff *skb)136{137	const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;138	const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;139 140	if (can_is_canxl_skb(skb))141		return cxl->len;142 143	return cfd->len;144}145 146/* get needed data length inside CAN frame for all frame types (RTR aware) */147static inline unsigned int can_skb_get_data_len(struct sk_buff *skb)148{149	unsigned int len = can_skb_get_len_val(skb);150	const struct can_frame *cf = (struct can_frame *)skb->data;151 152	/* RTR frames have an actual length of zero */153	if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG)154		return 0;155 156	return len;157}158 159#endif /* !_CAN_SKB_H */160