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 rte_pktmbuf_free(bufs[i]); 222 } 223 return ret; 224 } 225 226 static int 227 test_reorder_drain(void) 228 { 229 struct rte_reorder_buffer *b = NULL; 230 struct rte_mempool *p = test_params->p; 231 const unsigned int size = 4; 232 const unsigned int num_bufs = 8; 233 struct rte_mbuf *bufs[num_bufs]; 234 struct rte_mbuf *robufs[num_bufs]; 235 int ret = 0; 236 unsigned i, cnt; 237 238 /* initialize all robufs to NULL */ 239 for (i = 0; i < num_bufs; i++) 240 robufs[i] = NULL; 241 242 /* This would create a reorder buffer instance consisting of: 243 * reorder_seq = 0 244 * ready_buf: RB[size] = {NULL, NULL, NULL, NULL} 245 * order_buf: OB[size] = {NULL, NULL, NULL, NULL} 246 */ 247 b = rte_reorder_create("test_drain", rte_socket_id(), size); 248 TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer"); 249 250 /* Check no drained packets if reorder is empty */ 251 cnt = rte_reorder_drain(b, robufs, 1); 252 if (cnt != 0) { 253 printf("%s:%d: drained packets from empty reorder buffer\n", 254 __func__, __LINE__); 255 ret = -1; 256 goto exit; 257 } 258 259 for (i = 0; i < num_bufs; i++) { 260 bufs[i] = rte_pktmbuf_alloc(p); 261 TEST_ASSERT_NOT_NULL(bufs[i], "Packet allocation failed\n"); 262 *rte_reorder_seqn(bufs[i]) = i; 263 } 264 265 /* Insert packet with seqn 1: 266 * reorder_seq = 0 267 * RB[] = {NULL, NULL, NULL, NULL} 268 * OB[] = {1, NULL, NULL, NULL} 269 */ 270 rte_reorder_insert(b, bufs[1]); 271 bufs[1] = NULL; 272 273 cnt = rte_reorder_drain(b, robufs, 1); 274 if (cnt != 1) { 275 printf("%s:%d:%d: number of expected packets not drained\n", 276 __func__, __LINE__, cnt); 277 ret = -1; 278 goto exit; 279 } 280 rte_pktmbuf_free(robufs[0]); 281 282 /* Insert more packets 283 * RB[] = {NULL, NULL, NULL, NULL} 284 * OB[] = {NULL, 2, 3, NULL} 285 */ 286 rte_reorder_insert(b, bufs[2]); 287 rte_reorder_insert(b, bufs[3]); 288 bufs[2] = NULL; 289 bufs[3] = NULL; 290 291 /* Insert more packets 292 * RB[] = {NULL, NULL, NULL, NULL} 293 * OB[] = {NULL, 2, 3, 4} 294 */ 295 rte_reorder_insert(b, bufs[4]); 296 bufs[4] = NULL; 297 298 /* Insert more packets 299 * RB[] = {2, 3, 4, NULL} 300 * OB[] = {NULL, NULL, 7, NULL} 301 */ 302 rte_reorder_insert(b, bufs[7]); 303 bufs[7] = NULL; 304 305 /* drained expected packets */ 306 cnt = rte_reorder_drain(b, robufs, 4); 307 if (cnt != 3) { 308 printf("%s:%d:%d: number of expected packets not drained\n", 309 __func__, __LINE__, cnt); 310 ret = -1; 311 goto exit; 312 } 313 for (i = 0; i < 3; i++) { 314 rte_pktmbuf_free(robufs[i]); 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_reorder_free(b); 331 for (i = 0; i < num_bufs; i++) { 332 rte_pktmbuf_free(bufs[i]); 333 rte_pktmbuf_free(robufs[i]); 334 } 335 return ret; 336 } 337 338 static int 339 test_setup(void) 340 { 341 /* reorder buffer instance creation */ 342 if (test_params->b == NULL) { 343 test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(), 344 REORDER_BUFFER_SIZE); 345 if (test_params->b == NULL) { 346 printf("%s: Error creating reorder buffer instance b\n", 347 __func__); 348 return -1; 349 } 350 } else 351 rte_reorder_reset(test_params->b); 352 353 /* mempool creation */ 354 if (test_params->p == NULL) { 355 test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL", 356 NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE, 357 rte_socket_id()); 358 if (test_params->p == NULL) { 359 printf("%s: Error creating mempool\n", __func__); 360 return -1; 361 } 362 } 363 return 0; 364 } 365 366 static void 367 test_teardown(void) 368 { 369 rte_reorder_free(test_params->b); 370 test_params->b = NULL; 371 rte_mempool_free(test_params->p); 372 test_params->p = NULL; 373 } 374 375 376 static struct unit_test_suite reorder_test_suite = { 377 378 .setup = test_setup, 379 .teardown = test_teardown, 380 .suite_name = "Reorder Unit Test Suite", 381 .unit_test_cases = { 382 TEST_CASE(test_reorder_create), 383 TEST_CASE(test_reorder_init), 384 TEST_CASE(test_reorder_find_existing), 385 TEST_CASE(test_reorder_free), 386 TEST_CASE(test_reorder_insert), 387 TEST_CASE(test_reorder_drain), 388 TEST_CASES_END() 389 } 390 }; 391 392 static int 393 test_reorder(void) 394 { 395 return unit_test_suite_runner(&reorder_test_suite); 396 } 397 398 #endif /* !RTE_EXEC_ENV_WINDOWS */ 399 400 REGISTER_TEST_COMMAND(reorder_autotest, test_reorder); 401