1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Definitions for the 'struct skb_array' datastructure. 4 * 5 * Author: 6 * Michael S. Tsirkin <mst@redhat.com> 7 * 8 * Copyright (C) 2016 Red Hat, Inc. 9 * 10 * Limited-size FIFO of skbs. Can be used more or less whenever 11 * sk_buff_head can be used, except you need to know the queue size in 12 * advance. 13 * Implemented as a type-safe wrapper around ptr_ring. 14 */ 15 16 #ifndef _LINUX_SKB_ARRAY_H 17 #define _LINUX_SKB_ARRAY_H 1 18 19 #ifdef __KERNEL__ 20 #include <linux/ptr_ring.h> 21 #include <linux/skbuff.h> 22 #include <linux/if_vlan.h> 23 #endif 24 25 struct skb_array { 26 struct ptr_ring ring; 27 }; 28 29 /* Might be slightly faster than skb_array_full below, but callers invoking 30 * this in a loop must use a compiler barrier, for example cpu_relax(). 31 */ 32 static inline bool __skb_array_full(struct skb_array *a) 33 { 34 return __ptr_ring_full(&a->ring); 35 } 36 37 static inline bool skb_array_full(struct skb_array *a) 38 { 39 return ptr_ring_full(&a->ring); 40 } 41 42 static inline int skb_array_produce(struct skb_array *a, struct sk_buff *skb) 43 { 44 return ptr_ring_produce(&a->ring, skb); 45 } 46 47 static inline int skb_array_produce_irq(struct skb_array *a, struct sk_buff *skb) 48 { 49 return ptr_ring_produce_irq(&a->ring, skb); 50 } 51 52 static inline int skb_array_produce_bh(struct skb_array *a, struct sk_buff *skb) 53 { 54 return ptr_ring_produce_bh(&a->ring, skb); 55 } 56 57 static inline int skb_array_produce_any(struct skb_array *a, struct sk_buff *skb) 58 { 59 return ptr_ring_produce_any(&a->ring, skb); 60 } 61 62 /* Might be slightly faster than skb_array_empty below, but only safe if the 63 * array is never resized. Also, callers invoking this in a loop must take care 64 * to use a compiler barrier, for example cpu_relax(). 65 */ 66 static inline bool __skb_array_empty(struct skb_array *a) 67 { 68 return __ptr_ring_empty(&a->ring); 69 } 70 71 static inline struct sk_buff *__skb_array_peek(struct skb_array *a) 72 { 73 return __ptr_ring_peek(&a->ring); 74 } 75 76 static inline bool skb_array_empty(struct skb_array *a) 77 { 78 return ptr_ring_empty(&a->ring); 79 } 80 81 static inline bool skb_array_empty_bh(struct skb_array *a) 82 { 83 return ptr_ring_empty_bh(&a->ring); 84 } 85 86 static inline bool skb_array_empty_irq(struct skb_array *a) 87 { 88 return ptr_ring_empty_irq(&a->ring); 89 } 90 91 static inline bool skb_array_empty_any(struct skb_array *a) 92 { 93 return ptr_ring_empty_any(&a->ring); 94 } 95 96 static inline struct sk_buff *__skb_array_consume(struct skb_array *a) 97 { 98 return __ptr_ring_consume(&a->ring); 99 } 100 101 static inline struct sk_buff *skb_array_consume(struct skb_array *a) 102 { 103 return ptr_ring_consume(&a->ring); 104 } 105 106 static inline int skb_array_consume_batched(struct skb_array *a, 107 struct sk_buff **array, int n) 108 { 109 return ptr_ring_consume_batched(&a->ring, (void **)array, n); 110 } 111 112 static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a) 113 { 114 return ptr_ring_consume_irq(&a->ring); 115 } 116 117 static inline int skb_array_consume_batched_irq(struct skb_array *a, 118 struct sk_buff **array, int n) 119 { 120 return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n); 121 } 122 123 static inline struct sk_buff *skb_array_consume_any(struct skb_array *a) 124 { 125 return ptr_ring_consume_any(&a->ring); 126 } 127 128 static inline int skb_array_consume_batched_any(struct skb_array *a, 129 struct sk_buff **array, int n) 130 { 131 return ptr_ring_consume_batched_any(&a->ring, (void **)array, n); 132 } 133 134 135 static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a) 136 { 137 return ptr_ring_consume_bh(&a->ring); 138 } 139 140 static inline int skb_array_consume_batched_bh(struct skb_array *a, 141 struct sk_buff **array, int n) 142 { 143 return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n); 144 } 145 146 static inline int __skb_array_len_with_tag(struct sk_buff *skb) 147 { 148 if (likely(skb)) { 149 int len = skb->len; 150 151 if (skb_vlan_tag_present(skb)) 152 len += VLAN_HLEN; 153 154 return len; 155 } else { 156 return 0; 157 } 158 } 159 160 static inline int skb_array_peek_len(struct skb_array *a) 161 { 162 return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag); 163 } 164 165 static inline int skb_array_peek_len_irq(struct skb_array *a) 166 { 167 return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag); 168 } 169 170 static inline int skb_array_peek_len_bh(struct skb_array *a) 171 { 172 return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag); 173 } 174 175 static inline int skb_array_peek_len_any(struct skb_array *a) 176 { 177 return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag); 178 } 179 180 static inline int skb_array_init_noprof(struct skb_array *a, int size, gfp_t gfp) 181 { 182 return ptr_ring_init_noprof(&a->ring, size, gfp); 183 } 184 #define skb_array_init(...) alloc_hooks(skb_array_init_noprof(__VA_ARGS__)) 185 186 static void __skb_array_destroy_skb(void *ptr) 187 { 188 kfree_skb(ptr); 189 } 190 191 static inline void skb_array_unconsume(struct skb_array *a, 192 struct sk_buff **skbs, int n) 193 { 194 ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); 195 } 196 197 static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) 198 { 199 return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); 200 } 201 202 static inline int skb_array_resize_multiple_noprof(struct skb_array **rings, 203 int nrings, unsigned int size, 204 gfp_t gfp) 205 { 206 BUILD_BUG_ON(offsetof(struct skb_array, ring)); 207 return ptr_ring_resize_multiple_noprof((struct ptr_ring **)rings, 208 nrings, size, gfp, 209 __skb_array_destroy_skb); 210 } 211 #define skb_array_resize_multiple(...) \ 212 alloc_hooks(skb_array_resize_multiple_noprof(__VA_ARGS__)) 213 214 static inline void skb_array_cleanup(struct skb_array *a) 215 { 216 ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); 217 } 218 219 #endif /* _LINUX_SKB_ARRAY_H */ 220
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.