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