]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include "test.h" | |
35 | #include "stdio.h" | |
36 | ||
37 | #include <unistd.h> | |
38 | #include <string.h> | |
39 | ||
40 | #include <rte_cycles.h> | |
41 | #include <rte_errno.h> | |
42 | #include <rte_mbuf.h> | |
43 | #include <rte_reorder.h> | |
44 | #include <rte_lcore.h> | |
45 | #include <rte_malloc.h> | |
46 | ||
47 | #include "test.h" | |
48 | ||
49 | #define BURST 32 | |
50 | #define REORDER_BUFFER_SIZE 16384 | |
51 | #define NUM_MBUFS (2*REORDER_BUFFER_SIZE) | |
52 | #define REORDER_BUFFER_SIZE_INVALID 2049 | |
53 | ||
54 | struct reorder_unittest_params { | |
55 | struct rte_mempool *p; | |
56 | struct rte_reorder_buffer *b; | |
57 | }; | |
58 | ||
59 | static struct reorder_unittest_params default_params = { | |
60 | .p = NULL, | |
61 | .b = NULL | |
62 | }; | |
63 | ||
64 | static struct reorder_unittest_params *test_params = &default_params; | |
65 | ||
66 | static int | |
67 | test_reorder_create(void) | |
68 | { | |
69 | struct rte_reorder_buffer *b = NULL; | |
70 | ||
71 | b = rte_reorder_create(NULL, rte_socket_id(), REORDER_BUFFER_SIZE); | |
72 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
73 | "No error on create() with NULL name"); | |
74 | ||
75 | b = rte_reorder_create("PKT", rte_socket_id(), REORDER_BUFFER_SIZE_INVALID); | |
76 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
77 | "No error on create() with invalid buffer size param."); | |
78 | ||
79 | b = rte_reorder_create("PKT_RO1", rte_socket_id(), REORDER_BUFFER_SIZE); | |
80 | TEST_ASSERT_EQUAL(b, test_params->b, | |
81 | "New reorder instance created with already existing name"); | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | static int | |
87 | test_reorder_init(void) | |
88 | { | |
89 | struct rte_reorder_buffer *b = NULL; | |
90 | unsigned int size; | |
91 | /* | |
92 | * The minimum memory area size that should be passed to library is, | |
93 | * sizeof(struct rte_reorder_buffer) + (2 * size * sizeof(struct rte_mbuf *)); | |
94 | * Otherwise error will be thrown | |
95 | */ | |
96 | ||
97 | size = 100; | |
98 | b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE); | |
99 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
100 | "No error on init with NULL buffer."); | |
101 | ||
102 | b = rte_malloc(NULL, size, 0); | |
103 | b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE); | |
104 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
105 | "No error on init with invalid mem zone size."); | |
106 | rte_free(b); | |
107 | ||
108 | size = 262336; | |
109 | b = rte_malloc(NULL, size, 0); | |
110 | b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE_INVALID); | |
111 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
112 | "No error on init with invalid buffer size param."); | |
113 | ||
114 | b = rte_reorder_init(b, size, NULL, REORDER_BUFFER_SIZE); | |
115 | TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), | |
116 | "No error on init with invalid name."); | |
117 | rte_free(b); | |
118 | ||
119 | return 0; | |
120 | } | |
121 | ||
122 | static int | |
123 | test_reorder_find_existing(void) | |
124 | { | |
125 | struct rte_reorder_buffer *b = NULL; | |
126 | ||
127 | /* Try to find existing reorder buffer instance */ | |
128 | b = rte_reorder_find_existing("PKT_RO1"); | |
129 | TEST_ASSERT_EQUAL(b, test_params->b, | |
130 | "existing reorder buffer instance not found"); | |
131 | ||
132 | /* Try to find non existing reorder buffer instance */ | |
133 | b = rte_reorder_find_existing("ro_find_non_existing"); | |
134 | TEST_ASSERT((b == NULL) && (rte_errno == ENOENT), | |
135 | "non existing reorder buffer instance found"); | |
136 | ||
137 | return 0; | |
138 | } | |
139 | ||
140 | static int | |
141 | test_reorder_free(void) | |
142 | { | |
143 | struct rte_reorder_buffer *b1 = NULL, *b2 = NULL; | |
144 | const char *name = "test_free"; | |
145 | ||
146 | b1 = rte_reorder_create(name, rte_socket_id(), 8); | |
147 | TEST_ASSERT_NOT_NULL(b1, "Failed to create reorder buffer."); | |
148 | ||
149 | b2 = rte_reorder_find_existing(name); | |
150 | TEST_ASSERT_EQUAL(b1, b2, "Failed to find existing reorder buffer"); | |
151 | ||
152 | rte_reorder_free(b1); | |
153 | ||
154 | b2 = rte_reorder_find_existing(name); | |
155 | TEST_ASSERT((b2 == NULL) && (rte_errno == ENOENT), | |
156 | "Found previously freed reorder buffer"); | |
157 | ||
158 | return 0; | |
159 | } | |
160 | ||
161 | static int | |
162 | test_reorder_insert(void) | |
163 | { | |
164 | struct rte_reorder_buffer *b = NULL; | |
165 | struct rte_mempool *p = test_params->p; | |
166 | const unsigned int size = 4; | |
167 | const unsigned int num_bufs = 7; | |
168 | struct rte_mbuf *bufs[num_bufs]; | |
169 | int ret = 0; | |
170 | unsigned i; | |
171 | ||
172 | /* This would create a reorder buffer instance consisting of: | |
173 | * reorder_seq = 0 | |
174 | * ready_buf: RB[size] = {NULL, NULL, NULL, NULL} | |
175 | * order_buf: OB[size] = {NULL, NULL, NULL, NULL} | |
176 | */ | |
177 | b = rte_reorder_create("test_insert", rte_socket_id(), size); | |
178 | TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer"); | |
179 | ||
180 | ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs); | |
181 | TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool"); | |
182 | ||
183 | for (i = 0; i < num_bufs; i++) | |
184 | bufs[i]->seqn = i; | |
185 | ||
186 | /* This should fill up order buffer: | |
187 | * reorder_seq = 0 | |
188 | * RB[] = {NULL, NULL, NULL, NULL} | |
189 | * OB[] = {0, 1, 2, 3} | |
190 | */ | |
191 | for (i = 0; i < size; i++) { | |
192 | ret = rte_reorder_insert(b, bufs[i]); | |
193 | if (ret != 0) { | |
194 | printf("%s:%d: Error inserting packet with seqn less than size\n", | |
195 | __func__, __LINE__); | |
196 | ret = -1; | |
197 | goto exit; | |
198 | } | |
199 | } | |
200 | ||
201 | /* early packet - should move mbufs to ready buf and move sequence window | |
202 | * reorder_seq = 4 | |
203 | * RB[] = {0, 1, 2, 3} | |
204 | * OB[] = {4, NULL, NULL, NULL} | |
205 | */ | |
206 | ret = rte_reorder_insert(b, bufs[4]); | |
207 | if (ret != 0) { | |
208 | printf("%s:%d: Error inserting early packet with seqn: size\n", | |
209 | __func__, __LINE__); | |
210 | ret = -1; | |
211 | goto exit; | |
212 | } | |
213 | ||
214 | /* early packet from current sequence window - full ready buffer */ | |
215 | bufs[5]->seqn = 2 * size; | |
216 | ret = rte_reorder_insert(b, bufs[5]); | |
217 | if (!((ret == -1) && (rte_errno == ENOSPC))) { | |
218 | printf("%s:%d: No error inserting early packet with full ready buffer\n", | |
219 | __func__, __LINE__); | |
220 | ret = -1; | |
221 | goto exit; | |
222 | } | |
223 | ||
224 | /* late packet */ | |
225 | bufs[6]->seqn = 3 * size; | |
226 | ret = rte_reorder_insert(b, bufs[6]); | |
227 | if (!((ret == -1) && (rte_errno == ERANGE))) { | |
228 | printf("%s:%d: No error inserting late packet with seqn:" | |
229 | " 3 * size\n", __func__, __LINE__); | |
230 | ret = -1; | |
231 | goto exit; | |
232 | } | |
233 | ||
234 | ret = 0; | |
235 | exit: | |
236 | rte_mempool_put_bulk(p, (void *)bufs, num_bufs); | |
237 | rte_reorder_free(b); | |
238 | return ret; | |
239 | } | |
240 | ||
241 | static int | |
242 | test_reorder_drain(void) | |
243 | { | |
244 | struct rte_reorder_buffer *b = NULL; | |
245 | struct rte_mempool *p = test_params->p; | |
246 | const unsigned int size = 4; | |
247 | const unsigned int num_bufs = 8; | |
248 | struct rte_mbuf *bufs[num_bufs]; | |
249 | struct rte_mbuf *robufs[num_bufs]; | |
250 | int ret = 0; | |
251 | unsigned i, cnt; | |
252 | ||
253 | /* This would create a reorder buffer instance consisting of: | |
254 | * reorder_seq = 0 | |
255 | * ready_buf: RB[size] = {NULL, NULL, NULL, NULL} | |
256 | * order_buf: OB[size] = {NULL, NULL, NULL, NULL} | |
257 | */ | |
258 | b = rte_reorder_create("test_drain", rte_socket_id(), size); | |
259 | TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer"); | |
260 | ||
261 | ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs); | |
262 | TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool"); | |
263 | ||
264 | /* Check no drained packets if reorder is empty */ | |
265 | cnt = rte_reorder_drain(b, robufs, 1); | |
266 | if (cnt != 0) { | |
267 | printf("%s:%d: drained packets from empty reorder buffer\n", | |
268 | __func__, __LINE__); | |
269 | ret = -1; | |
270 | goto exit; | |
271 | } | |
272 | ||
273 | for (i = 0; i < num_bufs; i++) | |
274 | bufs[i]->seqn = i; | |
275 | ||
276 | /* Insert packet with seqn 1: | |
277 | * reorder_seq = 0 | |
278 | * RB[] = {NULL, NULL, NULL, NULL} | |
279 | * OB[] = {1, NULL, NULL, NULL} | |
280 | */ | |
281 | rte_reorder_insert(b, bufs[1]); | |
282 | ||
283 | cnt = rte_reorder_drain(b, robufs, 1); | |
284 | if (cnt != 1) { | |
285 | printf("%s:%d:%d: number of expected packets not drained\n", | |
286 | __func__, __LINE__, cnt); | |
287 | ret = -1; | |
288 | goto exit; | |
289 | } | |
290 | ||
291 | /* Insert more packets | |
292 | * RB[] = {NULL, NULL, NULL, NULL} | |
293 | * OB[] = {NULL, 2, 3, NULL} | |
294 | */ | |
295 | rte_reorder_insert(b, bufs[2]); | |
296 | rte_reorder_insert(b, bufs[3]); | |
297 | ||
298 | /* Insert more packets | |
299 | * RB[] = {NULL, NULL, NULL, NULL} | |
300 | * OB[] = {NULL, 2, 3, 4} | |
301 | */ | |
302 | rte_reorder_insert(b, bufs[4]); | |
303 | ||
304 | /* Insert more packets | |
305 | * RB[] = {2, 3, 4, NULL} | |
306 | * OB[] = {NULL, NULL, 7, NULL} | |
307 | */ | |
308 | rte_reorder_insert(b, bufs[7]); | |
309 | ||
310 | /* drained expected packets */ | |
311 | cnt = rte_reorder_drain(b, robufs, 4); | |
312 | if (cnt != 3) { | |
313 | printf("%s:%d:%d: number of expected packets not drained\n", | |
314 | __func__, __LINE__, cnt); | |
315 | ret = -1; | |
316 | goto exit; | |
317 | } | |
318 | ||
319 | /* | |
320 | * RB[] = {NULL, NULL, NULL, NULL} | |
321 | * OB[] = {NULL, NULL, 7, NULL} | |
322 | */ | |
323 | cnt = rte_reorder_drain(b, robufs, 1); | |
324 | if (cnt != 0) { | |
325 | printf("%s:%d:%d: number of expected packets not drained\n", | |
326 | __func__, __LINE__, cnt); | |
327 | ret = -1; | |
328 | goto exit; | |
329 | } | |
330 | ret = 0; | |
331 | exit: | |
332 | rte_mempool_put_bulk(p, (void *)bufs, num_bufs); | |
333 | rte_reorder_free(b); | |
334 | return ret; | |
335 | } | |
336 | ||
337 | static int | |
338 | test_setup(void) | |
339 | { | |
340 | /* reorder buffer instance creation */ | |
341 | if (test_params->b == NULL) { | |
342 | test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(), | |
343 | REORDER_BUFFER_SIZE); | |
344 | if (test_params->b == NULL) { | |
345 | printf("%s: Error creating reorder buffer instance b\n", | |
346 | __func__); | |
347 | return -1; | |
348 | } | |
349 | } else | |
350 | rte_reorder_reset(test_params->b); | |
351 | ||
352 | /* mempool creation */ | |
353 | if (test_params->p == NULL) { | |
354 | test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL", | |
355 | NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE, | |
356 | rte_socket_id()); | |
357 | if (test_params->p == NULL) { | |
358 | printf("%s: Error creating mempool\n", __func__); | |
359 | return -1; | |
360 | } | |
361 | } | |
362 | return 0; | |
363 | } | |
364 | ||
365 | static struct unit_test_suite reorder_test_suite = { | |
366 | ||
367 | .setup = test_setup, | |
368 | .suite_name = "Reorder Unit Test Suite", | |
369 | .unit_test_cases = { | |
370 | TEST_CASE(test_reorder_create), | |
371 | TEST_CASE(test_reorder_init), | |
372 | TEST_CASE(test_reorder_find_existing), | |
373 | TEST_CASE(test_reorder_free), | |
374 | TEST_CASE(test_reorder_insert), | |
375 | TEST_CASE(test_reorder_drain), | |
376 | TEST_CASES_END() | |
377 | } | |
378 | }; | |
379 | ||
380 | static int | |
381 | test_reorder(void) | |
382 | { | |
383 | return unit_test_suite_runner(&reorder_test_suite); | |
384 | } | |
385 | ||
386 | REGISTER_TEST_COMMAND(reorder_autotest, test_reorder); |