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