07dcce06d293ec9bab8cab6a2e60604dd0542608
[dpdk.git] / app / test / test_reorder.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include "test.h"
6
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <string.h>
10
11 #include <rte_cycles.h>
12 #include <rte_errno.h>
13 #include <rte_mbuf.h>
14
15 #ifdef RTE_EXEC_ENV_WINDOWS
16 static int
17 test_reorder(void)
18 {
19         printf("reorder not supported on Windows, skipping test\n");
20         return TEST_SKIPPED;
21 }
22 #else
23
24 #include <rte_reorder.h>
25 #include <rte_lcore.h>
26 #include <rte_malloc.h>
27
28 #define BURST 32
29 #define REORDER_BUFFER_SIZE 16384
30 #define NUM_MBUFS (2*REORDER_BUFFER_SIZE)
31 #define REORDER_BUFFER_SIZE_INVALID 2049
32
33 struct reorder_unittest_params {
34         struct rte_mempool *p;
35         struct rte_reorder_buffer *b;
36 };
37
38 static struct reorder_unittest_params default_params  = {
39         .p = NULL,
40         .b = NULL
41 };
42
43 static struct reorder_unittest_params *test_params = &default_params;
44
45 static int
46 test_reorder_create(void)
47 {
48         struct rte_reorder_buffer *b = NULL;
49
50         b = rte_reorder_create(NULL, rte_socket_id(), REORDER_BUFFER_SIZE);
51         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
52                         "No error on create() with NULL name");
53
54         b = rte_reorder_create("PKT", rte_socket_id(), REORDER_BUFFER_SIZE_INVALID);
55         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
56                         "No error on create() with invalid buffer size param.");
57
58         b = rte_reorder_create("PKT_RO1", rte_socket_id(), REORDER_BUFFER_SIZE);
59         TEST_ASSERT_EQUAL(b, test_params->b,
60                         "New reorder instance created with already existing name");
61
62         return 0;
63 }
64
65 static int
66 test_reorder_init(void)
67 {
68         struct rte_reorder_buffer *b = NULL;
69         unsigned int size;
70         /*
71          * The minimum memory area size that should be passed to library is,
72          * sizeof(struct rte_reorder_buffer) + (2 * size * sizeof(struct rte_mbuf *));
73          * Otherwise error will be thrown
74          */
75
76         size = 100;
77         b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE);
78         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
79                         "No error on init with NULL buffer.");
80
81         b = rte_malloc(NULL, size, 0);
82         b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE);
83         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
84                         "No error on init with invalid mem zone size.");
85         rte_free(b);
86
87         size = 262336;
88         b = rte_malloc(NULL, size, 0);
89         b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE_INVALID);
90         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
91                         "No error on init with invalid buffer size param.");
92
93         b = rte_reorder_init(b, size, NULL, REORDER_BUFFER_SIZE);
94         TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
95                         "No error on init with invalid name.");
96         rte_free(b);
97
98         return 0;
99 }
100
101 static int
102 test_reorder_find_existing(void)
103 {
104         struct rte_reorder_buffer *b = NULL;
105
106         /* Try to find existing reorder buffer instance */
107         b = rte_reorder_find_existing("PKT_RO1");
108         TEST_ASSERT_EQUAL(b, test_params->b,
109                         "existing reorder buffer instance not found");
110
111         /* Try to find non existing reorder buffer instance */
112         b = rte_reorder_find_existing("ro_find_non_existing");
113         TEST_ASSERT((b == NULL) && (rte_errno == ENOENT),
114                         "non existing reorder buffer instance found");
115
116         return 0;
117 }
118
119 static int
120 test_reorder_free(void)
121 {
122         struct rte_reorder_buffer *b1 = NULL, *b2 = NULL;
123         const char *name = "test_free";
124
125         b1 = rte_reorder_create(name, rte_socket_id(), 8);
126         TEST_ASSERT_NOT_NULL(b1, "Failed to create reorder buffer.");
127
128         b2 = rte_reorder_find_existing(name);
129         TEST_ASSERT_EQUAL(b1, b2, "Failed to find existing reorder buffer");
130
131         rte_reorder_free(b1);
132
133         b2 = rte_reorder_find_existing(name);
134         TEST_ASSERT((b2 == NULL) && (rte_errno == ENOENT),
135                         "Found previously freed reorder buffer");
136
137         return 0;
138 }
139
140 static int
141 test_reorder_insert(void)
142 {
143         struct rte_reorder_buffer *b = NULL;
144         struct rte_mempool *p = test_params->p;
145         const unsigned int size = 4;
146         const unsigned int num_bufs = 7;
147         struct rte_mbuf *bufs[num_bufs];
148         int ret = 0;
149         unsigned i;
150
151         /* This would create a reorder buffer instance consisting of:
152          * reorder_seq = 0
153          * ready_buf: RB[size] = {NULL, NULL, NULL, NULL}
154          * order_buf: OB[size] = {NULL, NULL, NULL, NULL}
155          */
156         b = rte_reorder_create("test_insert", rte_socket_id(), size);
157         TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer");
158
159         for (i = 0; i < num_bufs; i++) {
160                 bufs[i] = rte_pktmbuf_alloc(p);
161                 TEST_ASSERT_NOT_NULL(bufs[i], "Packet allocation failed\n");
162                 *rte_reorder_seqn(bufs[i]) = i;
163         }
164
165         /* This should fill up order buffer:
166          * reorder_seq = 0
167          * RB[] = {NULL, NULL, NULL, NULL}
168          * OB[] = {0, 1, 2, 3}
169          */
170         for (i = 0; i < size; i++) {
171                 ret = rte_reorder_insert(b, bufs[i]);
172                 if (ret != 0) {
173                         printf("%s:%d: Error inserting packet with seqn less than size\n",
174                                         __func__, __LINE__);
175                         ret = -1;
176                         goto exit;
177                 }
178                 bufs[i] = NULL;
179         }
180
181         /* early packet - should move mbufs to ready buf and move sequence window
182          * reorder_seq = 4
183          * RB[] = {0, 1, 2, 3}
184          * OB[] = {4, NULL, NULL, NULL}
185          */
186         ret = rte_reorder_insert(b, bufs[4]);
187         if (ret != 0) {
188                 printf("%s:%d: Error inserting early packet with seqn: size\n",
189                                 __func__, __LINE__);
190                 ret = -1;
191                 goto exit;
192         }
193         bufs[4] = NULL;
194
195         /* early packet from current sequence window - full ready buffer */
196         *rte_reorder_seqn(bufs[5]) = 2 * size;
197         ret = rte_reorder_insert(b, bufs[5]);
198         if (!((ret == -1) && (rte_errno == ENOSPC))) {
199                 printf("%s:%d: No error inserting early packet with full ready buffer\n",
200                                 __func__, __LINE__);
201                 ret = -1;
202                 goto exit;
203         }
204         bufs[5] = NULL;
205
206         /* late packet */
207         *rte_reorder_seqn(bufs[6]) = 3 * size;
208         ret = rte_reorder_insert(b, bufs[6]);
209         if (!((ret == -1) && (rte_errno == ERANGE))) {
210                 printf("%s:%d: No error inserting late packet with seqn:"
211                                 " 3 * size\n", __func__, __LINE__);
212                 ret = -1;
213                 goto exit;
214         }
215         bufs[6] = NULL;
216
217         ret = 0;
218 exit:
219         rte_reorder_free(b);
220         for (i = 0; i < num_bufs; i++) {
221                 if (bufs[i] != NULL)
222                         rte_pktmbuf_free(bufs[i]);
223         }
224         return ret;
225 }
226
227 static int
228 test_reorder_drain(void)
229 {
230         struct rte_reorder_buffer *b = NULL;
231         struct rte_mempool *p = test_params->p;
232         const unsigned int size = 4;
233         const unsigned int num_bufs = 8;
234         struct rte_mbuf *bufs[num_bufs];
235         struct rte_mbuf *robufs[num_bufs];
236         int ret = 0;
237         unsigned i, cnt;
238
239         /* initialize all robufs to NULL */
240         for (i = 0; i < num_bufs; i++)
241                 robufs[i] = NULL;
242
243         /* This would create a reorder buffer instance consisting of:
244          * reorder_seq = 0
245          * ready_buf: RB[size] = {NULL, NULL, NULL, NULL}
246          * order_buf: OB[size] = {NULL, NULL, NULL, NULL}
247          */
248         b = rte_reorder_create("test_drain", rte_socket_id(), size);
249         TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer");
250
251         /* Check no drained packets if reorder is empty */
252         cnt = rte_reorder_drain(b, robufs, 1);
253         if (cnt != 0) {
254                 printf("%s:%d: drained packets from empty reorder buffer\n",
255                                 __func__, __LINE__);
256                 ret = -1;
257                 goto exit;
258         }
259
260         for (i = 0; i < num_bufs; i++) {
261                 bufs[i] = rte_pktmbuf_alloc(p);
262                 TEST_ASSERT_NOT_NULL(bufs[i], "Packet allocation failed\n");
263                 *rte_reorder_seqn(bufs[i]) = i;
264         }
265
266         /* Insert packet with seqn 1:
267          * reorder_seq = 0
268          * RB[] = {NULL, NULL, NULL, NULL}
269          * OB[] = {1, NULL, NULL, NULL}
270          */
271         rte_reorder_insert(b, bufs[1]);
272         bufs[1] = NULL;
273
274         cnt = rte_reorder_drain(b, robufs, 1);
275         if (cnt != 1) {
276                 printf("%s:%d:%d: number of expected packets not drained\n",
277                                 __func__, __LINE__, cnt);
278                 ret = -1;
279                 goto exit;
280         }
281         if (robufs[0] != NULL)
282                 rte_pktmbuf_free(robufs[0]);
283
284         /* Insert more packets
285          * RB[] = {NULL, NULL, NULL, NULL}
286          * OB[] = {NULL, 2, 3, NULL}
287          */
288         rte_reorder_insert(b, bufs[2]);
289         rte_reorder_insert(b, bufs[3]);
290         bufs[2] = NULL;
291         bufs[3] = NULL;
292
293         /* Insert more packets
294          * RB[] = {NULL, NULL, NULL, NULL}
295          * OB[] = {NULL, 2, 3, 4}
296          */
297         rte_reorder_insert(b, bufs[4]);
298         bufs[4] = NULL;
299
300         /* Insert more packets
301          * RB[] = {2, 3, 4, NULL}
302          * OB[] = {NULL, NULL, 7, NULL}
303          */
304         rte_reorder_insert(b, bufs[7]);
305         bufs[7] = NULL;
306
307         /* drained expected packets */
308         cnt = rte_reorder_drain(b, robufs, 4);
309         if (cnt != 3) {
310                 printf("%s:%d:%d: number of expected packets not drained\n",
311                                 __func__, __LINE__, cnt);
312                 ret = -1;
313                 goto exit;
314         }
315         for (i = 0; i < 3; i++) {
316                 if (robufs[i] != NULL)
317                         rte_pktmbuf_free(robufs[i]);
318         }
319
320         /*
321          * RB[] = {NULL, NULL, NULL, NULL}
322          * OB[] = {NULL, NULL, 7, NULL}
323          */
324         cnt = rte_reorder_drain(b, robufs, 1);
325         if (cnt != 0) {
326                 printf("%s:%d:%d: number of expected packets not drained\n",
327                                 __func__, __LINE__, cnt);
328                 ret = -1;
329                 goto exit;
330         }
331         ret = 0;
332 exit:
333         rte_reorder_free(b);
334         for (i = 0; i < num_bufs; i++) {
335                 if (bufs[i] != NULL)
336                         rte_pktmbuf_free(bufs[i]);
337                 if (robufs[i] != NULL)
338                         rte_pktmbuf_free(robufs[i]);
339         }
340         return ret;
341 }
342
343 static int
344 test_setup(void)
345 {
346         /* reorder buffer instance creation */
347         if (test_params->b == NULL) {
348                 test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(),
349                                                         REORDER_BUFFER_SIZE);
350                 if (test_params->b == NULL) {
351                         printf("%s: Error creating reorder buffer instance b\n",
352                                         __func__);
353                         return -1;
354                 }
355         } else
356                 rte_reorder_reset(test_params->b);
357
358         /* mempool creation */
359         if (test_params->p == NULL) {
360                 test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL",
361                         NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
362                         rte_socket_id());
363                 if (test_params->p == NULL) {
364                         printf("%s: Error creating mempool\n", __func__);
365                         return -1;
366                 }
367         }
368         return 0;
369 }
370
371 static void
372 test_teardown(void)
373 {
374         rte_reorder_free(test_params->b);
375         test_params->b = NULL;
376         rte_mempool_free(test_params->p);
377         test_params->p = NULL;
378 }
379
380
381 static struct unit_test_suite reorder_test_suite  = {
382
383         .setup = test_setup,
384         .teardown = test_teardown,
385         .suite_name = "Reorder Unit Test Suite",
386         .unit_test_cases = {
387                 TEST_CASE(test_reorder_create),
388                 TEST_CASE(test_reorder_init),
389                 TEST_CASE(test_reorder_find_existing),
390                 TEST_CASE(test_reorder_free),
391                 TEST_CASE(test_reorder_insert),
392                 TEST_CASE(test_reorder_drain),
393                 TEST_CASES_END()
394         }
395 };
396
397 static int
398 test_reorder(void)
399 {
400         return unit_test_suite_runner(&reorder_test_suite);
401 }
402
403 #endif /* !RTE_EXEC_ENV_WINDOWS */
404
405 REGISTER_TEST_COMMAND(reorder_autotest, test_reorder);