Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at ee9dce44362b2d8132c32964656ab6dff7dfbc6a 143 lines 4.1 kB view raw
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ 2/* 3 * linux/can/skb.h 4 * 5 * Definitions for the CAN network socket buffer 6 * 7 * Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net> 8 * 9 */ 10 11#ifndef _CAN_SKB_H 12#define _CAN_SKB_H 13 14#include <linux/types.h> 15#include <linux/skbuff.h> 16#include <linux/can.h> 17#include <net/can.h> 18#include <net/sock.h> 19 20void can_flush_echo_skb(struct net_device *dev); 21int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, 22 unsigned int idx, unsigned int frame_len); 23struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, 24 unsigned int *len_ptr, 25 unsigned int *frame_len_ptr); 26unsigned int __must_check can_get_echo_skb(struct net_device *dev, 27 unsigned int idx, 28 unsigned int *frame_len_ptr); 29void can_free_echo_skb(struct net_device *dev, unsigned int idx, 30 unsigned int *frame_len_ptr); 31struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); 32struct sk_buff *alloc_canfd_skb(struct net_device *dev, 33 struct canfd_frame **cfd); 34struct sk_buff *alloc_canxl_skb(struct net_device *dev, 35 struct canxl_frame **cxl, 36 unsigned int data_len); 37struct sk_buff *alloc_can_err_skb(struct net_device *dev, 38 struct can_frame **cf); 39bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb); 40 41static inline struct can_skb_ext *can_skb_ext_add(struct sk_buff *skb) 42{ 43 struct can_skb_ext *csx = skb_ext_add(skb, SKB_EXT_CAN); 44 45 /* skb_ext_add() returns uninitialized space */ 46 if (csx) 47 csx->can_gw_hops = 0; 48 49 return csx; 50} 51 52static inline struct can_skb_ext *can_skb_ext_find(struct sk_buff *skb) 53{ 54 return skb_ext_find(skb, SKB_EXT_CAN); 55} 56 57static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) 58{ 59 /* If the socket has already been closed by user space, the 60 * refcount may already be 0 (and the socket will be freed 61 * after the last TX skb has been freed). So only increase 62 * socket refcount if the refcount is > 0. 63 */ 64 if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { 65 skb->destructor = sock_efree; 66 skb->sk = sk; 67 } 68} 69 70/* 71 * returns an unshared skb owned by the original sock to be echo'ed back 72 */ 73static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) 74{ 75 struct sk_buff *nskb; 76 77 nskb = skb_clone(skb, GFP_ATOMIC); 78 if (unlikely(!nskb)) { 79 kfree_skb(skb); 80 return NULL; 81 } 82 83 can_skb_set_owner(nskb, skb->sk); 84 consume_skb(skb); 85 return nskb; 86} 87 88static inline bool can_is_can_skb(const struct sk_buff *skb) 89{ 90 struct can_frame *cf = (struct can_frame *)skb->data; 91 92 /* the CAN specific type of skb is identified by its data length */ 93 return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN); 94} 95 96static inline bool can_is_canfd_skb(const struct sk_buff *skb) 97{ 98 struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 99 100 /* the CAN specific type of skb is identified by its data length */ 101 return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN); 102} 103 104static inline bool can_is_canxl_skb(const struct sk_buff *skb) 105{ 106 const struct canxl_frame *cxl = (struct canxl_frame *)skb->data; 107 108 if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU) 109 return false; 110 111 /* this also checks valid CAN XL data length boundaries */ 112 if (skb->len != CANXL_HDR_SIZE + cxl->len) 113 return false; 114 115 return cxl->flags & CANXL_XLF; 116} 117 118/* get length element value from can[|fd|xl]_frame structure */ 119static inline unsigned int can_skb_get_len_val(struct sk_buff *skb) 120{ 121 const struct canxl_frame *cxl = (struct canxl_frame *)skb->data; 122 const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 123 124 if (can_is_canxl_skb(skb)) 125 return cxl->len; 126 127 return cfd->len; 128} 129 130/* get needed data length inside CAN frame for all frame types (RTR aware) */ 131static inline unsigned int can_skb_get_data_len(struct sk_buff *skb) 132{ 133 unsigned int len = can_skb_get_len_val(skb); 134 const struct can_frame *cf = (struct can_frame *)skb->data; 135 136 /* RTR frames have an actual length of zero */ 137 if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG) 138 return 0; 139 140 return len; 141} 142 143#endif /* !_CAN_SKB_H */