1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <rte_byteorder.h> 7 #include <rte_table_lpm_ipv6.h> 8 #include <rte_lru.h> 9 #include <rte_cycles.h> 10 #include "test_table_tables.h" 11 #include "test_table.h" 12 13 table_test table_tests[] = { 14 test_table_stub, 15 test_table_array, 16 test_table_lpm, 17 test_table_lpm_ipv6, 18 test_table_hash_lru, 19 test_table_hash_ext, 20 test_table_hash_cuckoo, 21 }; 22 23 #define PREPARE_PACKET(mbuf, value) do { \ 24 uint32_t *k32, *signature; \ 25 uint8_t *key; \ 26 mbuf = rte_pktmbuf_alloc(pool); \ 27 signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, \ 28 APP_METADATA_OFFSET(0)); \ 29 key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, \ 30 APP_METADATA_OFFSET(32)); \ 31 memset(key, 0, 32); \ 32 k32 = (uint32_t *) key; \ 33 k32[0] = (value); \ 34 *signature = pipeline_test_hash(key, NULL, 0, 0); \ 35 } while (0) 36 37 unsigned n_table_tests = RTE_DIM(table_tests); 38 39 /* Function prototypes */ 40 static int 41 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size); 42 static int 43 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size); 44 45 struct rte_bucket_4_8 { 46 /* Cache line 0 */ 47 uint64_t signature; 48 uint64_t lru_list; 49 struct rte_bucket_4_8 *next; 50 uint64_t next_valid; 51 uint64_t key[4]; 52 /* Cache line 1 */ 53 uint8_t data[0]; 54 }; 55 56 #if RTE_TABLE_HASH_LRU_STRATEGY == 3 57 uint64_t shuffles = 0xfffffffdfffbfff9ULL; 58 #else 59 uint64_t shuffles = 0x0003000200010000ULL; 60 #endif 61 62 static int test_lru_update(void) 63 { 64 struct rte_bucket_4_8 b; 65 struct rte_bucket_4_8 *bucket; 66 uint32_t i; 67 uint64_t pos; 68 uint64_t iterations; 69 uint64_t j; 70 int poss; 71 72 printf("---------------------------\n"); 73 printf("Testing lru_update macro...\n"); 74 printf("---------------------------\n"); 75 bucket = &b; 76 iterations = 10; 77 #if RTE_TABLE_HASH_LRU_STRATEGY == 3 78 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL; 79 #else 80 bucket->lru_list = 0x0000000100020003ULL; 81 #endif 82 poss = 0; 83 for (j = 0; j < iterations; j++) 84 for (i = 0; i < 9; i++) { 85 uint32_t idx = i >> 1; 86 lru_update(bucket, idx); 87 pos = lru_pos(bucket); 88 poss += pos; 89 printf("%s: %d lru_list=%016"PRIx64", upd=%d, " 90 "pos=%"PRIx64"\n", 91 __func__, i, bucket->lru_list, i>>1, pos); 92 } 93 94 if (bucket->lru_list != shuffles) { 95 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016" 96 PRIx64"\n", 97 __func__, i, bucket->lru_list, shuffles); 98 return -1; 99 } 100 printf("%s: output checksum of results =%d\n", 101 __func__, poss); 102 #if 0 103 if (poss != 126) { 104 printf("%s: ERROR output checksum of results =%d expected %d\n", 105 __func__, poss, 126); 106 return -1; 107 } 108 #endif 109 110 fflush(stdout); 111 112 uint64_t sc_start = rte_rdtsc(); 113 iterations = 100000000; 114 poss = 0; 115 for (j = 0; j < iterations; j++) { 116 for (i = 0; i < 4; i++) { 117 lru_update(bucket, i); 118 pos |= bucket->lru_list; 119 } 120 } 121 uint64_t sc_end = rte_rdtsc(); 122 123 printf("%s: output checksum of results =%llu\n", 124 __func__, (long long unsigned int)pos); 125 printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n", 126 __func__, sc_start, sc_end); 127 printf("\nlru_update: %lu cycles per loop iteration.\n\n", 128 (long unsigned int)((sc_end-sc_start)/(iterations*4))); 129 130 return 0; 131 } 132 133 /* Table tests */ 134 int 135 test_table_stub(void) 136 { 137 int i; 138 uint64_t expected_mask = 0, result_mask; 139 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 140 void *table; 141 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 142 143 /* Create */ 144 table = rte_table_stub_ops.f_create(NULL, 0, 1); 145 if (table == NULL) 146 return -1; 147 148 /* Traffic flow */ 149 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 150 if (i % 2 == 0) 151 PREPARE_PACKET(mbufs[i], 0xadadadad); 152 else 153 PREPARE_PACKET(mbufs[i], 0xadadadab); 154 155 expected_mask = 0; 156 rte_table_stub_ops.f_lookup(table, mbufs, -1, 157 &result_mask, (void **)entries); 158 if (result_mask != expected_mask) 159 return -2; 160 161 /* Free resources */ 162 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 163 rte_pktmbuf_free(mbufs[i]); 164 165 return 0; 166 } 167 168 int 169 test_table_array(void) 170 { 171 int status, i; 172 uint64_t result_mask; 173 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 174 void *table; 175 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 176 char entry1, entry2; 177 void *entry_ptr; 178 int key_found; 179 180 /* Initialize params and create tables */ 181 struct rte_table_array_params array_params = { 182 .n_entries = 7, 183 .offset = APP_METADATA_OFFSET(1) 184 }; 185 186 table = rte_table_array_ops.f_create(NULL, 0, 1); 187 if (table != NULL) 188 return -1; 189 190 array_params.n_entries = 0; 191 192 table = rte_table_array_ops.f_create(&array_params, 0, 1); 193 if (table != NULL) 194 return -2; 195 196 array_params.n_entries = 7; 197 198 table = rte_table_array_ops.f_create(&array_params, 0, 1); 199 if (table != NULL) 200 return -3; 201 202 array_params.n_entries = 1 << 24; 203 array_params.offset = APP_METADATA_OFFSET(1); 204 205 table = rte_table_array_ops.f_create(&array_params, 0, 1); 206 if (table == NULL) 207 return -4; 208 209 array_params.offset = APP_METADATA_OFFSET(32); 210 211 table = rte_table_array_ops.f_create(&array_params, 0, 1); 212 if (table == NULL) 213 return -5; 214 215 /* Free */ 216 status = rte_table_array_ops.f_free(table); 217 if (status < 0) 218 return -6; 219 220 status = rte_table_array_ops.f_free(NULL); 221 if (status == 0) 222 return -7; 223 224 /* Add */ 225 struct rte_table_array_key array_key_1 = { 226 .pos = 10, 227 }; 228 struct rte_table_array_key array_key_2 = { 229 .pos = 20, 230 }; 231 entry1 = 'A'; 232 entry2 = 'B'; 233 234 table = rte_table_array_ops.f_create(&array_params, 0, 1); 235 if (table == NULL) 236 return -8; 237 238 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1, 239 &key_found, &entry_ptr); 240 if (status == 0) 241 return -9; 242 243 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL, 244 &key_found, &entry_ptr); 245 if (status == 0) 246 return -10; 247 248 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, 249 &entry1, &key_found, &entry_ptr); 250 if (status != 0) 251 return -11; 252 253 /* Traffic flow */ 254 status = rte_table_array_ops.f_add(table, (void *) &array_key_2, 255 &entry2, &key_found, &entry_ptr); 256 if (status != 0) 257 return -12; 258 259 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 260 if (i % 2 == 0) 261 PREPARE_PACKET(mbufs[i], 10); 262 else 263 PREPARE_PACKET(mbufs[i], 20); 264 265 rte_table_array_ops.f_lookup(table, mbufs, -1, 266 &result_mask, (void **)entries); 267 268 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 269 if (i % 2 == 0 && *entries[i] != 'A') 270 return -13; 271 else 272 if (i % 2 == 1 && *entries[i] != 'B') 273 return -13; 274 275 /* Free resources */ 276 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 277 rte_pktmbuf_free(mbufs[i]); 278 279 status = rte_table_array_ops.f_free(table); 280 281 return 0; 282 } 283 284 int 285 test_table_lpm(void) 286 { 287 int status, i; 288 uint64_t expected_mask = 0, result_mask; 289 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 290 void *table; 291 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 292 char entry; 293 void *entry_ptr; 294 int key_found; 295 uint32_t entry_size = 1; 296 297 /* Initialize params and create tables */ 298 struct rte_table_lpm_params lpm_params = { 299 .name = "LPM", 300 .n_rules = 1 << 24, 301 .number_tbl8s = 1 << 8, 302 .flags = 0, 303 .entry_unique_size = entry_size, 304 .offset = APP_METADATA_OFFSET(1) 305 }; 306 307 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size); 308 if (table != NULL) 309 return -1; 310 311 lpm_params.name = NULL; 312 313 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); 314 if (table != NULL) 315 return -2; 316 317 lpm_params.name = "LPM"; 318 lpm_params.n_rules = 0; 319 320 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); 321 if (table != NULL) 322 return -3; 323 324 lpm_params.n_rules = 1 << 24; 325 lpm_params.offset = APP_METADATA_OFFSET(32); 326 lpm_params.entry_unique_size = 0; 327 328 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); 329 if (table != NULL) 330 return -4; 331 332 lpm_params.entry_unique_size = entry_size + 1; 333 334 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); 335 if (table != NULL) 336 return -5; 337 338 lpm_params.entry_unique_size = entry_size; 339 340 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); 341 if (table == NULL) 342 return -6; 343 344 /* Free */ 345 status = rte_table_lpm_ops.f_free(table); 346 if (status < 0) 347 return -7; 348 349 status = rte_table_lpm_ops.f_free(NULL); 350 if (status == 0) 351 return -8; 352 353 /* Add */ 354 struct rte_table_lpm_key lpm_key; 355 lpm_key.ip = 0xadadadad; 356 357 table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1); 358 if (table == NULL) 359 return -9; 360 361 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found, 362 &entry_ptr); 363 if (status == 0) 364 return -10; 365 366 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found, 367 &entry_ptr); 368 if (status == 0) 369 return -11; 370 371 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found, 372 &entry_ptr); 373 if (status == 0) 374 return -12; 375 376 lpm_key.depth = 0; 377 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, 378 &entry_ptr); 379 if (status == 0) 380 return -13; 381 382 lpm_key.depth = 33; 383 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, 384 &entry_ptr); 385 if (status == 0) 386 return -14; 387 388 lpm_key.depth = 16; 389 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, 390 &entry_ptr); 391 if (status != 0) 392 return -15; 393 394 /* Delete */ 395 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL); 396 if (status == 0) 397 return -16; 398 399 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL); 400 if (status == 0) 401 return -17; 402 403 lpm_key.depth = 0; 404 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); 405 if (status == 0) 406 return -18; 407 408 lpm_key.depth = 33; 409 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); 410 if (status == 0) 411 return -19; 412 413 lpm_key.depth = 16; 414 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); 415 if (status != 0) 416 return -20; 417 418 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); 419 if (status != 0) 420 return -21; 421 422 /* Traffic flow */ 423 entry = 'A'; 424 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, 425 &entry_ptr); 426 if (status < 0) 427 return -22; 428 429 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 430 if (i % 2 == 0) { 431 expected_mask |= (uint64_t)1 << i; 432 PREPARE_PACKET(mbufs[i], 0xadadadad); 433 } else 434 PREPARE_PACKET(mbufs[i], 0xadadadab); 435 436 rte_table_lpm_ops.f_lookup(table, mbufs, -1, 437 &result_mask, (void **)entries); 438 if (result_mask != expected_mask) 439 return -23; 440 441 /* Free resources */ 442 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 443 rte_pktmbuf_free(mbufs[i]); 444 445 status = rte_table_lpm_ops.f_free(table); 446 447 return 0; 448 } 449 450 int 451 test_table_lpm_ipv6(void) 452 { 453 int status, i; 454 uint64_t expected_mask = 0, result_mask; 455 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 456 void *table; 457 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 458 char entry; 459 void *entry_ptr; 460 int key_found; 461 uint32_t entry_size = 1; 462 463 /* Initialize params and create tables */ 464 struct rte_table_lpm_ipv6_params lpm_params = { 465 .name = "LPM", 466 .n_rules = 1 << 24, 467 .number_tbl8s = 1 << 18, 468 .entry_unique_size = entry_size, 469 .offset = APP_METADATA_OFFSET(32) 470 }; 471 472 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size); 473 if (table != NULL) 474 return -1; 475 476 lpm_params.name = NULL; 477 478 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 479 if (table != NULL) 480 return -2; 481 482 lpm_params.name = "LPM"; 483 lpm_params.n_rules = 0; 484 485 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 486 if (table != NULL) 487 return -3; 488 489 lpm_params.n_rules = 1 << 24; 490 lpm_params.number_tbl8s = 0; 491 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 492 if (table != NULL) 493 return -4; 494 495 lpm_params.number_tbl8s = 1 << 18; 496 lpm_params.entry_unique_size = 0; 497 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 498 if (table != NULL) 499 return -5; 500 501 lpm_params.entry_unique_size = entry_size + 1; 502 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 503 if (table != NULL) 504 return -6; 505 506 lpm_params.entry_unique_size = entry_size; 507 lpm_params.offset = APP_METADATA_OFFSET(32); 508 509 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 510 if (table == NULL) 511 return -7; 512 513 /* Free */ 514 status = rte_table_lpm_ipv6_ops.f_free(table); 515 if (status < 0) 516 return -8; 517 518 status = rte_table_lpm_ipv6_ops.f_free(NULL); 519 if (status == 0) 520 return -9; 521 522 /* Add */ 523 struct rte_table_lpm_ipv6_key lpm_key; 524 525 lpm_key.ip[0] = 0xad; 526 lpm_key.ip[1] = 0xad; 527 lpm_key.ip[2] = 0xad; 528 lpm_key.ip[3] = 0xad; 529 530 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); 531 if (table == NULL) 532 return -10; 533 534 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry, 535 &key_found, &entry_ptr); 536 if (status == 0) 537 return -11; 538 539 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found, 540 &entry_ptr); 541 if (status == 0) 542 return -12; 543 544 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found, 545 &entry_ptr); 546 if (status == 0) 547 return -13; 548 549 lpm_key.depth = 0; 550 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, 551 &key_found, &entry_ptr); 552 if (status == 0) 553 return -14; 554 555 lpm_key.depth = 129; 556 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, 557 &key_found, &entry_ptr); 558 if (status == 0) 559 return -15; 560 561 lpm_key.depth = 16; 562 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, 563 &key_found, &entry_ptr); 564 if (status != 0) 565 return -16; 566 567 /* Delete */ 568 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found, 569 NULL); 570 if (status == 0) 571 return -17; 572 573 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL); 574 if (status == 0) 575 return -18; 576 577 lpm_key.depth = 0; 578 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, 579 NULL); 580 if (status == 0) 581 return -19; 582 583 lpm_key.depth = 129; 584 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, 585 NULL); 586 if (status == 0) 587 return -20; 588 589 lpm_key.depth = 16; 590 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, 591 NULL); 592 if (status != 0) 593 return -21; 594 595 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, 596 NULL); 597 if (status != 0) 598 return -22; 599 600 /* Traffic flow */ 601 entry = 'A'; 602 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, 603 &key_found, &entry_ptr); 604 if (status < 0) 605 return -23; 606 607 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 608 if (i % 2 == 0) { 609 expected_mask |= (uint64_t)1 << i; 610 PREPARE_PACKET(mbufs[i], 0xadadadad); 611 } else 612 PREPARE_PACKET(mbufs[i], 0xadadadab); 613 614 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1, 615 &result_mask, (void **)entries); 616 if (result_mask != expected_mask) 617 return -24; 618 619 /* Free resources */ 620 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 621 rte_pktmbuf_free(mbufs[i]); 622 623 status = rte_table_lpm_ipv6_ops.f_free(table); 624 625 return 0; 626 } 627 628 static int 629 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size) 630 { 631 int status, i; 632 uint64_t expected_mask = 0, result_mask; 633 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 634 void *table; 635 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 636 char entry; 637 void *entry_ptr; 638 int key_found; 639 640 /* Initialize params and create tables */ 641 struct rte_table_hash_params hash_params = { 642 .name = "TABLE", 643 .key_size = key_size, 644 .key_offset = APP_METADATA_OFFSET(32), 645 .key_mask = NULL, 646 .n_keys = 1 << 10, 647 .n_buckets = 1 << 10, 648 .f_hash = pipeline_test_hash, 649 .seed = 0, 650 }; 651 652 hash_params.n_keys = 0; 653 654 table = ops->f_create(&hash_params, 0, 1); 655 if (table != NULL) 656 return -1; 657 658 hash_params.n_keys = 1 << 10; 659 hash_params.f_hash = NULL; 660 661 table = ops->f_create(&hash_params, 0, 1); 662 if (table != NULL) 663 return -4; 664 665 hash_params.f_hash = pipeline_test_hash; 666 667 table = ops->f_create(&hash_params, 0, 1); 668 if (table == NULL) 669 return -5; 670 671 /* Free */ 672 status = ops->f_free(table); 673 if (status < 0) 674 return -6; 675 676 status = ops->f_free(NULL); 677 if (status == 0) 678 return -7; 679 680 /* Add */ 681 uint8_t key[32]; 682 uint32_t *k32 = (uint32_t *) &key; 683 684 memset(key, 0, 32); 685 k32[0] = rte_be_to_cpu_32(0xadadadad); 686 687 table = ops->f_create(&hash_params, 0, 1); 688 if (table == NULL) 689 return -8; 690 691 entry = 'A'; 692 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); 693 if (status != 0) 694 return -9; 695 696 /* Delete */ 697 status = ops->f_delete(table, &key, &key_found, NULL); 698 if (status != 0) 699 return -10; 700 701 status = ops->f_delete(table, &key, &key_found, NULL); 702 if (status != 0) 703 return -11; 704 705 /* Traffic flow */ 706 entry = 'A'; 707 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); 708 if (status < 0) 709 return -12; 710 711 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 712 if (i % 2 == 0) { 713 expected_mask |= (uint64_t)1 << i; 714 PREPARE_PACKET(mbufs[i], 0xadadadad); 715 } else 716 PREPARE_PACKET(mbufs[i], 0xadadadab); 717 718 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries); 719 if (result_mask != expected_mask) 720 return -13; 721 722 /* Free resources */ 723 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 724 rte_pktmbuf_free(mbufs[i]); 725 726 status = ops->f_free(table); 727 728 return 0; 729 } 730 731 static int 732 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size) 733 { 734 int status, i; 735 uint64_t expected_mask = 0, result_mask; 736 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 737 void *table; 738 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 739 char entry; 740 int key_found; 741 void *entry_ptr; 742 743 /* Initialize params and create tables */ 744 struct rte_table_hash_params hash_params = { 745 .name = "TABLE", 746 .key_size = key_size, 747 .key_offset = APP_METADATA_OFFSET(32), 748 .key_mask = NULL, 749 .n_keys = 1 << 10, 750 .n_buckets = 1 << 10, 751 .f_hash = pipeline_test_hash, 752 .seed = 0, 753 }; 754 755 hash_params.n_keys = 0; 756 757 table = ops->f_create(&hash_params, 0, 1); 758 if (table != NULL) 759 return -1; 760 761 hash_params.n_keys = 1 << 10; 762 hash_params.key_offset = APP_METADATA_OFFSET(1); 763 764 table = ops->f_create(&hash_params, 0, 1); 765 if (table == NULL) 766 return -3; 767 768 hash_params.key_offset = APP_METADATA_OFFSET(32); 769 hash_params.f_hash = NULL; 770 771 table = ops->f_create(&hash_params, 0, 1); 772 if (table != NULL) 773 return -4; 774 775 hash_params.f_hash = pipeline_test_hash; 776 777 table = ops->f_create(&hash_params, 0, 1); 778 if (table == NULL) 779 return -5; 780 781 /* Free */ 782 status = ops->f_free(table); 783 if (status < 0) 784 return -6; 785 786 status = ops->f_free(NULL); 787 if (status == 0) 788 return -7; 789 790 /* Add */ 791 uint8_t key[32]; 792 uint32_t *k32 = (uint32_t *) &key; 793 794 memset(key, 0, 32); 795 k32[0] = rte_be_to_cpu_32(0xadadadad); 796 797 table = ops->f_create(&hash_params, 0, 1); 798 if (table == NULL) 799 return -8; 800 801 entry = 'A'; 802 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); 803 if (status != 0) 804 return -9; 805 806 /* Delete */ 807 status = ops->f_delete(table, &key, &key_found, NULL); 808 if (status != 0) 809 return -10; 810 811 status = ops->f_delete(table, &key, &key_found, NULL); 812 if (status != 0) 813 return -11; 814 815 /* Traffic flow */ 816 entry = 'A'; 817 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); 818 if (status < 0) 819 return -12; 820 821 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 822 if (i % 2 == 0) { 823 expected_mask |= (uint64_t)1 << i; 824 PREPARE_PACKET(mbufs[i], 0xadadadad); 825 } else 826 PREPARE_PACKET(mbufs[i], 0xadadadab); 827 828 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries); 829 if (result_mask != expected_mask) 830 return -13; 831 832 /* Free resources */ 833 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 834 rte_pktmbuf_free(mbufs[i]); 835 836 status = ops->f_free(table); 837 838 return 0; 839 } 840 841 int 842 test_table_hash_lru(void) 843 { 844 int status; 845 846 status = test_table_hash_lru_generic( 847 &rte_table_hash_key8_lru_ops, 848 8); 849 if (status < 0) 850 return status; 851 852 status = test_table_hash_lru_generic( 853 &rte_table_hash_key16_lru_ops, 854 16); 855 if (status < 0) 856 return status; 857 858 status = test_table_hash_lru_generic( 859 &rte_table_hash_key32_lru_ops, 860 32); 861 if (status < 0) 862 return status; 863 864 status = test_lru_update(); 865 if (status < 0) 866 return status; 867 868 return 0; 869 } 870 871 int 872 test_table_hash_ext(void) 873 { 874 int status; 875 876 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8); 877 if (status < 0) 878 return status; 879 880 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16); 881 if (status < 0) 882 return status; 883 884 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32); 885 if (status < 0) 886 return status; 887 888 return 0; 889 } 890 891 892 int 893 test_table_hash_cuckoo(void) 894 { 895 int status, i; 896 uint64_t expected_mask = 0, result_mask; 897 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; 898 void *table; 899 char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; 900 char entry; 901 void *entry_ptr; 902 int key_found; 903 uint32_t entry_size = 1; 904 905 /* Initialize params and create tables */ 906 struct rte_table_hash_cuckoo_params cuckoo_params = { 907 .name = "TABLE", 908 .key_size = 32, 909 .key_offset = APP_METADATA_OFFSET(32), 910 .key_mask = NULL, 911 .n_keys = 1 << 16, 912 .n_buckets = 1 << 16, 913 .f_hash = pipeline_test_hash_cuckoo, 914 .seed = 0, 915 }; 916 917 table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size); 918 if (table != NULL) 919 return -1; 920 921 cuckoo_params.key_size = 0; 922 923 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 924 0, entry_size); 925 if (table != NULL) 926 return -2; 927 928 cuckoo_params.key_size = 32; 929 cuckoo_params.n_keys = 0; 930 931 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 932 0, entry_size); 933 if (table != NULL) 934 return -3; 935 936 cuckoo_params.n_keys = 1 << 24; 937 cuckoo_params.f_hash = NULL; 938 939 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 940 0, entry_size); 941 if (table != NULL) 942 return -4; 943 944 cuckoo_params.f_hash = pipeline_test_hash_cuckoo; 945 cuckoo_params.name = NULL; 946 947 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 948 0, entry_size); 949 if (table != NULL) 950 return -5; 951 952 cuckoo_params.name = "CUCKOO"; 953 954 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 955 0, entry_size); 956 if (table == NULL) 957 return -6; 958 959 /* Free */ 960 status = rte_table_hash_cuckoo_ops.f_free(table); 961 if (status < 0) 962 return -7; 963 964 status = rte_table_hash_cuckoo_ops.f_free(NULL); 965 if (status == 0) 966 return -8; 967 968 /* Add */ 969 uint8_t key_cuckoo[32]; 970 uint32_t *kcuckoo = (uint32_t *) &key_cuckoo; 971 972 memset(key_cuckoo, 0, 32); 973 kcuckoo[0] = rte_be_to_cpu_32(0xadadadad); 974 975 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1); 976 if (table == NULL) 977 return -9; 978 979 entry = 'A'; 980 status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo, 981 &entry, &key_found, &entry_ptr); 982 if (status == 0) 983 return -10; 984 985 status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry, 986 &key_found, &entry_ptr); 987 if (status == 0) 988 return -11; 989 990 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo, 991 NULL, &key_found, &entry_ptr); 992 if (status == 0) 993 return -12; 994 995 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo, 996 &entry, &key_found, &entry_ptr); 997 if (status != 0) 998 return -13; 999 1000 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo, 1001 &entry, &key_found, &entry_ptr); 1002 if (status != 0) 1003 return -14; 1004 1005 /* Delete */ 1006 status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo, 1007 &key_found, NULL); 1008 if (status == 0) 1009 return -15; 1010 1011 status = rte_table_hash_cuckoo_ops.f_delete(table, NULL, 1012 &key_found, NULL); 1013 if (status == 0) 1014 return -16; 1015 1016 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo, 1017 &key_found, NULL); 1018 if (status != 0) 1019 return -17; 1020 1021 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo, 1022 &key_found, NULL); 1023 if (status != -ENOENT) 1024 return -18; 1025 1026 /* Traffic flow */ 1027 entry = 'A'; 1028 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo, 1029 &entry, &key_found, 1030 &entry_ptr); 1031 if (status < 0) 1032 return -19; 1033 1034 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 1035 if (i % 2 == 0) { 1036 expected_mask |= (uint64_t)1 << i; 1037 PREPARE_PACKET(mbufs[i], 0xadadadad); 1038 } else 1039 PREPARE_PACKET(mbufs[i], 0xadadadab); 1040 1041 rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1, 1042 &result_mask, (void **)entries); 1043 if (result_mask != expected_mask) 1044 return -20; 1045 1046 /* Free resources */ 1047 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) 1048 rte_pktmbuf_free(mbufs[i]); 1049 1050 status = rte_table_hash_cuckoo_ops.f_free(table); 1051 1052 return 0; 1053 } 1054