xref: /linux-6.15/include/linux/skb_array.h (revision f417dc28)
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 {
72*f417dc28SMichael 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 
100ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume(struct skb_array *a)
101ad69f35dSMichael S. Tsirkin {
102ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume(&a->ring);
103ad69f35dSMichael S. Tsirkin }
104ad69f35dSMichael S. Tsirkin 
1053528c1a5SJason Wang static inline int skb_array_consume_batched(struct skb_array *a,
1063528c1a5SJason Wang 					    struct sk_buff **array, int n)
1073528c1a5SJason Wang {
1083528c1a5SJason Wang 	return ptr_ring_consume_batched(&a->ring, (void **)array, n);
1093528c1a5SJason Wang }
1103528c1a5SJason Wang 
111ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_irq(struct skb_array *a)
112ad69f35dSMichael S. Tsirkin {
113ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_irq(&a->ring);
114ad69f35dSMichael S. Tsirkin }
115ad69f35dSMichael S. Tsirkin 
1163528c1a5SJason Wang static inline int skb_array_consume_batched_irq(struct skb_array *a,
1173528c1a5SJason Wang 						struct sk_buff **array, int n)
1183528c1a5SJason Wang {
1193528c1a5SJason Wang 	return ptr_ring_consume_batched_irq(&a->ring, (void **)array, n);
1203528c1a5SJason Wang }
1213528c1a5SJason Wang 
122ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_any(struct skb_array *a)
123ad69f35dSMichael S. Tsirkin {
124ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_any(&a->ring);
125ad69f35dSMichael S. Tsirkin }
126ad69f35dSMichael S. Tsirkin 
1273528c1a5SJason Wang static inline int skb_array_consume_batched_any(struct skb_array *a,
1283528c1a5SJason Wang 						struct sk_buff **array, int n)
1293528c1a5SJason Wang {
1303528c1a5SJason Wang 	return ptr_ring_consume_batched_any(&a->ring, (void **)array, n);
1313528c1a5SJason Wang }
1323528c1a5SJason Wang 
1333528c1a5SJason Wang 
134ad69f35dSMichael S. Tsirkin static inline struct sk_buff *skb_array_consume_bh(struct skb_array *a)
135ad69f35dSMichael S. Tsirkin {
136ad69f35dSMichael S. Tsirkin 	return ptr_ring_consume_bh(&a->ring);
137ad69f35dSMichael S. Tsirkin }
138ad69f35dSMichael S. Tsirkin 
1393528c1a5SJason Wang static inline int skb_array_consume_batched_bh(struct skb_array *a,
1403528c1a5SJason Wang 					       struct sk_buff **array, int n)
1413528c1a5SJason Wang {
1423528c1a5SJason Wang 	return ptr_ring_consume_batched_bh(&a->ring, (void **)array, n);
1433528c1a5SJason Wang }
1443528c1a5SJason Wang 
145ad69f35dSMichael S. Tsirkin static inline int __skb_array_len_with_tag(struct sk_buff *skb)
146ad69f35dSMichael S. Tsirkin {
147ad69f35dSMichael S. Tsirkin 	if (likely(skb)) {
148ad69f35dSMichael S. Tsirkin 		int len = skb->len;
149ad69f35dSMichael S. Tsirkin 
150ad69f35dSMichael S. Tsirkin 		if (skb_vlan_tag_present(skb))
151ad69f35dSMichael S. Tsirkin 			len += VLAN_HLEN;
152ad69f35dSMichael S. Tsirkin 
153ad69f35dSMichael S. Tsirkin 		return len;
154ad69f35dSMichael S. Tsirkin 	} else {
155ad69f35dSMichael S. Tsirkin 		return 0;
156ad69f35dSMichael S. Tsirkin 	}
157ad69f35dSMichael S. Tsirkin }
158ad69f35dSMichael S. Tsirkin 
159ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len(struct skb_array *a)
160ad69f35dSMichael S. Tsirkin {
161ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL(&a->ring, __skb_array_len_with_tag);
162ad69f35dSMichael S. Tsirkin }
163ad69f35dSMichael S. Tsirkin 
164ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_irq(struct skb_array *a)
165ad69f35dSMichael S. Tsirkin {
166ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_IRQ(&a->ring, __skb_array_len_with_tag);
167ad69f35dSMichael S. Tsirkin }
168ad69f35dSMichael S. Tsirkin 
169ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_bh(struct skb_array *a)
170ad69f35dSMichael S. Tsirkin {
171ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_BH(&a->ring, __skb_array_len_with_tag);
172ad69f35dSMichael S. Tsirkin }
173ad69f35dSMichael S. Tsirkin 
174ad69f35dSMichael S. Tsirkin static inline int skb_array_peek_len_any(struct skb_array *a)
175ad69f35dSMichael S. Tsirkin {
176ad69f35dSMichael S. Tsirkin 	return PTR_RING_PEEK_CALL_ANY(&a->ring, __skb_array_len_with_tag);
177ad69f35dSMichael S. Tsirkin }
178ad69f35dSMichael S. Tsirkin 
179ad69f35dSMichael S. Tsirkin static inline int skb_array_init(struct skb_array *a, int size, gfp_t gfp)
180ad69f35dSMichael S. Tsirkin {
181ad69f35dSMichael S. Tsirkin 	return ptr_ring_init(&a->ring, size, gfp);
182ad69f35dSMichael S. Tsirkin }
183ad69f35dSMichael S. Tsirkin 
184fd68adecSJason Wang static void __skb_array_destroy_skb(void *ptr)
1857d7072e3SMichael S. Tsirkin {
1867d7072e3SMichael S. Tsirkin 	kfree_skb(ptr);
1877d7072e3SMichael S. Tsirkin }
1887d7072e3SMichael S. Tsirkin 
1893acb6960SJason Wang static inline void skb_array_unconsume(struct skb_array *a,
1903acb6960SJason Wang 				       struct sk_buff **skbs, int n)
1913acb6960SJason Wang {
1923acb6960SJason Wang 	ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb);
1933acb6960SJason Wang }
1943acb6960SJason Wang 
195fd68adecSJason Wang static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
1967d7072e3SMichael S. Tsirkin {
1977d7072e3SMichael S. Tsirkin 	return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb);
1987d7072e3SMichael S. Tsirkin }
1997d7072e3SMichael S. Tsirkin 
200bf900b3dSJason Wang static inline int skb_array_resize_multiple(struct skb_array **rings,
20181fbfe8aSEric Dumazet 					    int nrings, unsigned int size,
20281fbfe8aSEric Dumazet 					    gfp_t gfp)
203bf900b3dSJason Wang {
204bf900b3dSJason Wang 	BUILD_BUG_ON(offsetof(struct skb_array, ring));
205bf900b3dSJason Wang 	return ptr_ring_resize_multiple((struct ptr_ring **)rings,
206bf900b3dSJason Wang 					nrings, size, gfp,
207bf900b3dSJason Wang 					__skb_array_destroy_skb);
208bf900b3dSJason Wang }
209bf900b3dSJason Wang 
210ad69f35dSMichael S. Tsirkin static inline void skb_array_cleanup(struct skb_array *a)
211ad69f35dSMichael S. Tsirkin {
2127d7072e3SMichael S. Tsirkin 	ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb);
213ad69f35dSMichael S. Tsirkin }
214ad69f35dSMichael S. Tsirkin 
215ad69f35dSMichael S. Tsirkin #endif /* _LINUX_SKB_ARRAY_H  */
216