diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 219 |
1 files changed, 112 insertions, 107 deletions
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index b876c9c81c65..2e8ef42721e2 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c | |||
@@ -36,9 +36,100 @@ | |||
36 | 36 | ||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | |||
40 | #include "packet_history.h" | 39 | #include "packet_history.h" |
41 | 40 | ||
41 | /* | ||
42 | * Transmitter History Routines | ||
43 | */ | ||
44 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | ||
45 | { | ||
46 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
47 | static const char dccp_tx_hist_mask[] = "tx_hist_%s"; | ||
48 | char *slab_name; | ||
49 | |||
50 | if (hist == NULL) | ||
51 | goto out; | ||
52 | |||
53 | slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1, | ||
54 | GFP_ATOMIC); | ||
55 | if (slab_name == NULL) | ||
56 | goto out_free_hist; | ||
57 | |||
58 | sprintf(slab_name, dccp_tx_hist_mask, name); | ||
59 | hist->dccptxh_slab = kmem_cache_create(slab_name, | ||
60 | sizeof(struct dccp_tx_hist_entry), | ||
61 | 0, SLAB_HWCACHE_ALIGN, | ||
62 | NULL, NULL); | ||
63 | if (hist->dccptxh_slab == NULL) | ||
64 | goto out_free_slab_name; | ||
65 | out: | ||
66 | return hist; | ||
67 | out_free_slab_name: | ||
68 | kfree(slab_name); | ||
69 | out_free_hist: | ||
70 | kfree(hist); | ||
71 | hist = NULL; | ||
72 | goto out; | ||
73 | } | ||
74 | |||
75 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
76 | |||
77 | void dccp_tx_hist_delete(struct dccp_tx_hist *hist) | ||
78 | { | ||
79 | const char* name = kmem_cache_name(hist->dccptxh_slab); | ||
80 | |||
81 | kmem_cache_destroy(hist->dccptxh_slab); | ||
82 | kfree(name); | ||
83 | kfree(hist); | ||
84 | } | ||
85 | |||
86 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | ||
87 | |||
88 | struct dccp_tx_hist_entry * | ||
89 | dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) | ||
90 | { | ||
91 | struct dccp_tx_hist_entry *packet = NULL, *entry; | ||
92 | |||
93 | list_for_each_entry(entry, list, dccphtx_node) | ||
94 | if (entry->dccphtx_seqno == seq) { | ||
95 | packet = entry; | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | return packet; | ||
100 | } | ||
101 | |||
102 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | ||
103 | |||
104 | void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | ||
105 | { | ||
106 | struct dccp_tx_hist_entry *entry, *next; | ||
107 | |||
108 | list_for_each_entry_safe(entry, next, list, dccphtx_node) { | ||
109 | list_del_init(&entry->dccphtx_node); | ||
110 | dccp_tx_hist_entry_delete(hist, entry); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | ||
115 | |||
116 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | ||
117 | struct list_head *list, | ||
118 | struct dccp_tx_hist_entry *packet) | ||
119 | { | ||
120 | struct dccp_tx_hist_entry *next; | ||
121 | |||
122 | list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) { | ||
123 | list_del_init(&packet->dccphtx_node); | ||
124 | dccp_tx_hist_entry_delete(hist, packet); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | ||
129 | |||
130 | /* | ||
131 | * Receiver History Routines | ||
132 | */ | ||
42 | struct dccp_rx_hist *dccp_rx_hist_new(const char *name) | 133 | struct dccp_rx_hist *dccp_rx_hist_new(const char *name) |
43 | { | 134 | { |
44 | struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | 135 | struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); |
@@ -83,18 +174,24 @@ void dccp_rx_hist_delete(struct dccp_rx_hist *hist) | |||
83 | 174 | ||
84 | EXPORT_SYMBOL_GPL(dccp_rx_hist_delete); | 175 | EXPORT_SYMBOL_GPL(dccp_rx_hist_delete); |
85 | 176 | ||
86 | void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) | 177 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, |
178 | u8 *ccval) | ||
87 | { | 179 | { |
88 | struct dccp_rx_hist_entry *entry, *next; | 180 | struct dccp_rx_hist_entry *packet = NULL, *entry; |
89 | 181 | ||
90 | list_for_each_entry_safe(entry, next, list, dccphrx_node) { | 182 | list_for_each_entry(entry, list, dccphrx_node) |
91 | list_del_init(&entry->dccphrx_node); | 183 | if (entry->dccphrx_seqno == seq) { |
92 | kmem_cache_free(hist->dccprxh_slab, entry); | 184 | packet = entry; |
93 | } | 185 | break; |
94 | } | 186 | } |
95 | 187 | ||
96 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); | 188 | if (packet) |
189 | *ccval = packet->dccphrx_ccval; | ||
97 | 190 | ||
191 | return packet != NULL; | ||
192 | } | ||
193 | |||
194 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
98 | struct dccp_rx_hist_entry * | 195 | struct dccp_rx_hist_entry * |
99 | dccp_rx_hist_find_data_packet(const struct list_head *list) | 196 | dccp_rx_hist_find_data_packet(const struct list_head *list) |
100 | { | 197 | { |
@@ -184,110 +281,18 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | |||
184 | 281 | ||
185 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); | 282 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); |
186 | 283 | ||
187 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | 284 | void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) |
188 | { | ||
189 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
190 | static const char dccp_tx_hist_mask[] = "tx_hist_%s"; | ||
191 | char *slab_name; | ||
192 | |||
193 | if (hist == NULL) | ||
194 | goto out; | ||
195 | |||
196 | slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1, | ||
197 | GFP_ATOMIC); | ||
198 | if (slab_name == NULL) | ||
199 | goto out_free_hist; | ||
200 | |||
201 | sprintf(slab_name, dccp_tx_hist_mask, name); | ||
202 | hist->dccptxh_slab = kmem_cache_create(slab_name, | ||
203 | sizeof(struct dccp_tx_hist_entry), | ||
204 | 0, SLAB_HWCACHE_ALIGN, | ||
205 | NULL, NULL); | ||
206 | if (hist->dccptxh_slab == NULL) | ||
207 | goto out_free_slab_name; | ||
208 | out: | ||
209 | return hist; | ||
210 | out_free_slab_name: | ||
211 | kfree(slab_name); | ||
212 | out_free_hist: | ||
213 | kfree(hist); | ||
214 | hist = NULL; | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
219 | |||
220 | void dccp_tx_hist_delete(struct dccp_tx_hist *hist) | ||
221 | { | ||
222 | const char* name = kmem_cache_name(hist->dccptxh_slab); | ||
223 | |||
224 | kmem_cache_destroy(hist->dccptxh_slab); | ||
225 | kfree(name); | ||
226 | kfree(hist); | ||
227 | } | ||
228 | |||
229 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | ||
230 | |||
231 | struct dccp_tx_hist_entry * | ||
232 | dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) | ||
233 | { | ||
234 | struct dccp_tx_hist_entry *packet = NULL, *entry; | ||
235 | |||
236 | list_for_each_entry(entry, list, dccphtx_node) | ||
237 | if (entry->dccphtx_seqno == seq) { | ||
238 | packet = entry; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | return packet; | ||
243 | } | ||
244 | |||
245 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | ||
246 | |||
247 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
248 | u8 *ccval) | ||
249 | { | ||
250 | struct dccp_rx_hist_entry *packet = NULL, *entry; | ||
251 | |||
252 | list_for_each_entry(entry, list, dccphrx_node) | ||
253 | if (entry->dccphrx_seqno == seq) { | ||
254 | packet = entry; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (packet) | ||
259 | *ccval = packet->dccphrx_ccval; | ||
260 | |||
261 | return packet != NULL; | ||
262 | } | ||
263 | |||
264 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
265 | |||
266 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | ||
267 | struct list_head *list, | ||
268 | struct dccp_tx_hist_entry *packet) | ||
269 | { | 285 | { |
270 | struct dccp_tx_hist_entry *next; | 286 | struct dccp_rx_hist_entry *entry, *next; |
271 | 287 | ||
272 | list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) { | 288 | list_for_each_entry_safe(entry, next, list, dccphrx_node) { |
273 | list_del_init(&packet->dccphtx_node); | 289 | list_del_init(&entry->dccphrx_node); |
274 | dccp_tx_hist_entry_delete(hist, packet); | 290 | kmem_cache_free(hist->dccprxh_slab, entry); |
275 | } | 291 | } |
276 | } | 292 | } |
277 | 293 | ||
278 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | 294 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); |
279 | |||
280 | void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | ||
281 | { | ||
282 | struct dccp_tx_hist_entry *entry, *next; | ||
283 | |||
284 | list_for_each_entry_safe(entry, next, list, dccphtx_node) { | ||
285 | list_del_init(&entry->dccphtx_node); | ||
286 | dccp_tx_hist_entry_delete(hist, entry); | ||
287 | } | ||
288 | } | ||
289 | 295 | ||
290 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | ||
291 | 296 | ||
292 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " | 297 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
293 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 298 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |