xref: /linux-6.15/include/linux/skb_array.h (revision 81fbfe8a)
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 {
72ad69f35dSMichael S. Tsirkin 	return !__ptr_ring_peek(&a->ring);
73ad69f35dSMichael S. Tsirkin }
74ad69f35dSMichael S. Tsirkin 
75ad69f35dSMichael S. Tsirkin static inline bool skb_array_empty(struct skb_array *a)
76ad69f35dSMichael S. Tsirkin {
77ad69f35dSMichael S. Tsirkin 	return ptr_ring_empty(&a->ring);
78ad69f35dSMichael S. Tsirkin }
79ad69f35dSMichael S. Tsirkin 
807d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_bh(struct skb_array *a)
817d7072e3SMichael S. Tsirkin {
827d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_bh(&a->ring);
837d7072e3SMichael S. Tsirkin }
847d7072e3SMichael S. Tsirkin 
857d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_irq(struct skb_array *a)
867d7072e3SMichael S. Tsirkin {
877d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_irq(&a->ring);
887d7072e3SMichael S. Tsirkin }
897d7072e3SMichael S. Tsirkin 
907d7072e3SMichael S. Tsirkin static inline bool skb_array_empty_any(struct skb_array *a)
917d7072e3SMichael S. Tsirkin {
927d7072e3SMichael S. Tsirkin 	return ptr_ring_empty_any(&a->ring);
937d7072e3SMichael S. Tsirkin }
947d7072e3SMichael S. Tsirkin 
95ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a)
96ad69f35dSMichael S. Tsirkin {
97ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume(&a->ring);
98ad69f35dSMichael S. Tsirkin }
99ad69f35dSMichael S. Tsirkin 
1003528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a,
1013528c1a5SJason Wang 					    struct sk_buff **array, int n)
1023528c1a5SJason Wang {
1033528c1a5SJason Wang 	return ptr_ring_consume_batched(&a->ring, (void **)array, n);
1043528c1a5SJason Wang }
1053528c1a5SJason Wang 
106ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a)
107ad69f35dSMichael S. Tsirkin {
108ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_irq(&a->ring);
109ad69f35dSMichael S. Tsirkin }
110ad69f35dSMichael S. Tsirkin 
1113528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a,
1123528c1a5SJason Wang 						struct sk_buff **array, int n)
1133528c1a5SJason Wang {
1143528c1a5SJason Wang 	return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n);
1153528c1a5SJason Wang }
1163528c1a5SJason Wang 
117ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a)
118ad69f35dSMichael S. Tsirkin {
119ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_any(&a->ring);
120ad69f35dSMichael S. Tsirkin }
121ad69f35dSMichael S. Tsirkin 
1223528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a,
1233528c1a5SJason Wang 						struct sk_buff **array, int n)
1243528c1a5SJason Wang {
1253528c1a5SJason Wang 	return ptr_ring_consume_batched_any(&a->ring, (void **)array, n);
1263528c1a5SJason Wang }
1273528c1a5SJason Wang 
1283528c1a5SJason Wang 
129ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a)
130ad69f35dSMichael S. Tsirkin {
131ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_bh(&a->ring);
132ad69f35dSMichael S. Tsirkin }
133ad69f35dSMichael S. Tsirkin 
1343528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a,
1353528c1a5SJason Wang 					       struct sk_buff **array, int n)
1363528c1a5SJason Wang {
1373528c1a5SJason Wang 	return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n);
1383528c1a5SJason Wang }
1393528c1a5SJason Wang 
140ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb)
141ad69f35dSMichael S. Tsirkin {
142ad69f35dSMichael S. Tsirkin 	if (likely(skb)) {
143ad69f35dSMichael S. Tsirkin 		int len = skb->len;
144ad69f35dSMichael S. Tsirkin 
145ad69f35dSMichael S. Tsirkin 		if (skb_vlan_tag_present(skb))
146ad69f35dSMichael S. Tsirkin 			len += VLAN_HLEN;
147ad69f35dSMichael S. Tsirkin 
148ad69f35dSMichael S. Tsirkin 		return len;
149ad69f35dSMichael S. Tsirkin 	} else {
150ad69f35dSMichael S. Tsirkin 		return 0;
151ad69f35dSMichael S. Tsirkin 	}
152ad69f35dSMichael S. Tsirkin }
153ad69f35dSMichael S. Tsirkin 
154ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a)
155ad69f35dSMichael S. Tsirkin {
156ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag);
157ad69f35dSMichael S. Tsirkin }
158ad69f35dSMichael S. Tsirkin 
159ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a)
160ad69f35dSMichael S. Tsirkin {
161ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag);
162ad69f35dSMichael S. Tsirkin }
163ad69f35dSMichael S. Tsirkin 
164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a)
165ad69f35dSMichael S. Tsirkin {
166ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag);
167ad69f35dSMichael S. Tsirkin }
168ad69f35dSMichael S. Tsirkin 
169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a)
170ad69f35dSMichael S. Tsirkin {
171ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag);
172ad69f35dSMichael S. Tsirkin }
173ad69f35dSMichael S. Tsirkin 
174ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp)
175ad69f35dSMichael S. Tsirkin {
176ad69f35dSMichael S. Tsirkin 	return ptr_ring_init(&a->ring, size, gfp);
177ad69f35dSMichael S. Tsirkin }
178ad69f35dSMichael S. Tsirkin 
179fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr)
1807d7072e3SMichael S. Tsirkin {
1817d7072e3SMichael S. Tsirkin 	kfree_skb(ptr);
1827d7072e3SMichael S. Tsirkin }
1837d7072e3SMichael S. Tsirkin 
1843acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a,
1853acb6960SJason Wang 				       struct sk_buff **skbs, int n)
1863acb6960SJason Wang {
1873acb6960SJason Wang 	ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb);
1883acb6960SJason Wang }
1893acb6960SJason Wang 
190fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
1917d7072e3SMichael S. Tsirkin {
1927d7072e3SMichael S. Tsirkin 	return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb);
1937d7072e3SMichael S. Tsirkin }
1947d7072e3SMichael S. Tsirkin 
195bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings,
196*81fbfe8aSEric Dumazet 					    int nrings, unsigned int size,
197*81fbfe8aSEric Dumazet 					    gfp_t gfp)
198bf900b3dSJason Wang {
199bf900b3dSJason Wang 	BUILD_BUG_ON(offsetof(struct skb_array, ring));
200bf900b3dSJason Wang 	return ptr_ring_resize_multiple((struct ptr_ring **)rings,
201bf900b3dSJason Wang 					nrings, size, gfp,
202bf900b3dSJason Wang 					__skb_array_destroy_skb);
203bf900b3dSJason Wang }
204bf900b3dSJason Wang 
205ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a)
206ad69f35dSMichael S. Tsirkin {
2077d7072e3SMichael S. Tsirkin 	ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb);
208ad69f35dSMichael S. Tsirkin }
209ad69f35dSMichael S. Tsirkin 
210ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H  */
211