xref: /linux-6.15/include/linux/skb_array.h (revision a126061c)
12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
2ad69f35dSMichael S. Tsirkin /*
3ad69f35dSMichael S. Tsirkin  *	Definitions for the 'struct skb_array' datastructure.
4ad69f35dSMichael S. Tsirkin  *
5ad69f35dSMichael S. Tsirkin  *	Author:
6ad69f35dSMichael S. Tsirkin  *		Michael S. Tsirkin <[email protected]>
7ad69f35dSMichael S. Tsirkin  *
8ad69f35dSMichael S. Tsirkin  *	Copyright (C) 2016 Red Hat, Inc.
9ad69f35dSMichael S. Tsirkin  *
10ad69f35dSMichael S. Tsirkin  *	Limited-size FIFO of skbs. Can be used more or less whenever
11ad69f35dSMichael S. Tsirkin  *	sk_buff_head can be used, except you need to know the queue size in
12ad69f35dSMichael S. Tsirkin  *	advance.
13ad69f35dSMichael S. Tsirkin  *	Implemented as a type-safe wrapper around ptr_ring.
14ad69f35dSMichael S. Tsirkin  */
15ad69f35dSMichael S. Tsirkin 
16ad69f35dSMichael S. Tsirkin #ifndef _LINUX_SKB_ARRAY_H
17ad69f35dSMichael S. Tsirkin #define _LINUX_SKB_ARRAY_H 1
18ad69f35dSMichael S. Tsirkin 
19ad69f35dSMichael S. Tsirkin #ifdef __KERNEL__
20ad69f35dSMichael S. Tsirkin #include <linux/ptr_ring.h>
21ad69f35dSMichael S. Tsirkin #include <linux/skbuff.h>
22ad69f35dSMichael S. Tsirkin #include <linux/if_vlan.h>
23ad69f35dSMichael S. Tsirkin #endif
24ad69f35dSMichael S. Tsirkin 
25ad69f35dSMichael S. Tsirkin struct skb_array {
26ad69f35dSMichael S. Tsirkin 	struct ptr_ring ring;
27ad69f35dSMichael S. Tsirkin };
28ad69f35dSMichael S. Tsirkin 
29ad69f35dSMichael S. Tsirkin /* Might be slightly faster than skb_array_full below, but callers invoking
30ad69f35dSMichael S. Tsirkin  * this in a loop must use a compiler barrier, for example cpu_relax().
31ad69f35dSMichael S. Tsirkin  */
__skb_array_full(struct skb_array * a)32ad69f35dSMichael S. Tsirkin static inline bool __skb_array_full(struct skb_array *a)
33ad69f35dSMichael S. Tsirkin {
34ad69f35dSMichael S. Tsirkin 	return __ptr_ring_full(&a->ring);
35ad69f35dSMichael S. Tsirkin }
36ad69f35dSMichael S. Tsirkin 
skb_array_full(struct skb_array * a)37ad69f35dSMichael S. Tsirkin static inline bool skb_array_full(struct skb_array *a)
38ad69f35dSMichael S. Tsirkin {
39ad69f35dSMichael S. Tsirkin 	return ptr_ring_full(&a->ring);
40ad69f35dSMichael S. Tsirkin }
41ad69f35dSMichael S. Tsirkin 
skb_array_produce(struct skb_array * a,struct sk_buff * skb)42ad69f35dSMichael S. Tsirkin static inline int skb_array_produce(struct skb_array *a, struct sk_buff *skb)
43ad69f35dSMichael S. Tsirkin {
44ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce(&a->ring, skb);
45ad69f35dSMichael S. Tsirkin }
46ad69f35dSMichael S. Tsirkin 
skb_array_produce_irq(struct skb_array * a,struct sk_buff * skb)47ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_irq(struct skb_array *a, struct sk_buff *skb)
48ad69f35dSMichael S. Tsirkin {
49ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_irq(&a->ring, skb);
50ad69f35dSMichael S. Tsirkin }
51ad69f35dSMichael S. Tsirkin 
skb_array_produce_bh(struct skb_array * a,struct sk_buff * skb)52ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_bh(struct skb_array *a, struct sk_buff *skb)
53ad69f35dSMichael S. Tsirkin {
54ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_bh(&a->ring, skb);
55ad69f35dSMichael S. Tsirkin }
56ad69f35dSMichael S. Tsirkin 
skb_array_produce_any(struct skb_array * a,struct sk_buff * skb)57ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_any(struct skb_array *a, struct sk_buff *skb)
58ad69f35dSMichael S. Tsirkin {
59ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_any(&a->ring, skb);
60ad69f35dSMichael S. Tsirkin }
61ad69f35dSMichael S. Tsirkin 
627d7072e3SMichael S. Tsirkin /* Might be slightly faster than skb_array_empty below, but only safe if the
637d7072e3SMichael S. Tsirkin  * array is never resized. Also, callers invoking this in a loop must take care
647d7072e3SMichael S. Tsirkin  * to use a compiler barrier, for example cpu_relax().
65ad69f35dSMichael S. Tsirkin  */
__skb_array_empty(struct skb_array * a)66ad69f35dSMichael S. Tsirkin static inline bool __skb_array_empty(struct skb_array *a)
67ad69f35dSMichael S. Tsirkin {
68f417dc28SMichael S. Tsirkin 	return __ptr_ring_empty(&a->ring);
69ad69f35dSMichael S. Tsirkin }
70ad69f35dSMichael S. Tsirkin 
__skb_array_peek(struct skb_array * a)714a86a4cfSJohn Fastabend static inline struct sk_buff *__skb_array_peek(struct skb_array *a)
724a86a4cfSJohn Fastabend {
734a86a4cfSJohn Fastabend 	return __ptr_ring_peek(&a->ring);
744a86a4cfSJohn Fastabend }
754a86a4cfSJohn Fastabend 
skb_array_empty(struct skb_array * a)76ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a)
77ad69f35dSMichael S. Tsirkin {
78ad69f35dSMichael S. Tsirkin 	return ptr_ring_empty(&a->ring);
79ad69f35dSMichael S. Tsirkin }
80ad69f35dSMichael S. Tsirkin 
skb_array_empty_bh(struct skb_array * a)817d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a)
827d7072e3SMichael S. Tsirkin {
837d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_bh(&a->ring);
847d7072e3SMichael S. Tsirkin }
857d7072e3SMichael S. Tsirkin 
skb_array_empty_irq(struct skb_array * a)867d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a)
877d7072e3SMichael S. Tsirkin {
887d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_irq(&a->ring);
897d7072e3SMichael S. Tsirkin }
907d7072e3SMichael S. Tsirkin 
skb_array_empty_any(struct skb_array * a)917d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a)
927d7072e3SMichael S. Tsirkin {
937d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_any(&a->ring);
947d7072e3SMichael S. Tsirkin }
957d7072e3SMichael S. Tsirkin 
__skb_array_consume(struct skb_array * a)96021a17edSPaolo Abeni static inline struct sk_buff *__skb_array_consume(struct skb_array *a)
97021a17edSPaolo Abeni {
98021a17edSPaolo Abeni 	return __ptr_ring_consume(&a->ring);
99021a17edSPaolo Abeni }
100021a17edSPaolo Abeni 
skb_array_consume(struct skb_array * a)101ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a)
102ad69f35dSMichael S. Tsirkin {
103ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume(&a->ring);
104ad69f35dSMichael S. Tsirkin }
105ad69f35dSMichael S. Tsirkin 
skb_array_consume_batched(struct skb_array * a,struct sk_buff ** array,int n)1063528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a,
1073528c1a5SJason Wang 					    struct sk_buff **array, int n)
1083528c1a5SJason Wang {
1093528c1a5SJason Wang 	return ptr_ring_consume_batched(&a->ring, (void **)array, n);
1103528c1a5SJason Wang }
1113528c1a5SJason Wang 
skb_array_consume_irq(struct skb_array * a)112ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a)
113ad69f35dSMichael S. Tsirkin {
114ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_irq(&a->ring);
115ad69f35dSMichael S. Tsirkin }
116ad69f35dSMichael S. Tsirkin 
skb_array_consume_batched_irq(struct skb_array * a,struct sk_buff ** array,int n)1173528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a,
1183528c1a5SJason Wang 						struct sk_buff **array, int n)
1193528c1a5SJason Wang {
1203528c1a5SJason Wang 	return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n);
1213528c1a5SJason Wang }
1223528c1a5SJason Wang 
skb_array_consume_any(struct skb_array * a)123ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a)
124ad69f35dSMichael S. Tsirkin {
125ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_any(&a->ring);
126ad69f35dSMichael S. Tsirkin }
127ad69f35dSMichael S. Tsirkin 
skb_array_consume_batched_any(struct skb_array * a,struct sk_buff ** array,int n)1283528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a,
1293528c1a5SJason Wang 						struct sk_buff **array, int n)
1303528c1a5SJason Wang {
1313528c1a5SJason Wang 	return ptr_ring_consume_batched_any(&a->ring, (void **)array, n);
1323528c1a5SJason Wang }
1333528c1a5SJason Wang 
1343528c1a5SJason Wang 
skb_array_consume_bh(struct skb_array * a)135ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a)
136ad69f35dSMichael S. Tsirkin {
137ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_bh(&a->ring);
138ad69f35dSMichael S. Tsirkin }
139ad69f35dSMichael S. Tsirkin 
skb_array_consume_batched_bh(struct skb_array * a,struct sk_buff ** array,int n)1403528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a,
1413528c1a5SJason Wang 					       struct sk_buff **array, int n)
1423528c1a5SJason Wang {
1433528c1a5SJason Wang 	return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n);
1443528c1a5SJason Wang }
1453528c1a5SJason Wang 
__skb_array_len_with_tag(struct sk_buff * skb)146ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb)
147ad69f35dSMichael S. Tsirkin {
148ad69f35dSMichael S. Tsirkin 	if (likely(skb)) {
149ad69f35dSMichael S. Tsirkin 		int len = skb->len;
150ad69f35dSMichael S. Tsirkin 
151ad69f35dSMichael S. Tsirkin 		if (skb_vlan_tag_present(skb))
152ad69f35dSMichael S. Tsirkin 			len += VLAN_HLEN;
153ad69f35dSMichael S. Tsirkin 
154ad69f35dSMichael S. Tsirkin 		return len;
155ad69f35dSMichael S. Tsirkin 	} else {
156ad69f35dSMichael S. Tsirkin 		return 0;
157ad69f35dSMichael S. Tsirkin 	}
158ad69f35dSMichael S. Tsirkin }
159ad69f35dSMichael S. Tsirkin 
skb_array_peek_len(struct skb_array * a)160ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a)
161ad69f35dSMichael S. Tsirkin {
162ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag);
163ad69f35dSMichael S. Tsirkin }
164ad69f35dSMichael S. Tsirkin 
skb_array_peek_len_irq(struct skb_array * a)165ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a)
166ad69f35dSMichael S. Tsirkin {
167ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag);
168ad69f35dSMichael S. Tsirkin }
169ad69f35dSMichael S. Tsirkin 
skb_array_peek_len_bh(struct skb_array * a)170ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a)
171ad69f35dSMichael S. Tsirkin {
172ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag);
173ad69f35dSMichael S. Tsirkin }
174ad69f35dSMichael S. Tsirkin 
skb_array_peek_len_any(struct skb_array * a)175ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a)
176ad69f35dSMichael S. Tsirkin {
177ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag);
178ad69f35dSMichael S. Tsirkin }
179ad69f35dSMichael S. Tsirkin 
skb_array_init_noprof(struct skb_array * a,int size,gfp_t gfp)1802c321f3fSSuren Baghdasaryan static inline int skb_array_init_noprof(struct skb_array *a, int size, gfp_t gfp)
181ad69f35dSMichael S. Tsirkin {
1822c321f3fSSuren Baghdasaryan 	return ptr_ring_init_noprof(&a->ring, size, gfp);
183ad69f35dSMichael S. Tsirkin }
1842c321f3fSSuren Baghdasaryan #define skb_array_init(...)	alloc_hooks(skb_array_init_noprof(__VA_ARGS__))
185ad69f35dSMichael S. Tsirkin 
__skb_array_destroy_skb(void * ptr)186fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr)
1877d7072e3SMichael S. Tsirkin {
1887d7072e3SMichael S. Tsirkin 	kfree_skb(ptr);
1897d7072e3SMichael S. Tsirkin }
1907d7072e3SMichael S. Tsirkin 
skb_array_unconsume(struct skb_array * a,struct sk_buff ** skbs,int n)1913acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a,
1923acb6960SJason Wang 				       struct sk_buff **skbs, int n)
1933acb6960SJason Wang {
1943acb6960SJason Wang 	ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb);
1953acb6960SJason Wang }
1963acb6960SJason Wang 
skb_array_resize(struct skb_array * a,int size,gfp_t gfp)197fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
1987d7072e3SMichael S. Tsirkin {
1997d7072e3SMichael S. Tsirkin 	return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb);
2007d7072e3SMichael S. Tsirkin }
2017d7072e3SMichael S. Tsirkin 
skb_array_resize_multiple_bh_noprof(struct skb_array ** rings,int nrings,unsigned int size,gfp_t gfp)202*a126061cSEric Dumazet static inline int skb_array_resize_multiple_bh_noprof(struct skb_array **rings,
203*a126061cSEric Dumazet 						      int nrings,
204*a126061cSEric Dumazet 						      unsigned int size,
20581fbfe8aSEric Dumazet 						      gfp_t gfp)
206bf900b3dSJason Wang {
207bf900b3dSJason Wang 	BUILD_BUG_ON(offsetof(struct skb_array, ring));
208*a126061cSEric Dumazet 	return ptr_ring_resize_multiple_bh_noprof((struct ptr_ring **)rings,
209bf900b3dSJason Wang 					          nrings, size, gfp,
210bf900b3dSJason Wang 					          __skb_array_destroy_skb);
211bf900b3dSJason Wang }
212*a126061cSEric Dumazet #define skb_array_resize_multiple_bh(...)	\
213*a126061cSEric Dumazet 		alloc_hooks(skb_array_resize_multiple_bh_noprof(__VA_ARGS__))
214bf900b3dSJason Wang 
skb_array_cleanup(struct skb_array * a)215ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a)
216ad69f35dSMichael S. Tsirkin {
2177d7072e3SMichael S. Tsirkin 	ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb);
218ad69f35dSMichael S. Tsirkin }
219ad69f35dSMichael S. Tsirkin 
220ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H  */
221