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