Commit | Line | Data |
---|---|---|
2874c5fd | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
ad69f35d MT |
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 | * | |
ad69f35d MT |
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 | ||
7d7072e3 MT |
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(). | |
ad69f35d MT |
65 | */ |
66 | static inline bool __skb_array_empty(struct skb_array *a) | |
67 | { | |
f417dc28 | 68 | return __ptr_ring_empty(&a->ring); |
ad69f35d MT |
69 | } |
70 | ||
4a86a4cf JF |
71 | static inline struct sk_buff *__skb_array_peek(struct skb_array *a) |
72 | { | |
73 | return __ptr_ring_peek(&a->ring); | |
74 | } | |
75 | ||
ad69f35d MT |
76 | static inline bool skb_array_empty(struct skb_array *a) |
77 | { | |
78 | return ptr_ring_empty(&a->ring); | |
79 | } | |
80 | ||
7d7072e3 MT |
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 | ||
021a17ed PA |
96 | static inline struct sk_buff *__skb_array_consume(struct skb_array *a) |
97 | { | |
98 | return __ptr_ring_consume(&a->ring); | |
99 | } | |
100 | ||
ad69f35d MT |
101 | static inline struct sk_buff *skb_array_consume(struct skb_array *a) |
102 | { | |
103 | return ptr_ring_consume(&a->ring); | |
104 | } | |
105 | ||
3528c1a5 JW |
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 | ||
ad69f35d MT |
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 | ||
3528c1a5 JW |
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 | ||
ad69f35d MT |
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 | ||
3528c1a5 JW |
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 | ||
ad69f35d MT |
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 | ||
3528c1a5 JW |
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 | ||
ad69f35d MT |
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(struct skb_array *a, int size, gfp_t gfp) | |
181 | { | |
182 | return ptr_ring_init(&a->ring, size, gfp); | |
183 | } | |
184 | ||
fd68adec | 185 | static void __skb_array_destroy_skb(void *ptr) |
7d7072e3 MT |
186 | { |
187 | kfree_skb(ptr); | |
188 | } | |
189 | ||
3acb6960 JW |
190 | static inline void skb_array_unconsume(struct skb_array *a, |
191 | struct sk_buff **skbs, int n) | |
192 | { | |
193 | ptr_ring_unconsume(&a->ring, (void **)skbs, n, __skb_array_destroy_skb); | |
194 | } | |
195 | ||
fd68adec | 196 | static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) |
7d7072e3 MT |
197 | { |
198 | return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb); | |
199 | } | |
200 | ||
bf900b3d | 201 | static inline int skb_array_resize_multiple(struct skb_array **rings, |
81fbfe8a ED |
202 | int nrings, unsigned int size, |
203 | gfp_t gfp) | |
bf900b3d JW |
204 | { |
205 | BUILD_BUG_ON(offsetof(struct skb_array, ring)); | |
206 | return ptr_ring_resize_multiple((struct ptr_ring **)rings, | |
207 | nrings, size, gfp, | |
208 | __skb_array_destroy_skb); | |
209 | } | |
210 | ||
ad69f35d MT |
211 | static inline void skb_array_cleanup(struct skb_array *a) |
212 | { | |
7d7072e3 | 213 | ptr_ring_cleanup(&a->ring, __skb_array_destroy_skb); |
ad69f35d MT |
214 | } |
215 | ||
216 | #endif /* _LINUX_SKB_ARRAY_H */ |