xref: /linux-6.15/include/linux/skb_array.h (revision 021a17ed)
1ad69f35dSMichael S. Tsirkin /*
2ad69f35dSMichael S. Tsirkin  *	Definitions for the 'struct skb_array' datastructure.
3ad69f35dSMichael S. Tsirkin  *
4ad69f35dSMichael S. Tsirkin  *	Author:
5ad69f35dSMichael S. Tsirkin  *		Michael S. Tsirkin <[email protected]>
6ad69f35dSMichael S. Tsirkin  *
7ad69f35dSMichael S. Tsirkin  *	Copyright (C) 2016 Red Hat, Inc.
8ad69f35dSMichael S. Tsirkin  *
9ad69f35dSMichael S. Tsirkin  *	This program is free software; you can redistribute it and/or modify it
10ad69f35dSMichael S. Tsirkin  *	under the terms of the GNU General Public License as published by the
11ad69f35dSMichael S. Tsirkin  *	Free Software Foundation; either version 2 of the License, or (at your
12ad69f35dSMichael S. Tsirkin  *	option) any later version.
13ad69f35dSMichael S. Tsirkin  *
14ad69f35dSMichael S. Tsirkin  *	Limited-size FIFO of skbs. Can be used more or less whenever
15ad69f35dSMichael S. Tsirkin  *	sk_buff_head can be used, except you need to know the queue size in
16ad69f35dSMichael S. Tsirkin  *	advance.
17ad69f35dSMichael S. Tsirkin  *	Implemented as a type-safe wrapper around ptr_ring.
18ad69f35dSMichael S. Tsirkin  */
19ad69f35dSMichael S. Tsirkin 
20ad69f35dSMichael S. Tsirkin #ifndef _LINUX_SKB_ARRAY_H
21ad69f35dSMichael S. Tsirkin #define _LINUX_SKB_ARRAY_H 1
22ad69f35dSMichael S. Tsirkin 
23ad69f35dSMichael S. Tsirkin #ifdef __KERNEL__
24ad69f35dSMichael S. Tsirkin #include <linux/ptr_ring.h>
25ad69f35dSMichael S. Tsirkin #include <linux/skbuff.h>
26ad69f35dSMichael S. Tsirkin #include <linux/if_vlan.h>
27ad69f35dSMichael S. Tsirkin #endif
28ad69f35dSMichael S. Tsirkin 
29ad69f35dSMichael S. Tsirkin struct skb_array {
30ad69f35dSMichael S. Tsirkin 	struct ptr_ring ring;
31ad69f35dSMichael S. Tsirkin };
32ad69f35dSMichael S. Tsirkin 
33ad69f35dSMichael S. Tsirkin /* Might be slightly faster than skb_array_full below, but callers invoking
34ad69f35dSMichael S. Tsirkin  * this in a loop must use a compiler barrier, for example cpu_relax().
35ad69f35dSMichael S. Tsirkin  */
36ad69f35dSMichael S. Tsirkin static inline bool __skb_array_full(struct skb_array *a)
37ad69f35dSMichael S. Tsirkin {
38ad69f35dSMichael S. Tsirkin 	return __ptr_ring_full(&a->ring);
39ad69f35dSMichael S. Tsirkin }
40ad69f35dSMichael S. Tsirkin 
41ad69f35dSMichael S. Tsirkin static inline bool skb_array_full(struct skb_array *a)
42ad69f35dSMichael S. Tsirkin {
43ad69f35dSMichael S. Tsirkin 	return ptr_ring_full(&a->ring);
44ad69f35dSMichael S. Tsirkin }
45ad69f35dSMichael S. Tsirkin 
46ad69f35dSMichael S. Tsirkin static inline int skb_array_produce(struct skb_array *a, struct sk_buff *skb)
47ad69f35dSMichael S. Tsirkin {
48ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce(&a->ring, skb);
49ad69f35dSMichael S. Tsirkin }
50ad69f35dSMichael S. Tsirkin 
51ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_irq(struct skb_array *a, struct sk_buff *skb)
52ad69f35dSMichael S. Tsirkin {
53ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_irq(&a->ring, skb);
54ad69f35dSMichael S. Tsirkin }
55ad69f35dSMichael S. Tsirkin 
56ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_bh(struct skb_array *a, struct sk_buff *skb)
57ad69f35dSMichael S. Tsirkin {
58ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_bh(&a->ring, skb);
59ad69f35dSMichael S. Tsirkin }
60ad69f35dSMichael S. Tsirkin 
61ad69f35dSMichael S. Tsirkin static inline int skb_array_produce_any(struct skb_array *a, struct sk_buff *skb)
62ad69f35dSMichael S. Tsirkin {
63ad69f35dSMichael S. Tsirkin 	return ptr_ring_produce_any(&a->ring, skb);
64ad69f35dSMichael S. Tsirkin }
65ad69f35dSMichael S. Tsirkin 
667d7072e3SMichael S. Tsirkin /* Might be slightly faster than skb_array_empty below, but only safe if the
677d7072e3SMichael S. Tsirkin  * array is never resized. Also, callers invoking this in a loop must take care
687d7072e3SMichael S. Tsirkin  * to use a compiler barrier, for example cpu_relax().
69ad69f35dSMichael S. Tsirkin  */
70ad69f35dSMichael S. Tsirkin static inline bool __skb_array_empty(struct skb_array *a)
71ad69f35dSMichael S. Tsirkin {
72f417dc28SMichael S. Tsirkin 	return __ptr_ring_empty(&a->ring);
73ad69f35dSMichael S. Tsirkin }
74ad69f35dSMichael S. Tsirkin 
754a86a4cfSJohn Fastabend static inline struct sk_buff *__skb_array_peek(struct skb_array *a)
764a86a4cfSJohn Fastabend {
774a86a4cfSJohn Fastabend 	return __ptr_ring_peek(&a->ring);
784a86a4cfSJohn Fastabend }
794a86a4cfSJohn Fastabend 
80ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a)
81ad69f35dSMichael S. Tsirkin {
82ad69f35dSMichael S. Tsirkin 	return ptr_ring_empty(&a->ring);
83ad69f35dSMichael S. Tsirkin }
84ad69f35dSMichael S. Tsirkin 
857d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a)
867d7072e3SMichael S. Tsirkin {
877d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_bh(&a->ring);
887d7072e3SMichael S. Tsirkin }
897d7072e3SMichael S. Tsirkin 
907d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a)
917d7072e3SMichael S. Tsirkin {
927d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_irq(&a->ring);
937d7072e3SMichael S. Tsirkin }
947d7072e3SMichael S. Tsirkin 
957d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a)
967d7072e3SMichael S. Tsirkin {
977d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_any(&a->ring);
987d7072e3SMichael S. Tsirkin }
997d7072e3SMichael S. Tsirkin 
100*021a17edSPaolo Abeni static inline struct sk_buff *__skb_array_consume(struct skb_array *a)
101*021a17edSPaolo Abeni {
102*021a17edSPaolo Abeni 	return __ptr_ring_consume(&a->ring);
103*021a17edSPaolo Abeni }
104*021a17edSPaolo Abeni 
105ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a)
106ad69f35dSMichael S. Tsirkin {
107ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume(&a->ring);
108ad69f35dSMichael S. Tsirkin }
109ad69f35dSMichael S. Tsirkin 
1103528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a,
1113528c1a5SJason Wang 					    struct sk_buff **array, int n)
1123528c1a5SJason Wang {
1133528c1a5SJason Wang 	return ptr_ring_consume_batched(&a->ring, (void **)array, n);
1143528c1a5SJason Wang }
1153528c1a5SJason Wang 
116ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a)
117ad69f35dSMichael S. Tsirkin {
118ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_irq(&a->ring);
119ad69f35dSMichael S. Tsirkin }
120ad69f35dSMichael S. Tsirkin 
1213528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a,
1223528c1a5SJason Wang 						struct sk_buff **array, int n)
1233528c1a5SJason Wang {
1243528c1a5SJason Wang 	return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n);
1253528c1a5SJason Wang }
1263528c1a5SJason Wang 
127ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a)
128ad69f35dSMichael S. Tsirkin {
129ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_any(&a->ring);
130ad69f35dSMichael S. Tsirkin }
131ad69f35dSMichael S. Tsirkin 
1323528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a,
1333528c1a5SJason Wang 						struct sk_buff **array, int n)
1343528c1a5SJason Wang {
1353528c1a5SJason Wang 	return ptr_ring_consume_batched_any(&a->ring, (void **)array, n);
1363528c1a5SJason Wang }
1373528c1a5SJason Wang 
1383528c1a5SJason Wang 
139ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a)
140ad69f35dSMichael S. Tsirkin {
141ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_bh(&a->ring);
142ad69f35dSMichael S. Tsirkin }
143ad69f35dSMichael S. Tsirkin 
1443528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a,
1453528c1a5SJason Wang 					       struct sk_buff **array, int n)
1463528c1a5SJason Wang {
1473528c1a5SJason Wang 	return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n);
1483528c1a5SJason Wang }
1493528c1a5SJason Wang 
150ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb)
151ad69f35dSMichael S. Tsirkin {
152ad69f35dSMichael S. Tsirkin 	if (likely(skb)) {
153ad69f35dSMichael S. Tsirkin 		int len = skb->len;
154ad69f35dSMichael S. Tsirkin 
155ad69f35dSMichael S. Tsirkin 		if (skb_vlan_tag_present(skb))
156ad69f35dSMichael S. Tsirkin 			len += VLAN_HLEN;
157ad69f35dSMichael S. Tsirkin 
158ad69f35dSMichael S. Tsirkin 		return len;
159ad69f35dSMichael S. Tsirkin 	} else {
160ad69f35dSMichael S. Tsirkin 		return 0;
161ad69f35dSMichael S. Tsirkin 	}
162ad69f35dSMichael S. Tsirkin }
163ad69f35dSMichael S. Tsirkin 
164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a)
165ad69f35dSMichael S. Tsirkin {
166ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag);
167ad69f35dSMichael S. Tsirkin }
168ad69f35dSMichael S. Tsirkin 
169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a)
170ad69f35dSMichael S. Tsirkin {
171ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag);
172ad69f35dSMichael S. Tsirkin }
173ad69f35dSMichael S. Tsirkin 
174ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a)
175ad69f35dSMichael S. Tsirkin {
176ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag);
177ad69f35dSMichael S. Tsirkin }
178ad69f35dSMichael S. Tsirkin 
179ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a)
180ad69f35dSMichael S. Tsirkin {
181ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag);
182ad69f35dSMichael S. Tsirkin }
183ad69f35dSMichael S. Tsirkin 
184ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp)
185ad69f35dSMichael S. Tsirkin {
186ad69f35dSMichael S. Tsirkin 	return ptr_ring_init(&a->ring, size, gfp);
187ad69f35dSMichael S. Tsirkin }
188ad69f35dSMichael S. Tsirkin 
189fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr)
1907d7072e3SMichael S. Tsirkin {
1917d7072e3SMichael S. Tsirkin 	kfree_skb(ptr);
1927d7072e3SMichael S. Tsirkin }
1937d7072e3SMichael S. Tsirkin 
1943acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a,
1953acb6960SJason Wang 				       struct sk_buff **skbs, int n)
1963acb6960SJason Wang {
1973acb6960SJason Wang 	ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb);
1983acb6960SJason Wang }
1993acb6960SJason Wang 
200fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
2017d7072e3SMichael S. Tsirkin {
2027d7072e3SMichael S. Tsirkin 	return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb);
2037d7072e3SMichael S. Tsirkin }
2047d7072e3SMichael S. Tsirkin 
205bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings,
20681fbfe8aSEric Dumazet 					    int nrings, unsigned int size,
20781fbfe8aSEric Dumazet 					    gfp_t gfp)
208bf900b3dSJason Wang {
209bf900b3dSJason Wang 	BUILD_BUG_ON(offsetof(struct skb_array, ring));
210bf900b3dSJason Wang 	return ptr_ring_resize_multiple((struct ptr_ring **)rings,
211bf900b3dSJason Wang 					nrings, size, gfp,
212bf900b3dSJason Wang 					__skb_array_destroy_skb);
213bf900b3dSJason Wang }
214bf900b3dSJason Wang 
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