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