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