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