1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include <rte_memory.h> 11 #include <rte_lpm6.h> 12 13 #include "test.h" 14 #include "test_lpm6_data.h" 15 16 #define TEST_LPM_ASSERT(cond) do { \ 17 if (!(cond)) { \ 18 printf("Error at line %d: \n", __LINE__); \ 19 return -1; \ 20 } \ 21 } while(0) 22 23 typedef int32_t (* rte_lpm6_test)(void); 24 25 static int32_t test0(void); 26 static int32_t test1(void); 27 static int32_t test2(void); 28 static int32_t test3(void); 29 static int32_t test4(void); 30 static int32_t test5(void); 31 static int32_t test6(void); 32 static int32_t test7(void); 33 static int32_t test8(void); 34 static int32_t test9(void); 35 static int32_t test10(void); 36 static int32_t test11(void); 37 static int32_t test12(void); 38 static int32_t test13(void); 39 static int32_t test14(void); 40 static int32_t test15(void); 41 static int32_t test16(void); 42 static int32_t test17(void); 43 static int32_t test18(void); 44 static int32_t test19(void); 45 static int32_t test20(void); 46 static int32_t test21(void); 47 static int32_t test22(void); 48 static int32_t test23(void); 49 static int32_t test24(void); 50 static int32_t test25(void); 51 static int32_t test26(void); 52 static int32_t test27(void); 53 static int32_t test28(void); 54 55 rte_lpm6_test tests6[] = { 56 /* Test Cases */ 57 test0, 58 test1, 59 test2, 60 test3, 61 test4, 62 test5, 63 test6, 64 test7, 65 test8, 66 test9, 67 test10, 68 test11, 69 test12, 70 test13, 71 test14, 72 test15, 73 test16, 74 test17, 75 test18, 76 test19, 77 test20, 78 test21, 79 test22, 80 test23, 81 test24, 82 test25, 83 test26, 84 test27, 85 test28, 86 }; 87 88 #define MAX_DEPTH 128 89 #define MAX_RULES 1000000 90 #define NUMBER_TBL8S (1 << 16) 91 #define MAX_NUM_TBL8S (1 << 21) 92 #define PASS 0 93 94 static void 95 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, 96 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10, 97 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15, 98 uint8_t b16) 99 { 100 ip[0] = b1; 101 ip[1] = b2; 102 ip[2] = b3; 103 ip[3] = b4; 104 ip[4] = b5; 105 ip[5] = b6; 106 ip[6] = b7; 107 ip[7] = b8; 108 ip[8] = b9; 109 ip[9] = b10; 110 ip[10] = b11; 111 ip[11] = b12; 112 ip[12] = b13; 113 ip[13] = b14; 114 ip[14] = b15; 115 ip[15] = b16; 116 } 117 118 /* 119 * Check that rte_lpm6_create fails gracefully for incorrect user input 120 * arguments 121 */ 122 int32_t 123 test0(void) 124 { 125 struct rte_lpm6 *lpm = NULL; 126 struct rte_lpm6_config config; 127 128 config.max_rules = MAX_RULES; 129 config.number_tbl8s = NUMBER_TBL8S; 130 config.flags = 0; 131 132 /* rte_lpm6_create: lpm name == NULL */ 133 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config); 134 TEST_LPM_ASSERT(lpm == NULL); 135 136 /* rte_lpm6_create: max_rules = 0 */ 137 /* Note: __func__ inserts the function name, in this case "test0". */ 138 config.max_rules = 0; 139 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 140 TEST_LPM_ASSERT(lpm == NULL); 141 142 /* socket_id < -1 is invalid */ 143 config.max_rules = MAX_RULES; 144 lpm = rte_lpm6_create(__func__, -2, &config); 145 TEST_LPM_ASSERT(lpm == NULL); 146 147 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */ 148 config.number_tbl8s = MAX_NUM_TBL8S + 1; 149 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 150 TEST_LPM_ASSERT(lpm == NULL); 151 152 /* rte_lpm6_create: config = NULL */ 153 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL); 154 TEST_LPM_ASSERT(lpm == NULL); 155 156 return PASS; 157 } 158 159 /* 160 * Creates two different LPM tables. Tries to create a third one with the same 161 * name as the first one and expects the create function to return the same 162 * pointer. 163 */ 164 int32_t 165 test1(void) 166 { 167 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL; 168 struct rte_lpm6_config config; 169 170 config.max_rules = MAX_RULES; 171 config.number_tbl8s = NUMBER_TBL8S; 172 config.flags = 0; 173 174 /* rte_lpm6_create: lpm name == LPM1 */ 175 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config); 176 TEST_LPM_ASSERT(lpm1 != NULL); 177 178 /* rte_lpm6_create: lpm name == LPM2 */ 179 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config); 180 TEST_LPM_ASSERT(lpm2 != NULL); 181 182 /* rte_lpm6_create: lpm name == LPM2 */ 183 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config); 184 TEST_LPM_ASSERT(lpm3 == NULL); 185 186 rte_lpm6_free(lpm1); 187 rte_lpm6_free(lpm2); 188 189 return PASS; 190 } 191 192 /* 193 * Create lpm table then delete lpm table 20 times 194 * Use a slightly different rules size each time 195 */ 196 int32_t 197 test2(void) 198 { 199 struct rte_lpm6 *lpm = NULL; 200 struct rte_lpm6_config config; 201 int32_t i; 202 203 config.number_tbl8s = NUMBER_TBL8S; 204 config.flags = 0; 205 206 /* rte_lpm6_free: Free NULL */ 207 for (i = 0; i < 20; i++) { 208 config.max_rules = MAX_RULES - i; 209 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 210 TEST_LPM_ASSERT(lpm != NULL); 211 212 rte_lpm6_free(lpm); 213 } 214 215 /* Can not test free so return success */ 216 return PASS; 217 } 218 219 /* 220 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and 221 * therefore it is impossible to check for failure but this test is added to 222 * increase function coverage metrics and to validate that freeing null does 223 * not crash. 224 */ 225 int32_t 226 test3(void) 227 { 228 struct rte_lpm6 *lpm = NULL; 229 struct rte_lpm6_config config; 230 231 config.max_rules = MAX_RULES; 232 config.number_tbl8s = NUMBER_TBL8S; 233 config.flags = 0; 234 235 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 236 TEST_LPM_ASSERT(lpm != NULL); 237 238 rte_lpm6_free(lpm); 239 rte_lpm6_free(NULL); 240 return PASS; 241 } 242 243 /* 244 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments 245 */ 246 int32_t 247 test4(void) 248 { 249 struct rte_lpm6 *lpm = NULL; 250 struct rte_lpm6_config config; 251 252 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 253 uint8_t depth = 24, next_hop = 100; 254 int32_t status = 0; 255 256 config.max_rules = MAX_RULES; 257 config.number_tbl8s = NUMBER_TBL8S; 258 config.flags = 0; 259 260 /* rte_lpm6_add: lpm == NULL */ 261 status = rte_lpm6_add(NULL, ip, depth, next_hop); 262 TEST_LPM_ASSERT(status < 0); 263 264 /*Create vaild lpm to use in rest of test. */ 265 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 266 TEST_LPM_ASSERT(lpm != NULL); 267 268 /* rte_lpm6_add: depth < 1 */ 269 status = rte_lpm6_add(lpm, ip, 0, next_hop); 270 TEST_LPM_ASSERT(status < 0); 271 272 /* rte_lpm6_add: depth > MAX_DEPTH */ 273 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop); 274 TEST_LPM_ASSERT(status < 0); 275 276 rte_lpm6_free(lpm); 277 278 return PASS; 279 } 280 281 /* 282 * Check that rte_lpm6_delete fails gracefully for incorrect user input 283 * arguments 284 */ 285 int32_t 286 test5(void) 287 { 288 struct rte_lpm6 *lpm = NULL; 289 struct rte_lpm6_config config; 290 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 291 uint8_t depth = 24; 292 int32_t status = 0; 293 294 config.max_rules = MAX_RULES; 295 config.number_tbl8s = NUMBER_TBL8S; 296 config.flags = 0; 297 298 /* rte_lpm_delete: lpm == NULL */ 299 status = rte_lpm6_delete(NULL, ip, depth); 300 TEST_LPM_ASSERT(status < 0); 301 302 /*Create vaild lpm to use in rest of test. */ 303 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 304 TEST_LPM_ASSERT(lpm != NULL); 305 306 /* rte_lpm_delete: depth < 1 */ 307 status = rte_lpm6_delete(lpm, ip, 0); 308 TEST_LPM_ASSERT(status < 0); 309 310 /* rte_lpm_delete: depth > MAX_DEPTH */ 311 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1)); 312 TEST_LPM_ASSERT(status < 0); 313 314 rte_lpm6_free(lpm); 315 316 return PASS; 317 } 318 319 /* 320 * Check that rte_lpm6_lookup fails gracefully for incorrect user input 321 * arguments 322 */ 323 int32_t 324 test6(void) 325 { 326 struct rte_lpm6 *lpm = NULL; 327 struct rte_lpm6_config config; 328 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 329 uint32_t next_hop_return = 0; 330 int32_t status = 0; 331 332 config.max_rules = MAX_RULES; 333 config.number_tbl8s = NUMBER_TBL8S; 334 config.flags = 0; 335 336 /* rte_lpm6_lookup: lpm == NULL */ 337 status = rte_lpm6_lookup(NULL, ip, &next_hop_return); 338 TEST_LPM_ASSERT(status < 0); 339 340 /*Create vaild lpm to use in rest of test. */ 341 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 342 TEST_LPM_ASSERT(lpm != NULL); 343 344 /* rte_lpm6_lookup: ip = NULL */ 345 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return); 346 TEST_LPM_ASSERT(status < 0); 347 348 /* rte_lpm6_lookup: next_hop = NULL */ 349 status = rte_lpm6_lookup(lpm, ip, NULL); 350 TEST_LPM_ASSERT(status < 0); 351 352 rte_lpm6_free(lpm); 353 354 return PASS; 355 } 356 357 /* 358 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user 359 * input arguments 360 */ 361 int32_t 362 test7(void) 363 { 364 struct rte_lpm6 *lpm = NULL; 365 struct rte_lpm6_config config; 366 uint8_t ip[10][16]; 367 int32_t next_hop_return[10]; 368 int32_t status = 0; 369 370 config.max_rules = MAX_RULES; 371 config.number_tbl8s = NUMBER_TBL8S; 372 config.flags = 0; 373 374 /* rte_lpm6_lookup: lpm == NULL */ 375 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10); 376 TEST_LPM_ASSERT(status < 0); 377 378 /*Create vaild lpm to use in rest of test. */ 379 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 380 TEST_LPM_ASSERT(lpm != NULL); 381 382 /* rte_lpm6_lookup: ip = NULL */ 383 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10); 384 TEST_LPM_ASSERT(status < 0); 385 386 /* rte_lpm6_lookup: next_hop = NULL */ 387 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10); 388 TEST_LPM_ASSERT(status < 0); 389 390 rte_lpm6_free(lpm); 391 392 return PASS; 393 } 394 395 /* 396 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user 397 * input arguments 398 */ 399 int32_t 400 test8(void) 401 { 402 struct rte_lpm6 *lpm = NULL; 403 struct rte_lpm6_config config; 404 uint8_t ip[10][16]; 405 uint8_t depth[10]; 406 int32_t status = 0; 407 408 config.max_rules = MAX_RULES; 409 config.number_tbl8s = NUMBER_TBL8S; 410 config.flags = 0; 411 412 /* rte_lpm6_delete: lpm == NULL */ 413 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10); 414 TEST_LPM_ASSERT(status < 0); 415 416 /*Create vaild lpm to use in rest of test. */ 417 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 418 TEST_LPM_ASSERT(lpm != NULL); 419 420 /* rte_lpm6_delete: ip = NULL */ 421 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10); 422 TEST_LPM_ASSERT(status < 0); 423 424 /* rte_lpm6_delete: next_hop = NULL */ 425 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10); 426 TEST_LPM_ASSERT(status < 0); 427 428 rte_lpm6_free(lpm); 429 430 return PASS; 431 } 432 433 /* 434 * Call add, lookup and delete for a single rule with depth < 24. 435 * Check all the combinations for the first three bytes that result in a hit. 436 * Delete the rule and check that the same test returs a miss. 437 */ 438 int32_t 439 test9(void) 440 { 441 struct rte_lpm6 *lpm = NULL; 442 struct rte_lpm6_config config; 443 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 444 uint8_t depth = 16; 445 uint32_t next_hop_add = 100, next_hop_return = 0; 446 int32_t status = 0; 447 uint8_t i; 448 449 config.max_rules = MAX_RULES; 450 config.number_tbl8s = NUMBER_TBL8S; 451 config.flags = 0; 452 453 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 454 TEST_LPM_ASSERT(lpm != NULL); 455 456 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 457 TEST_LPM_ASSERT(status == 0); 458 459 for (i = 0; i < UINT8_MAX; i++) { 460 ip[2] = i; 461 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 462 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 463 } 464 465 status = rte_lpm6_delete(lpm, ip, depth); 466 TEST_LPM_ASSERT(status == 0); 467 468 for (i = 0; i < UINT8_MAX; i++) { 469 ip[2] = i; 470 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 471 TEST_LPM_ASSERT(status == -ENOENT); 472 } 473 474 rte_lpm6_free(lpm); 475 476 return PASS; 477 } 478 479 /* 480 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds 481 * another one and expects success. 482 */ 483 int32_t 484 test10(void) 485 { 486 struct rte_lpm6 *lpm = NULL; 487 struct rte_lpm6_config config; 488 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 489 uint8_t depth; 490 uint32_t next_hop_add = 100; 491 int32_t status = 0; 492 int i; 493 494 config.max_rules = 127; 495 config.number_tbl8s = NUMBER_TBL8S; 496 config.flags = 0; 497 498 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 499 TEST_LPM_ASSERT(lpm != NULL); 500 501 for (i = 1; i < 128; i++) { 502 depth = (uint8_t)i; 503 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 504 TEST_LPM_ASSERT(status == 0); 505 } 506 507 depth = 128; 508 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 509 TEST_LPM_ASSERT(status == -ENOSPC); 510 511 depth = 127; 512 status = rte_lpm6_delete(lpm, ip, depth); 513 TEST_LPM_ASSERT(status == 0); 514 515 depth = 128; 516 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 517 TEST_LPM_ASSERT(status == 0); 518 519 rte_lpm6_free(lpm); 520 521 return PASS; 522 } 523 524 /* 525 * Creates an LPM table with a small number of tbl8s and exhaust them in the 526 * middle of the process of creating a rule. 527 */ 528 int32_t 529 test11(void) 530 { 531 struct rte_lpm6 *lpm = NULL; 532 struct rte_lpm6_config config; 533 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 534 uint8_t depth; 535 uint32_t next_hop_add = 100; 536 int32_t status = 0; 537 538 config.max_rules = MAX_RULES; 539 config.number_tbl8s = 16; 540 config.flags = 0; 541 542 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 543 TEST_LPM_ASSERT(lpm != NULL); 544 545 depth = 128; 546 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 547 TEST_LPM_ASSERT(status == 0); 548 549 ip[0] = 1; 550 depth = 25; 551 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 552 TEST_LPM_ASSERT(status == 0); 553 554 status = rte_lpm6_delete(lpm, ip, depth); 555 TEST_LPM_ASSERT(status == 0); 556 557 depth = 33; 558 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 559 TEST_LPM_ASSERT(status == 0); 560 561 status = rte_lpm6_delete(lpm, ip, depth); 562 TEST_LPM_ASSERT(status == 0); 563 564 depth = 41; 565 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 566 TEST_LPM_ASSERT(status == 0); 567 568 status = rte_lpm6_delete(lpm, ip, depth); 569 TEST_LPM_ASSERT(status == 0); 570 571 depth = 49; 572 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 573 TEST_LPM_ASSERT(status == -ENOSPC); 574 575 depth = 41; 576 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 577 TEST_LPM_ASSERT(status == 0); 578 579 rte_lpm6_free(lpm); 580 581 return PASS; 582 } 583 584 /* 585 * Creates an LPM table with a small number of tbl8s and exhaust them in the 586 * middle of the process of adding a rule when there is already an existing rule 587 * in that position and needs to be extended. 588 */ 589 int32_t 590 test12(void) 591 { 592 struct rte_lpm6 *lpm = NULL; 593 struct rte_lpm6_config config; 594 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 595 uint8_t depth; 596 uint32_t next_hop_add = 100; 597 int32_t status = 0; 598 599 config.max_rules = MAX_RULES; 600 config.number_tbl8s = 16; 601 config.flags = 0; 602 603 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 604 TEST_LPM_ASSERT(lpm != NULL); 605 606 depth = 128; 607 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 608 TEST_LPM_ASSERT(status == 0); 609 610 ip[0] = 1; 611 depth = 41; 612 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 613 TEST_LPM_ASSERT(status == 0); 614 615 depth = 49; 616 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 617 TEST_LPM_ASSERT(status == -ENOSPC); 618 619 rte_lpm6_free(lpm); 620 621 return PASS; 622 } 623 624 /* 625 * Creates an LPM table with max_rules = 2 and tries to add 3 rules. 626 * Delete one of the rules and tries to add the third one again. 627 */ 628 int32_t 629 test13(void) 630 { 631 struct rte_lpm6 *lpm = NULL; 632 struct rte_lpm6_config config; 633 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 634 uint8_t depth; 635 uint32_t next_hop_add = 100; 636 int32_t status = 0; 637 638 config.max_rules = 2; 639 config.number_tbl8s = NUMBER_TBL8S; 640 config.flags = 0; 641 642 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 643 TEST_LPM_ASSERT(lpm != NULL); 644 645 depth = 1; 646 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 647 TEST_LPM_ASSERT(status == 0); 648 649 depth = 2; 650 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 651 TEST_LPM_ASSERT(status == 0); 652 653 depth = 3; 654 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 655 TEST_LPM_ASSERT(status == -ENOSPC); 656 657 depth = 2; 658 status = rte_lpm6_delete(lpm, ip, depth); 659 TEST_LPM_ASSERT(status == 0); 660 661 depth = 3; 662 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 663 TEST_LPM_ASSERT(status == 0); 664 665 rte_lpm6_free(lpm); 666 667 return PASS; 668 } 669 670 /* 671 * Add 2^12 routes with different first 12 bits and depth 25. 672 * Add one more route with the same depth and check that results in a failure. 673 * After that delete the last rule and create the one that was attempted to be 674 * created. This checks tbl8 exhaustion. 675 */ 676 int32_t 677 test14(void) 678 { 679 struct rte_lpm6 *lpm = NULL; 680 struct rte_lpm6_config config; 681 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 682 uint8_t depth = 25; 683 uint32_t next_hop_add = 100; 684 int32_t status = 0; 685 int i; 686 687 config.max_rules = MAX_RULES; 688 config.number_tbl8s = 256; 689 config.flags = 0; 690 691 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 692 TEST_LPM_ASSERT(lpm != NULL); 693 694 for (i = 0; i < 256; i++) { 695 ip[0] = (uint8_t)i; 696 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 697 TEST_LPM_ASSERT(status == 0); 698 } 699 700 ip[0] = 255; 701 ip[1] = 1; 702 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 703 TEST_LPM_ASSERT(status == -ENOSPC); 704 705 ip[0] = 255; 706 ip[1] = 0; 707 status = rte_lpm6_delete(lpm, ip, depth); 708 TEST_LPM_ASSERT(status == 0); 709 710 ip[0] = 255; 711 ip[1] = 1; 712 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 713 TEST_LPM_ASSERT(status == 0); 714 715 rte_lpm6_free(lpm); 716 717 return PASS; 718 } 719 720 /* 721 * Call add, lookup and delete for a single rule with depth = 24 722 */ 723 int32_t 724 test15(void) 725 { 726 struct rte_lpm6 *lpm = NULL; 727 struct rte_lpm6_config config; 728 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 729 uint8_t depth = 24; 730 uint32_t next_hop_add = 100, next_hop_return = 0; 731 int32_t status = 0; 732 733 config.max_rules = MAX_RULES; 734 config.number_tbl8s = NUMBER_TBL8S; 735 config.flags = 0; 736 737 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 738 TEST_LPM_ASSERT(lpm != NULL); 739 740 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 741 TEST_LPM_ASSERT(status == 0); 742 743 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 744 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 745 746 status = rte_lpm6_delete(lpm, ip, depth); 747 TEST_LPM_ASSERT(status == 0); 748 749 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 750 TEST_LPM_ASSERT(status == -ENOENT); 751 752 rte_lpm6_free(lpm); 753 754 return PASS; 755 } 756 757 /* 758 * Call add, lookup and delete for a single rule with depth > 24 759 */ 760 int32_t 761 test16(void) 762 { 763 struct rte_lpm6 *lpm = NULL; 764 struct rte_lpm6_config config; 765 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; 766 uint8_t depth = 128; 767 uint32_t next_hop_add = 100, next_hop_return = 0; 768 int32_t status = 0; 769 770 config.max_rules = MAX_RULES; 771 config.number_tbl8s = NUMBER_TBL8S; 772 config.flags = 0; 773 774 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 775 TEST_LPM_ASSERT(lpm != NULL); 776 777 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 778 TEST_LPM_ASSERT(status == 0); 779 780 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 781 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 782 783 status = rte_lpm6_delete(lpm, ip, depth); 784 TEST_LPM_ASSERT(status == 0); 785 786 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 787 TEST_LPM_ASSERT(status == -ENOENT); 788 789 rte_lpm6_free(lpm); 790 791 return PASS; 792 } 793 794 /* 795 * Use rte_lpm6_add to add rules which effect only the second half of the lpm 796 * table. Use all possible depths ranging from 1..32. Set the next hop = to the 797 * depth. Check lookup hit for on every add and check for lookup miss on the 798 * first half of the lpm table after each add. Finally delete all rules going 799 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each 800 * delete. The lookup should return the next_hop_add value related to the 801 * previous depth value (i.e. depth -1). 802 */ 803 int32_t 804 test17(void) 805 { 806 struct rte_lpm6 *lpm = NULL; 807 struct rte_lpm6_config config; 808 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255, 809 255,255,255,255,255,255,255}; 810 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 811 uint8_t depth; 812 uint32_t next_hop_add, next_hop_return; 813 int32_t status = 0; 814 815 config.max_rules = MAX_RULES; 816 config.number_tbl8s = NUMBER_TBL8S; 817 config.flags = 0; 818 819 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 820 TEST_LPM_ASSERT(lpm != NULL); 821 822 /* Loop with rte_lpm6_add. */ 823 for (depth = 1; depth <= 16; depth++) { 824 /* Let the next_hop_add value = depth. Just for change. */ 825 next_hop_add = depth; 826 827 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add); 828 TEST_LPM_ASSERT(status == 0); 829 830 /* Check IP in first half of tbl24 which should be empty. */ 831 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); 832 TEST_LPM_ASSERT(status == -ENOENT); 833 834 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); 835 TEST_LPM_ASSERT((status == 0) && 836 (next_hop_return == next_hop_add)); 837 } 838 839 /* Loop with rte_lpm6_delete. */ 840 for (depth = 16; depth >= 1; depth--) { 841 next_hop_add = (depth - 1); 842 843 status = rte_lpm6_delete(lpm, ip2, depth); 844 TEST_LPM_ASSERT(status == 0); 845 846 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); 847 848 if (depth != 1) { 849 TEST_LPM_ASSERT((status == 0) && 850 (next_hop_return == next_hop_add)); 851 } 852 else { 853 TEST_LPM_ASSERT(status == -ENOENT); 854 } 855 856 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); 857 TEST_LPM_ASSERT(status == -ENOENT); 858 } 859 860 rte_lpm6_free(lpm); 861 862 return PASS; 863 } 864 865 /* 866 * - Add & lookup to hit invalid TBL24 entry 867 * - Add & lookup to hit valid TBL24 entry not extended 868 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry 869 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry 870 */ 871 int32_t 872 test18(void) 873 { 874 struct rte_lpm6 *lpm = NULL; 875 struct rte_lpm6_config config; 876 uint8_t ip[16], ip_1[16], ip_2[16]; 877 uint8_t depth, depth_1, depth_2; 878 uint32_t next_hop_add, next_hop_add_1, 879 next_hop_add_2, next_hop_return; 880 int32_t status = 0; 881 882 config.max_rules = MAX_RULES; 883 config.number_tbl8s = NUMBER_TBL8S; 884 config.flags = 0; 885 886 /* Add & lookup to hit invalid TBL24 entry */ 887 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 888 depth = 24; 889 next_hop_add = 100; 890 891 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 892 TEST_LPM_ASSERT(lpm != NULL); 893 894 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 895 TEST_LPM_ASSERT(status == 0); 896 897 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 898 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 899 900 status = rte_lpm6_delete(lpm, ip, depth); 901 TEST_LPM_ASSERT(status == 0); 902 903 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 904 TEST_LPM_ASSERT(status == -ENOENT); 905 906 rte_lpm6_delete_all(lpm); 907 908 /* Add & lookup to hit valid TBL24 entry not extended */ 909 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 910 depth = 23; 911 next_hop_add = 100; 912 913 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 914 TEST_LPM_ASSERT(status == 0); 915 916 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 917 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 918 919 depth = 24; 920 next_hop_add = 101; 921 922 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 923 TEST_LPM_ASSERT(status == 0); 924 925 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 926 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 927 928 depth = 24; 929 930 status = rte_lpm6_delete(lpm, ip, depth); 931 TEST_LPM_ASSERT(status == 0); 932 933 depth = 23; 934 935 status = rte_lpm6_delete(lpm, ip, depth); 936 TEST_LPM_ASSERT(status == 0); 937 938 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 939 TEST_LPM_ASSERT(status == -ENOENT); 940 941 rte_lpm6_delete_all(lpm); 942 943 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8 944 * entry. 945 */ 946 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 947 depth = 32; 948 next_hop_add = 100; 949 950 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 951 TEST_LPM_ASSERT(status == 0); 952 953 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 954 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 955 956 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 957 depth = 32; 958 next_hop_add = 101; 959 960 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 961 TEST_LPM_ASSERT(status == 0); 962 963 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 964 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 965 966 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 967 depth = 32; 968 next_hop_add = 100; 969 970 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 971 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 972 973 status = rte_lpm6_delete(lpm, ip, depth); 974 TEST_LPM_ASSERT(status == 0); 975 976 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 977 TEST_LPM_ASSERT(status == -ENOENT); 978 979 rte_lpm6_delete_all(lpm); 980 981 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8 982 * entry 983 */ 984 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 985 depth_1 = 25; 986 next_hop_add_1 = 101; 987 988 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 989 depth_2 = 32; 990 next_hop_add_2 = 102; 991 992 next_hop_return = 0; 993 994 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1); 995 TEST_LPM_ASSERT(status == 0); 996 997 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); 998 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); 999 1000 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2); 1001 TEST_LPM_ASSERT(status == 0); 1002 1003 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); 1004 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2)); 1005 1006 status = rte_lpm6_delete(lpm, ip_2, depth_2); 1007 TEST_LPM_ASSERT(status == 0); 1008 1009 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); 1010 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); 1011 1012 status = rte_lpm6_delete(lpm, ip_1, depth_1); 1013 TEST_LPM_ASSERT(status == 0); 1014 1015 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); 1016 TEST_LPM_ASSERT(status == -ENOENT); 1017 1018 rte_lpm6_free(lpm); 1019 1020 return PASS; 1021 } 1022 1023 /* 1024 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete & 1025 * lookup) 1026 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup) 1027 * - Add rule that extends a TBL24 valid entry & lookup for both rules (& 1028 * delete & lookup) 1029 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup) 1030 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup) 1031 * - Delete a rule that is not present in the TBL24 & lookup 1032 * - Delete a rule that is not present in the TBL8 & lookup 1033 */ 1034 int32_t 1035 test19(void) 1036 { 1037 struct rte_lpm6 *lpm = NULL; 1038 struct rte_lpm6_config config; 1039 uint8_t ip[16]; 1040 uint8_t depth; 1041 uint32_t next_hop_add, next_hop_return; 1042 int32_t status = 0; 1043 1044 config.max_rules = MAX_RULES; 1045 config.number_tbl8s = NUMBER_TBL8S; 1046 config.flags = 0; 1047 1048 /* Add rule that covers a TBL24 range previously invalid & lookup 1049 * (& delete & lookup) 1050 */ 1051 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1052 TEST_LPM_ASSERT(lpm != NULL); 1053 1054 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1055 depth = 16; 1056 next_hop_add = 100; 1057 1058 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1059 TEST_LPM_ASSERT(status == 0); 1060 1061 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1062 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1063 1064 status = rte_lpm6_delete(lpm, ip, depth); 1065 TEST_LPM_ASSERT(status == 0); 1066 1067 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1068 TEST_LPM_ASSERT(status == -ENOENT); 1069 1070 rte_lpm6_delete_all(lpm); 1071 1072 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1073 depth = 25; 1074 next_hop_add = 100; 1075 1076 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1077 TEST_LPM_ASSERT(status == 0); 1078 1079 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1080 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1081 1082 status = rte_lpm6_delete(lpm, ip, depth); 1083 TEST_LPM_ASSERT(status == 0); 1084 1085 rte_lpm6_delete_all(lpm); 1086 1087 /* 1088 * Add rule that extends a TBL24 valid entry & lookup for both rules 1089 * (& delete & lookup) 1090 */ 1091 1092 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1093 depth = 24; 1094 next_hop_add = 100; 1095 1096 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1097 TEST_LPM_ASSERT(status == 0); 1098 1099 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1100 depth = 32; 1101 next_hop_add = 101; 1102 1103 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1104 TEST_LPM_ASSERT(status == 0); 1105 1106 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1107 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1108 1109 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1110 next_hop_add = 100; 1111 1112 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1113 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1114 1115 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1116 depth = 24; 1117 1118 status = rte_lpm6_delete(lpm, ip, depth); 1119 TEST_LPM_ASSERT(status == 0); 1120 1121 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1122 TEST_LPM_ASSERT(status == -ENOENT); 1123 1124 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1125 depth = 32; 1126 1127 status = rte_lpm6_delete(lpm, ip, depth); 1128 TEST_LPM_ASSERT(status == 0); 1129 1130 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1131 TEST_LPM_ASSERT(status == -ENOENT); 1132 1133 rte_lpm6_delete_all(lpm); 1134 1135 /* 1136 * Add rule that updates the next hop in TBL24 & lookup 1137 * (& delete & lookup) 1138 */ 1139 1140 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1141 depth = 24; 1142 next_hop_add = 100; 1143 1144 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1145 TEST_LPM_ASSERT(status == 0); 1146 1147 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1148 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1149 1150 next_hop_add = 101; 1151 1152 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1153 TEST_LPM_ASSERT(status == 0); 1154 1155 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1156 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1157 1158 status = rte_lpm6_delete(lpm, ip, depth); 1159 TEST_LPM_ASSERT(status == 0); 1160 1161 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1162 TEST_LPM_ASSERT(status == -ENOENT); 1163 1164 rte_lpm6_delete_all(lpm); 1165 1166 /* 1167 * Add rule that updates the next hop in TBL8 & lookup 1168 * (& delete & lookup) 1169 */ 1170 1171 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1172 depth = 32; 1173 next_hop_add = 100; 1174 1175 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1176 TEST_LPM_ASSERT(status == 0); 1177 1178 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1179 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1180 1181 next_hop_add = 101; 1182 1183 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1184 TEST_LPM_ASSERT(status == 0); 1185 1186 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1187 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1188 1189 status = rte_lpm6_delete(lpm, ip, depth); 1190 TEST_LPM_ASSERT(status == 0); 1191 1192 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1193 TEST_LPM_ASSERT(status == -ENOENT); 1194 1195 rte_lpm6_delete_all(lpm); 1196 1197 /* Delete a rule that is not present in the TBL24 & lookup */ 1198 1199 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1200 depth = 24; 1201 next_hop_add = 100; 1202 1203 status = rte_lpm6_delete(lpm, ip, depth); 1204 TEST_LPM_ASSERT(status < 0); 1205 1206 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1207 TEST_LPM_ASSERT(status == -ENOENT); 1208 1209 rte_lpm6_delete_all(lpm); 1210 1211 /* Delete a rule that is not present in the TBL8 & lookup */ 1212 1213 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1214 depth = 32; 1215 next_hop_add = 100; 1216 1217 status = rte_lpm6_delete(lpm, ip, depth); 1218 TEST_LPM_ASSERT(status < 0); 1219 1220 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1221 TEST_LPM_ASSERT(status == -ENOENT); 1222 1223 rte_lpm6_free(lpm); 1224 1225 return PASS; 1226 } 1227 1228 /* 1229 * Add two rules, lookup to hit the more specific one, lookup to hit the less 1230 * specific one delete the less specific rule and lookup previous values again; 1231 * add a more specific rule than the existing rule, lookup again 1232 */ 1233 int32_t 1234 test20(void) 1235 { 1236 struct rte_lpm6 *lpm = NULL; 1237 struct rte_lpm6_config config; 1238 uint8_t ip[16]; 1239 uint8_t depth; 1240 uint32_t next_hop_add, next_hop_return; 1241 int32_t status = 0; 1242 1243 config.max_rules = MAX_RULES; 1244 config.number_tbl8s = NUMBER_TBL8S; 1245 config.flags = 0; 1246 1247 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1248 TEST_LPM_ASSERT(lpm != NULL); 1249 1250 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1251 depth = 24; 1252 next_hop_add = 100; 1253 1254 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1255 TEST_LPM_ASSERT(status == 0); 1256 1257 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10); 1258 depth = 128; 1259 next_hop_add = 101; 1260 1261 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1262 TEST_LPM_ASSERT(status == 0); 1263 1264 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1265 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1266 1267 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1268 next_hop_add = 100; 1269 1270 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1271 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1272 1273 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1274 depth = 24; 1275 1276 status = rte_lpm6_delete(lpm, ip, depth); 1277 TEST_LPM_ASSERT(status == 0); 1278 1279 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1280 TEST_LPM_ASSERT(status == -ENOENT); 1281 1282 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10); 1283 depth = 128; 1284 1285 status = rte_lpm6_delete(lpm, ip, depth); 1286 TEST_LPM_ASSERT(status == 0); 1287 1288 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1289 TEST_LPM_ASSERT(status == -ENOENT); 1290 1291 rte_lpm6_free(lpm); 1292 1293 return PASS; 1294 } 1295 1296 /* 1297 * Adds 3 rules and look them up through the lookup_bulk function. 1298 * Includes in the lookup a fourth IP address that won't match 1299 * and checks that the result is as expected. 1300 */ 1301 int32_t 1302 test21(void) 1303 { 1304 struct rte_lpm6 *lpm = NULL; 1305 struct rte_lpm6_config config; 1306 uint8_t ip_batch[4][16]; 1307 uint8_t depth; 1308 uint32_t next_hop_add; 1309 int32_t next_hop_return[4]; 1310 int32_t status = 0; 1311 1312 config.max_rules = MAX_RULES; 1313 config.number_tbl8s = NUMBER_TBL8S; 1314 config.flags = 0; 1315 1316 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1317 TEST_LPM_ASSERT(lpm != NULL); 1318 1319 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1320 depth = 48; 1321 next_hop_add = 100; 1322 1323 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add); 1324 TEST_LPM_ASSERT(status == 0); 1325 1326 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1327 depth = 48; 1328 next_hop_add = 101; 1329 1330 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add); 1331 TEST_LPM_ASSERT(status == 0); 1332 1333 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1334 depth = 48; 1335 next_hop_add = 102; 1336 1337 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add); 1338 TEST_LPM_ASSERT(status == 0); 1339 1340 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1341 1342 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1343 next_hop_return, 4); 1344 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100 1345 && next_hop_return[1] == 101 && next_hop_return[2] == 102 1346 && next_hop_return[3] == -1); 1347 1348 rte_lpm6_free(lpm); 1349 1350 return PASS; 1351 } 1352 1353 /* 1354 * Adds 5 rules and look them up. 1355 * Use the delete_bulk function to delete two of them. Lookup again. 1356 * Use the delete_bulk function to delete one more. Lookup again. 1357 * Use the delete_bulk function to delete two more, one invalid. Lookup again. 1358 * Use the delete_bulk function to delete the remaining one. Lookup again. 1359 */ 1360 int32_t 1361 test22(void) 1362 { 1363 struct rte_lpm6 *lpm = NULL; 1364 struct rte_lpm6_config config; 1365 uint8_t ip_batch[5][16]; 1366 uint8_t depth[5]; 1367 uint32_t next_hop_add; 1368 int32_t next_hop_return[5]; 1369 int32_t status = 0; 1370 1371 config.max_rules = MAX_RULES; 1372 config.number_tbl8s = NUMBER_TBL8S; 1373 config.flags = 0; 1374 1375 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1376 TEST_LPM_ASSERT(lpm != NULL); 1377 1378 /* Adds 5 rules and look them up */ 1379 1380 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1381 depth[0] = 48; 1382 next_hop_add = 101; 1383 1384 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add); 1385 TEST_LPM_ASSERT(status == 0); 1386 1387 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1388 depth[1] = 48; 1389 next_hop_add = 102; 1390 1391 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add); 1392 TEST_LPM_ASSERT(status == 0); 1393 1394 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1395 depth[2] = 48; 1396 next_hop_add = 103; 1397 1398 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add); 1399 TEST_LPM_ASSERT(status == 0); 1400 1401 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1402 depth[3] = 48; 1403 next_hop_add = 104; 1404 1405 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add); 1406 TEST_LPM_ASSERT(status == 0); 1407 1408 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1409 depth[4] = 48; 1410 next_hop_add = 105; 1411 1412 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add); 1413 TEST_LPM_ASSERT(status == 0); 1414 1415 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1416 next_hop_return, 5); 1417 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101 1418 && next_hop_return[1] == 102 && next_hop_return[2] == 103 1419 && next_hop_return[3] == 104 && next_hop_return[4] == 105); 1420 1421 /* Use the delete_bulk function to delete two of them. Lookup again */ 1422 1423 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2); 1424 TEST_LPM_ASSERT(status == 0); 1425 1426 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1427 next_hop_return, 5); 1428 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 1429 && next_hop_return[1] == -1 && next_hop_return[2] == 103 1430 && next_hop_return[3] == 104 && next_hop_return[4] == 105); 1431 1432 /* Use the delete_bulk function to delete one more. Lookup again */ 1433 1434 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1); 1435 TEST_LPM_ASSERT(status == 0); 1436 1437 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1438 next_hop_return, 5); 1439 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 1440 && next_hop_return[1] == -1 && next_hop_return[2] == -1 1441 && next_hop_return[3] == 104 && next_hop_return[4] == 105); 1442 1443 /* Use the delete_bulk function to delete two, one invalid. Lookup again */ 1444 1445 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1446 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2); 1447 TEST_LPM_ASSERT(status == 0); 1448 1449 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1450 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1451 next_hop_return, 5); 1452 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 1453 && next_hop_return[1] == -1 && next_hop_return[2] == -1 1454 && next_hop_return[3] == -1 && next_hop_return[4] == 105); 1455 1456 /* Use the delete_bulk function to delete the remaining one. Lookup again */ 1457 1458 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1); 1459 TEST_LPM_ASSERT(status == 0); 1460 1461 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, 1462 next_hop_return, 5); 1463 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 1464 && next_hop_return[1] == -1 && next_hop_return[2] == -1 1465 && next_hop_return[3] == -1 && next_hop_return[4] == -1); 1466 1467 rte_lpm6_free(lpm); 1468 1469 return PASS; 1470 } 1471 1472 /* 1473 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete, 1474 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension 1475 * and contraction. 1476 */ 1477 int32_t 1478 test23(void) 1479 { 1480 struct rte_lpm6 *lpm = NULL; 1481 struct rte_lpm6_config config; 1482 uint32_t i; 1483 uint8_t ip[16]; 1484 uint8_t depth; 1485 uint32_t next_hop_add, next_hop_return; 1486 int32_t status = 0; 1487 1488 config.max_rules = MAX_RULES; 1489 config.number_tbl8s = NUMBER_TBL8S; 1490 config.flags = 0; 1491 1492 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1493 TEST_LPM_ASSERT(lpm != NULL); 1494 1495 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 1496 depth = 128; 1497 next_hop_add = 100; 1498 1499 for (i = 0; i < 30; i++) { 1500 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1501 TEST_LPM_ASSERT(status == 0); 1502 1503 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1504 TEST_LPM_ASSERT((status == 0) && 1505 (next_hop_return == next_hop_add)); 1506 1507 status = rte_lpm6_delete(lpm, ip, depth); 1508 TEST_LPM_ASSERT(status == 0); 1509 1510 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1511 TEST_LPM_ASSERT(status == -ENOENT); 1512 } 1513 1514 rte_lpm6_free(lpm); 1515 1516 return PASS; 1517 } 1518 1519 /* 1520 * Sequence of operations for find existing lpm table 1521 * 1522 * - create table 1523 * - find existing table: hit 1524 * - find non-existing table: miss 1525 */ 1526 int32_t 1527 test24(void) 1528 { 1529 struct rte_lpm6 *lpm = NULL, *result = NULL; 1530 struct rte_lpm6_config config; 1531 1532 config.max_rules = 256 * 32; 1533 config.number_tbl8s = NUMBER_TBL8S; 1534 config.flags = 0; 1535 1536 /* Create lpm */ 1537 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config); 1538 TEST_LPM_ASSERT(lpm != NULL); 1539 1540 /* Try to find existing lpm */ 1541 result = rte_lpm6_find_existing("lpm_find_existing"); 1542 TEST_LPM_ASSERT(result == lpm); 1543 1544 /* Try to find non-existing lpm */ 1545 result = rte_lpm6_find_existing("lpm_find_non_existing"); 1546 TEST_LPM_ASSERT(result == NULL); 1547 1548 /* Cleanup. */ 1549 rte_lpm6_delete_all(lpm); 1550 rte_lpm6_free(lpm); 1551 1552 return PASS; 1553 } 1554 1555 /* 1556 * Add a set of random routes with random depths. 1557 * Lookup different IP addresses that match the routes previously added. 1558 * Checks that the next hop is the expected one. 1559 * The routes, IP addresses and expected result for every case have been 1560 * precalculated by using a python script and stored in a .h file. 1561 */ 1562 int32_t 1563 test25(void) 1564 { 1565 struct rte_lpm6 *lpm = NULL; 1566 struct rte_lpm6_config config; 1567 uint8_t ip[16]; 1568 uint32_t i; 1569 uint8_t depth; 1570 uint32_t next_hop_add, next_hop_return, next_hop_expected; 1571 int32_t status = 0; 1572 1573 config.max_rules = MAX_RULES; 1574 config.number_tbl8s = NUMBER_TBL8S; 1575 config.flags = 0; 1576 1577 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1578 TEST_LPM_ASSERT(lpm != NULL); 1579 1580 for (i = 0; i < 1000; i++) { 1581 memcpy(ip, large_route_table[i].ip, 16); 1582 depth = large_route_table[i].depth; 1583 next_hop_add = large_route_table[i].next_hop; 1584 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1585 TEST_LPM_ASSERT(status == 0); 1586 } 1587 1588 /* generate large IPS table and expected next_hops */ 1589 generate_large_ips_table(1); 1590 1591 for (i = 0; i < 100000; i++) { 1592 memcpy(ip, large_ips_table[i].ip, 16); 1593 next_hop_expected = large_ips_table[i].next_hop; 1594 1595 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1596 TEST_LPM_ASSERT((status == 0) && 1597 (next_hop_return == next_hop_expected)); 1598 } 1599 1600 rte_lpm6_free(lpm); 1601 1602 return PASS; 1603 } 1604 1605 /* 1606 * Test for overwriting of tbl8: 1607 * - add rule /32 and lookup 1608 * - add new rule /24 and lookup 1609 * - add third rule /25 and lookup 1610 * - lookup /32 and /24 rule to ensure the table has not been overwritten. 1611 */ 1612 int32_t 1613 test26(void) 1614 { 1615 struct rte_lpm6 *lpm = NULL; 1616 struct rte_lpm6_config config; 1617 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1618 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1619 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1620 uint8_t d_ip_10_32 = 32; 1621 uint8_t d_ip_10_24 = 24; 1622 uint8_t d_ip_20_25 = 25; 1623 uint32_t next_hop_ip_10_32 = 100; 1624 uint32_t next_hop_ip_10_24 = 105; 1625 uint32_t next_hop_ip_20_25 = 111; 1626 uint32_t next_hop_return = 0; 1627 int32_t status = 0; 1628 1629 config.max_rules = MAX_RULES; 1630 config.number_tbl8s = NUMBER_TBL8S; 1631 config.flags = 0; 1632 1633 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1634 TEST_LPM_ASSERT(lpm != NULL); 1635 1636 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32, 1637 next_hop_ip_10_32)) < 0) 1638 return -1; 1639 1640 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); 1641 uint32_t test_hop_10_32 = next_hop_return; 1642 TEST_LPM_ASSERT(status == 0); 1643 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); 1644 1645 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24, 1646 next_hop_ip_10_24)) < 0) 1647 return -1; 1648 1649 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); 1650 uint32_t test_hop_10_24 = next_hop_return; 1651 TEST_LPM_ASSERT(status == 0); 1652 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); 1653 1654 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25, 1655 next_hop_ip_20_25)) < 0) 1656 return -1; 1657 1658 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return); 1659 uint32_t test_hop_20_25 = next_hop_return; 1660 TEST_LPM_ASSERT(status == 0); 1661 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25); 1662 1663 if (test_hop_10_32 == test_hop_10_24) { 1664 printf("Next hop return equal\n"); 1665 return -1; 1666 } 1667 1668 if (test_hop_10_24 == test_hop_20_25){ 1669 printf("Next hop return equal\n"); 1670 return -1; 1671 } 1672 1673 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); 1674 TEST_LPM_ASSERT(status == 0); 1675 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); 1676 1677 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); 1678 TEST_LPM_ASSERT(status == 0); 1679 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); 1680 1681 rte_lpm6_free(lpm); 1682 1683 return PASS; 1684 } 1685 1686 /* 1687 * Add a rule that reaches the end of the tree. 1688 * Add a rule that is more generic than the first one. 1689 * Check every possible combination that produces a match for the second rule. 1690 * This tests tbl expansion. 1691 */ 1692 int32_t 1693 test27(void) 1694 { 1695 struct rte_lpm6 *lpm = NULL; 1696 struct rte_lpm6_config config; 1697 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0}; 1698 uint8_t depth = 128; 1699 uint32_t next_hop_add = 100, next_hop_return; 1700 int32_t status = 0; 1701 int i, j; 1702 1703 config.max_rules = MAX_RULES; 1704 config.number_tbl8s = NUMBER_TBL8S; 1705 config.flags = 0; 1706 1707 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1708 TEST_LPM_ASSERT(lpm != NULL); 1709 1710 depth = 128; 1711 next_hop_add = 128; 1712 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1713 TEST_LPM_ASSERT(status == 0); 1714 1715 depth = 112; 1716 next_hop_add = 112; 1717 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1718 TEST_LPM_ASSERT(status == 0); 1719 1720 for (i = 0; i < 256; i++) { 1721 ip[14] = (uint8_t)i; 1722 for (j = 0; j < 256; j++) { 1723 ip[15] = (uint8_t)j; 1724 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1725 if (i == 0 && j == 0) 1726 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128); 1727 else 1728 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112); 1729 } 1730 } 1731 1732 rte_lpm6_free(lpm); 1733 1734 return PASS; 1735 } 1736 1737 /* 1738 * Call add, lookup and delete for a single rule with maximum 21bit next_hop 1739 * size. 1740 * Check that next_hop returned from lookup is equal to provisioned value. 1741 * Delete the rule and check that the same test returs a miss. 1742 */ 1743 int32_t 1744 test28(void) 1745 { 1746 struct rte_lpm6 *lpm = NULL; 1747 struct rte_lpm6_config config; 1748 uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 1749 uint8_t depth = 16; 1750 uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0; 1751 int32_t status = 0; 1752 1753 config.max_rules = MAX_RULES; 1754 config.number_tbl8s = NUMBER_TBL8S; 1755 config.flags = 0; 1756 1757 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 1758 TEST_LPM_ASSERT(lpm != NULL); 1759 1760 status = rte_lpm6_add(lpm, ip, depth, next_hop_add); 1761 TEST_LPM_ASSERT(status == 0); 1762 1763 status = rte_lpm6_lookup(lpm, ip, &next_hop_return); 1764 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); 1765 1766 status = rte_lpm6_delete(lpm, ip, depth); 1767 TEST_LPM_ASSERT(status == 0); 1768 rte_lpm6_free(lpm); 1769 1770 return PASS; 1771 } 1772 1773 /* 1774 * Do all unit tests. 1775 */ 1776 static int 1777 test_lpm6(void) 1778 { 1779 unsigned i; 1780 int status = -1, global_status = 0; 1781 1782 for (i = 0; i < RTE_DIM(tests6); i++) { 1783 printf("# test %02d\n", i); 1784 status = tests6[i](); 1785 1786 if (status < 0) { 1787 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i])); 1788 global_status = status; 1789 } 1790 } 1791 1792 return global_status; 1793 } 1794 1795 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6); 1796