doc: announce behaviour change to i40e RSS
[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         ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs);
179         TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool");
180
181         for (i = 0; i < num_bufs; i++)
182                 bufs[i]->seqn = i;
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         }
198
199         /* early packet - should move mbufs to ready buf and move sequence window
200          * reorder_seq = 4
201          * RB[] = {0, 1, 2, 3}
202          * OB[] = {4, NULL, NULL, NULL}
203          */
204         ret = rte_reorder_insert(b, bufs[4]);
205         if (ret != 0) {
206                 printf("%s:%d: Error inserting early packet with seqn: size\n",
207                                 __func__, __LINE__);
208                 ret = -1;
209                 goto exit;
210         }
211
212         /* early packet from current sequence window - full ready buffer */
213         bufs[5]->seqn = 2 * size;
214         ret = rte_reorder_insert(b, bufs[5]);
215         if (!((ret == -1) && (rte_errno == ENOSPC))) {
216                 printf("%s:%d: No error inserting early packet with full ready buffer\n",
217                                 __func__, __LINE__);
218                 ret = -1;
219                 goto exit;
220         }
221
222         /* late packet */
223         bufs[6]->seqn = 3 * size;
224         ret = rte_reorder_insert(b, bufs[6]);
225         if (!((ret == -1) && (rte_errno == ERANGE))) {
226                 printf("%s:%d: No error inserting late packet with seqn:"
227                                 " 3 * size\n", __func__, __LINE__);
228                 ret = -1;
229                 goto exit;
230         }
231
232         ret = 0;
233 exit:
234         rte_mempool_put_bulk(p, (void *)bufs, num_bufs);
235         rte_reorder_free(b);
236         return ret;
237 }
238
239 static int
240 test_reorder_drain(void)
241 {
242         struct rte_reorder_buffer *b = NULL;
243         struct rte_mempool *p = test_params->p;
244         const unsigned int size = 4;
245         const unsigned int num_bufs = 8;
246         struct rte_mbuf *bufs[num_bufs];
247         struct rte_mbuf *robufs[num_bufs];
248         int ret = 0;
249         unsigned i, cnt;
250
251         /* This would create a reorder buffer instance consisting of:
252          * reorder_seq = 0
253          * ready_buf: RB[size] = {NULL, NULL, NULL, NULL}
254          * order_buf: OB[size] = {NULL, NULL, NULL, NULL}
255          */
256         b = rte_reorder_create("test_drain", rte_socket_id(), size);
257         TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer");
258
259         ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs);
260         TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool");
261
262         /* Check no drained packets if reorder is empty */
263         cnt = rte_reorder_drain(b, robufs, 1);
264         if (cnt != 0) {
265                 printf("%s:%d: drained packets from empty reorder buffer\n",
266                                 __func__, __LINE__);
267                 ret = -1;
268                 goto exit;
269         }
270
271         for (i = 0; i < num_bufs; i++)
272                 bufs[i]->seqn = i;
273
274         /* Insert packet with seqn 1:
275          * reorder_seq = 0
276          * RB[] = {NULL, NULL, NULL, NULL}
277          * OB[] = {1, NULL, NULL, NULL}
278          */
279         rte_reorder_insert(b, bufs[1]);
280
281         cnt = rte_reorder_drain(b, robufs, 1);
282         if (cnt != 1) {
283                 printf("%s:%d:%d: number of expected packets not drained\n",
284                                 __func__, __LINE__, cnt);
285                 ret = -1;
286                 goto exit;
287         }
288
289         /* Insert more packets
290          * RB[] = {NULL, NULL, NULL, NULL}
291          * OB[] = {NULL, 2, 3, NULL}
292          */
293         rte_reorder_insert(b, bufs[2]);
294         rte_reorder_insert(b, bufs[3]);
295
296         /* Insert more packets
297          * RB[] = {NULL, NULL, NULL, NULL}
298          * OB[] = {NULL, 2, 3, 4}
299          */
300         rte_reorder_insert(b, bufs[4]);
301
302         /* Insert more packets
303          * RB[] = {2, 3, 4, NULL}
304          * OB[] = {NULL, NULL, 7, NULL}
305          */
306         rte_reorder_insert(b, bufs[7]);
307
308         /* drained expected packets */
309         cnt = rte_reorder_drain(b, robufs, 4);
310         if (cnt != 3) {
311                 printf("%s:%d:%d: number of expected packets not drained\n",
312                                 __func__, __LINE__, cnt);
313                 ret = -1;
314                 goto exit;
315         }
316
317         /*
318          * RB[] = {NULL, NULL, NULL, NULL}
319          * OB[] = {NULL, NULL, 7, NULL}
320          */
321         cnt = rte_reorder_drain(b, robufs, 1);
322         if (cnt != 0) {
323                 printf("%s:%d:%d: number of expected packets not drained\n",
324                                 __func__, __LINE__, cnt);
325                 ret = -1;
326                 goto exit;
327         }
328         ret = 0;
329 exit:
330         rte_mempool_put_bulk(p, (void *)bufs, num_bufs);
331         rte_reorder_free(b);
332         return ret;
333 }
334
335 static int
336 test_setup(void)
337 {
338         /* reorder buffer instance creation */
339         if (test_params->b == NULL) {
340                 test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(),
341                                                         REORDER_BUFFER_SIZE);
342                 if (test_params->b == NULL) {
343                         printf("%s: Error creating reorder buffer instance b\n",
344                                         __func__);
345                         return -1;
346                 }
347         } else
348                 rte_reorder_reset(test_params->b);
349
350         /* mempool creation */
351         if (test_params->p == NULL) {
352                 test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL",
353                         NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
354                         rte_socket_id());
355                 if (test_params->p == NULL) {
356                         printf("%s: Error creating mempool\n", __func__);
357                         return -1;
358                 }
359         }
360         return 0;
361 }
362
363 static struct unit_test_suite reorder_test_suite  = {
364
365         .setup = test_setup,
366         .suite_name = "Reorder Unit Test Suite",
367         .unit_test_cases = {
368                 TEST_CASE(test_reorder_create),
369                 TEST_CASE(test_reorder_init),
370                 TEST_CASE(test_reorder_find_existing),
371                 TEST_CASE(test_reorder_free),
372                 TEST_CASE(test_reorder_insert),
373                 TEST_CASE(test_reorder_drain),
374                 TEST_CASES_END()
375         }
376 };
377
378 static int
379 test_reorder(void)
380 {
381         return unit_test_suite_runner(&reorder_test_suite);
382 }
383
384 REGISTER_TEST_COMMAND(reorder_autotest, test_reorder);