LCOV - code coverage report
Current view: top level - app/test - test_lpm.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 476 508 93.7 %
Date: 2025-01-02 22:41:34 Functions: 25 25 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 203 380 53.4 %

           Branch data     Line data    Source code
       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                 :            : 
       9                 :            : #include <rte_ip.h>
      10                 :            : #include <rte_lpm.h>
      11                 :            : #include <rte_malloc.h>
      12                 :            : 
      13                 :            : #include "test.h"
      14                 :            : #include "test_xmmt_ops.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_lpm_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                 :            : 
      48                 :            : rte_lpm_test tests[] = {
      49                 :            : /* Test Cases */
      50                 :            :         test0,
      51                 :            :         test1,
      52                 :            :         test2,
      53                 :            :         test3,
      54                 :            :         test4,
      55                 :            :         test5,
      56                 :            :         test6,
      57                 :            :         test7,
      58                 :            :         test8,
      59                 :            :         test9,
      60                 :            :         test10,
      61                 :            :         test11,
      62                 :            :         test12,
      63                 :            :         test13,
      64                 :            :         test14,
      65                 :            :         test15,
      66                 :            :         test16,
      67                 :            :         test17,
      68                 :            :         test18,
      69                 :            :         test19,
      70                 :            :         test20,
      71                 :            :         test21
      72                 :            : };
      73                 :            : 
      74                 :            : #define MAX_DEPTH 32
      75                 :            : #define MAX_RULES 256
      76                 :            : #define NUMBER_TBL8S 256
      77                 :            : #define PASS 0
      78                 :            : 
      79                 :            : /*
      80                 :            :  * Check that rte_lpm_create fails gracefully for incorrect user input
      81                 :            :  * arguments
      82                 :            :  */
      83                 :            : int32_t
      84                 :          1 : test0(void)
      85                 :            : {
      86                 :            :         struct rte_lpm *lpm = NULL;
      87                 :            :         struct rte_lpm_config config;
      88                 :            : 
      89                 :          1 :         config.max_rules = MAX_RULES;
      90                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
      91                 :          1 :         config.flags = 0;
      92                 :            : 
      93                 :            :         /* rte_lpm_create: lpm name == NULL */
      94                 :          1 :         lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
      95         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm == NULL);
      96                 :            : 
      97                 :            :         /* rte_lpm_create: max_rules = 0 */
      98                 :            :         /* Note: __func__ inserts the function name, in this case "test0". */
      99                 :          1 :         config.max_rules = 0;
     100                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     101         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm == NULL);
     102                 :            : 
     103                 :            :         /* socket_id < -1 is invalid */
     104                 :          1 :         config.max_rules = MAX_RULES;
     105                 :          1 :         lpm = rte_lpm_create(__func__, -2, &config);
     106         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm == NULL);
     107                 :            : 
     108                 :            :         return PASS;
     109                 :            : }
     110                 :            : 
     111                 :            : /*
     112                 :            :  * Create lpm table then delete lpm table 100 times
     113                 :            :  * Use a slightly different rules size each time
     114                 :            :  * */
     115                 :            : int32_t
     116                 :          1 : test1(void)
     117                 :            : {
     118                 :            :         struct rte_lpm *lpm = NULL;
     119                 :            :         struct rte_lpm_config config;
     120                 :            : 
     121                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     122                 :          1 :         config.flags = 0;
     123                 :            :         int32_t i;
     124                 :            : 
     125                 :            :         /* rte_lpm_free: Free NULL */
     126         [ +  + ]:        101 :         for (i = 0; i < 100; i++) {
     127                 :        100 :                 config.max_rules = MAX_RULES - i;
     128                 :        100 :                 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     129         [ -  + ]:        100 :                 TEST_LPM_ASSERT(lpm != NULL);
     130                 :            : 
     131                 :        100 :                 rte_lpm_free(lpm);
     132                 :            :         }
     133                 :            : 
     134                 :            :         /* Can not test free so return success */
     135                 :            :         return PASS;
     136                 :            : }
     137                 :            : 
     138                 :            : /*
     139                 :            :  * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
     140                 :            :  * therefore it is impossible to check for failure but this test is added to
     141                 :            :  * increase function coverage metrics and to validate that freeing null does
     142                 :            :  * not crash.
     143                 :            :  */
     144                 :            : int32_t
     145                 :          1 : test2(void)
     146                 :            : {
     147                 :            :         struct rte_lpm *lpm = NULL;
     148                 :            :         struct rte_lpm_config config;
     149                 :            : 
     150                 :          1 :         config.max_rules = MAX_RULES;
     151                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     152                 :          1 :         config.flags = 0;
     153                 :            : 
     154                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     155         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     156                 :            : 
     157                 :          1 :         rte_lpm_free(lpm);
     158                 :          1 :         rte_lpm_free(NULL);
     159                 :          1 :         return PASS;
     160                 :            : }
     161                 :            : 
     162                 :            : /*
     163                 :            :  * Check that rte_lpm_add fails gracefully for incorrect user input arguments
     164                 :            :  */
     165                 :            : int32_t
     166                 :          1 : test3(void)
     167                 :            : {
     168                 :            :         struct rte_lpm *lpm = NULL;
     169                 :            :         struct rte_lpm_config config;
     170                 :            : 
     171                 :          1 :         config.max_rules = MAX_RULES;
     172                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     173                 :          1 :         config.flags = 0;
     174                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop = 100;
     175                 :            :         uint8_t depth = 24;
     176                 :            :         int32_t status = 0;
     177                 :            : 
     178                 :            :         /* rte_lpm_add: lpm == NULL */
     179                 :          1 :         status = rte_lpm_add(NULL, ip, depth, next_hop);
     180         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     181                 :            : 
     182                 :            :         /*Create valid lpm to use in rest of test. */
     183                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     184         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     185                 :            : 
     186                 :            :         /* rte_lpm_add: depth < 1 */
     187                 :          1 :         status = rte_lpm_add(lpm, ip, 0, next_hop);
     188         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     189                 :            : 
     190                 :            :         /* rte_lpm_add: depth > MAX_DEPTH */
     191                 :          1 :         status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
     192         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     193                 :            : 
     194                 :          1 :         rte_lpm_free(lpm);
     195                 :            : 
     196                 :          1 :         return PASS;
     197                 :            : }
     198                 :            : 
     199                 :            : /*
     200                 :            :  * Check that rte_lpm_delete fails gracefully for incorrect user input
     201                 :            :  * arguments
     202                 :            :  */
     203                 :            : int32_t
     204                 :          1 : test4(void)
     205                 :            : {
     206                 :            :         struct rte_lpm *lpm = NULL;
     207                 :            :         struct rte_lpm_config config;
     208                 :            : 
     209                 :          1 :         config.max_rules = MAX_RULES;
     210                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     211                 :          1 :         config.flags = 0;
     212                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0);
     213                 :            :         uint8_t depth = 24;
     214                 :            :         int32_t status = 0;
     215                 :            : 
     216                 :            :         /* rte_lpm_delete: lpm == NULL */
     217                 :          1 :         status = rte_lpm_delete(NULL, ip, depth);
     218         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     219                 :            : 
     220                 :            :         /*Create valid lpm to use in rest of test. */
     221                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     222         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     223                 :            : 
     224                 :            :         /* rte_lpm_delete: depth < 1 */
     225                 :          1 :         status = rte_lpm_delete(lpm, ip, 0);
     226         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     227                 :            : 
     228                 :            :         /* rte_lpm_delete: depth > MAX_DEPTH */
     229                 :          1 :         status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
     230         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     231                 :            : 
     232                 :          1 :         rte_lpm_free(lpm);
     233                 :            : 
     234                 :          1 :         return PASS;
     235                 :            : }
     236                 :            : 
     237                 :            : /*
     238                 :            :  * Check that rte_lpm_lookup fails gracefully for incorrect user input
     239                 :            :  * arguments
     240                 :            :  */
     241                 :            : int32_t
     242                 :          1 : test5(void)
     243                 :            : {
     244                 :            : #if defined(RTE_LIBRTE_LPM_DEBUG)
     245                 :            :         struct rte_lpm *lpm = NULL;
     246                 :            :         struct rte_lpm_config config;
     247                 :            : 
     248                 :            :         config.max_rules = MAX_RULES;
     249                 :            :         config.number_tbl8s = NUMBER_TBL8S;
     250                 :            :         config.flags = 0;
     251                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_return = 0;
     252                 :            :         int32_t status = 0;
     253                 :            : 
     254                 :            :         /* rte_lpm_lookup: lpm == NULL */
     255                 :            :         status = rte_lpm_lookup(NULL, ip, &next_hop_return);
     256                 :            :         TEST_LPM_ASSERT(status < 0);
     257                 :            : 
     258                 :            :         /*Create valid lpm to use in rest of test. */
     259                 :            :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     260                 :            :         TEST_LPM_ASSERT(lpm != NULL);
     261                 :            : 
     262                 :            :         /* rte_lpm_lookup: depth < 1 */
     263                 :            :         status = rte_lpm_lookup(lpm, ip, NULL);
     264                 :            :         TEST_LPM_ASSERT(status < 0);
     265                 :            : 
     266                 :            :         rte_lpm_free(lpm);
     267                 :            : #endif
     268                 :          1 :         return PASS;
     269                 :            : }
     270                 :            : 
     271                 :            : 
     272                 :            : 
     273                 :            : /*
     274                 :            :  * Call add, lookup and delete for a single rule with depth <= 24
     275                 :            :  */
     276                 :            : int32_t
     277                 :          1 : test6(void)
     278                 :            : {
     279                 :            :         struct rte_lpm *lpm = NULL;
     280                 :            :         struct rte_lpm_config config;
     281                 :            : 
     282                 :          1 :         config.max_rules = MAX_RULES;
     283                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     284                 :          1 :         config.flags = 0;
     285                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
     286                 :            :         uint8_t depth = 24;
     287                 :            :         int32_t status = 0;
     288                 :            : 
     289                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     290         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     291                 :            : 
     292                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     293         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     294                 :            : 
     295                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     296         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     297                 :            : 
     298                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     299         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     300                 :            : 
     301                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     302                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     303                 :            : 
     304                 :          1 :         rte_lpm_free(lpm);
     305                 :            : 
     306                 :          1 :         return PASS;
     307                 :            : }
     308                 :            : 
     309                 :            : /*
     310                 :            :  * Call add, lookup and delete for a single rule with depth > 24
     311                 :            :  */
     312                 :            : 
     313                 :            : int32_t
     314                 :          1 : test7(void)
     315                 :            : {
     316                 :            :         xmm_t ipx4;
     317                 :            :         uint32_t hop[4];
     318                 :            :         struct rte_lpm *lpm = NULL;
     319                 :            :         struct rte_lpm_config config;
     320                 :            : 
     321                 :          1 :         config.max_rules = MAX_RULES;
     322                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     323                 :          1 :         config.flags = 0;
     324                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
     325                 :            :         uint8_t depth = 32;
     326                 :            :         int32_t status = 0;
     327                 :            : 
     328                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     329         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     330                 :            : 
     331                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     332         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     333                 :            : 
     334                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     335         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     336                 :            : 
     337                 :            :         ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
     338                 :          1 :         rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
     339         [ -  + ]:          1 :         TEST_LPM_ASSERT(hop[0] == next_hop_add);
     340         [ -  + ]:          1 :         TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
     341         [ -  + ]:          1 :         TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
     342         [ -  + ]:          1 :         TEST_LPM_ASSERT(hop[3] == next_hop_add);
     343                 :            : 
     344                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     345         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     346                 :            : 
     347                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     348                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     349                 :            : 
     350                 :          1 :         rte_lpm_free(lpm);
     351                 :            : 
     352                 :          1 :         return PASS;
     353                 :            : }
     354                 :            : 
     355                 :            : /*
     356                 :            :  * Use rte_lpm_add to add rules which effect only the second half of the lpm
     357                 :            :  * table. Use all possible depths ranging from 1..32. Set the next hop = to the
     358                 :            :  * depth. Check lookup hit for on every add and check for lookup miss on the
     359                 :            :  * first half of the lpm table after each add. Finally delete all rules going
     360                 :            :  * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
     361                 :            :  * delete. The lookup should return the next_hop_add value related to the
     362                 :            :  * previous depth value (i.e. depth -1).
     363                 :            :  */
     364                 :            : int32_t
     365                 :          1 : test8(void)
     366                 :            : {
     367                 :            :         xmm_t ipx4;
     368                 :            :         uint32_t hop[4];
     369                 :            :         struct rte_lpm *lpm = NULL;
     370                 :            :         struct rte_lpm_config config;
     371                 :            : 
     372                 :          1 :         config.max_rules = MAX_RULES;
     373                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     374                 :          1 :         config.flags = 0;
     375                 :            :         uint32_t ip1 = RTE_IPV4(127, 255, 255, 255), ip2 = RTE_IPV4(128, 0, 0, 0);
     376                 :            :         uint32_t next_hop_add, next_hop_return;
     377                 :            :         uint8_t depth;
     378                 :            :         int32_t status = 0;
     379                 :            : 
     380                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     381         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     382                 :            : 
     383                 :            :         /* Loop with rte_lpm_add. */
     384         [ +  + ]:         33 :         for (depth = 1; depth <= 32; depth++) {
     385                 :            :                 /* Let the next_hop_add value = depth. Just for change. */
     386                 :         32 :                 next_hop_add = depth;
     387                 :            : 
     388                 :         32 :                 status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
     389         [ -  + ]:         32 :                 TEST_LPM_ASSERT(status == 0);
     390                 :            : 
     391                 :            :                 /* Check IP in first half of tbl24 which should be empty. */
     392                 :            :                 status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
     393                 :          0 :                 TEST_LPM_ASSERT(status == -ENOENT);
     394                 :            : 
     395                 :            :                 status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
     396         [ -  + ]:         32 :                 TEST_LPM_ASSERT((status == 0) &&
     397                 :            :                         (next_hop_return == next_hop_add));
     398                 :            : 
     399                 :            :                 ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
     400                 :         32 :                 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
     401         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
     402         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[1] == next_hop_add);
     403         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
     404         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[3] == next_hop_add);
     405                 :            :         }
     406                 :            : 
     407                 :            :         /* Loop with rte_lpm_delete. */
     408         [ +  + ]:         33 :         for (depth = 32; depth >= 1; depth--) {
     409                 :         32 :                 next_hop_add = (uint8_t) (depth - 1);
     410                 :            : 
     411                 :         32 :                 status = rte_lpm_delete(lpm, ip2, depth);
     412         [ -  + ]:         32 :                 TEST_LPM_ASSERT(status == 0);
     413                 :            : 
     414                 :            :                 status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
     415                 :            : 
     416         [ +  + ]:         32 :                 if (depth != 1) {
     417   [ +  -  -  + ]:         31 :                         TEST_LPM_ASSERT((status == 0) &&
     418                 :            :                                 (next_hop_return == next_hop_add));
     419                 :            :                 } else {
     420         [ -  + ]:          1 :                         TEST_LPM_ASSERT(status == -ENOENT);
     421                 :            :                 }
     422                 :            : 
     423                 :            :                 status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
     424                 :          0 :                 TEST_LPM_ASSERT(status == -ENOENT);
     425                 :            : 
     426                 :            :                 ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
     427                 :         32 :                 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
     428         [ +  + ]:         32 :                 if (depth != 1) {
     429         [ -  + ]:         31 :                         TEST_LPM_ASSERT(hop[0] == next_hop_add);
     430         [ -  + ]:         31 :                         TEST_LPM_ASSERT(hop[1] == next_hop_add);
     431                 :            :                 } else {
     432         [ -  + ]:          1 :                         TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
     433         [ -  + ]:          1 :                         TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
     434                 :            :                 }
     435         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
     436         [ -  + ]:         32 :                 TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
     437                 :            :         }
     438                 :            : 
     439                 :          1 :         rte_lpm_free(lpm);
     440                 :            : 
     441                 :          1 :         return PASS;
     442                 :            : }
     443                 :            : 
     444                 :            : /*
     445                 :            :  * - Add & lookup to hit invalid TBL24 entry
     446                 :            :  * - Add & lookup to hit valid TBL24 entry not extended
     447                 :            :  * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
     448                 :            :  * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
     449                 :            :  *
     450                 :            :  */
     451                 :            : int32_t
     452                 :          1 : test9(void)
     453                 :            : {
     454                 :            :         struct rte_lpm *lpm = NULL;
     455                 :            :         struct rte_lpm_config config;
     456                 :            : 
     457                 :          1 :         config.max_rules = MAX_RULES;
     458                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     459                 :          1 :         config.flags = 0;
     460                 :            :         uint32_t ip, ip_1, ip_2;
     461                 :            :         uint8_t depth, depth_1, depth_2;
     462                 :            :         uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
     463                 :            :         int32_t status = 0;
     464                 :            : 
     465                 :            :         /* Add & lookup to hit invalid TBL24 entry */
     466                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     467                 :            :         depth = 24;
     468                 :            :         next_hop_add = 100;
     469                 :            : 
     470                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     471         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     472                 :            : 
     473                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     474         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     475                 :            : 
     476                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     477         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     478                 :            : 
     479                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     480         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     481                 :            : 
     482                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     483                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     484                 :            : 
     485                 :          1 :         rte_lpm_delete_all(lpm);
     486                 :            : 
     487                 :            :         /* Add & lookup to hit valid TBL24 entry not extended */
     488                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     489                 :            :         depth = 23;
     490                 :            :         next_hop_add = 100;
     491                 :            : 
     492                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     493         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     494                 :            : 
     495                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     496         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     497                 :            : 
     498                 :            :         depth = 24;
     499                 :            :         next_hop_add = 101;
     500                 :            : 
     501                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     502         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     503                 :            : 
     504                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     505         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     506                 :            : 
     507                 :            :         depth = 24;
     508                 :            : 
     509                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     510         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     511                 :            : 
     512                 :            :         depth = 23;
     513                 :            : 
     514                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     515         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     516                 :            : 
     517                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     518                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     519                 :            : 
     520                 :          1 :         rte_lpm_delete_all(lpm);
     521                 :            : 
     522                 :            :         /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
     523                 :            :          * entry */
     524                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     525                 :            :         depth = 32;
     526                 :            :         next_hop_add = 100;
     527                 :            : 
     528                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     529         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     530                 :            : 
     531                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     532         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     533                 :            : 
     534                 :            :         ip = RTE_IPV4(128, 0, 0, 5);
     535                 :            :         depth = 32;
     536                 :            :         next_hop_add = 101;
     537                 :            : 
     538                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     539         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     540                 :            : 
     541                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     542         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     543                 :            : 
     544                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     545         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     546                 :            : 
     547                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     548                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     549                 :            : 
     550                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     551                 :            :         depth = 32;
     552                 :            :         next_hop_add = 100;
     553                 :            : 
     554                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     555         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     556                 :            : 
     557                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     558         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     559                 :            : 
     560                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     561                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     562                 :            : 
     563                 :          1 :         rte_lpm_delete_all(lpm);
     564                 :            : 
     565                 :            :         /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
     566                 :            :          * entry */
     567                 :            :         ip_1 = RTE_IPV4(128, 0, 0, 0);
     568                 :            :         depth_1 = 25;
     569                 :            :         next_hop_add_1 = 101;
     570                 :            : 
     571                 :            :         ip_2 = RTE_IPV4(128, 0, 0, 5);
     572                 :            :         depth_2 = 32;
     573                 :            :         next_hop_add_2 = 102;
     574                 :            : 
     575                 :            :         next_hop_return = 0;
     576                 :            : 
     577                 :          1 :         status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
     578         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     579                 :            : 
     580                 :            :         status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
     581         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
     582                 :            : 
     583                 :          1 :         status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
     584         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     585                 :            : 
     586                 :            :         status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
     587         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
     588                 :            : 
     589                 :          1 :         status = rte_lpm_delete(lpm, ip_2, depth_2);
     590         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     591                 :            : 
     592                 :            :         status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
     593         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
     594                 :            : 
     595                 :          1 :         status = rte_lpm_delete(lpm, ip_1, depth_1);
     596         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     597                 :            : 
     598                 :            :         status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
     599                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     600                 :            : 
     601                 :          1 :         rte_lpm_free(lpm);
     602                 :            : 
     603                 :          1 :         return PASS;
     604                 :            : }
     605                 :            : 
     606                 :            : 
     607                 :            : /*
     608                 :            :  * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
     609                 :            :  *   lookup)
     610                 :            :  * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
     611                 :            :  * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
     612                 :            :  *   delete & lookup)
     613                 :            :  * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
     614                 :            :  * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
     615                 :            :  * - Delete a rule that is not present in the TBL24 & lookup
     616                 :            :  * - Delete a rule that is not present in the TBL8 & lookup
     617                 :            :  *
     618                 :            :  */
     619                 :            : int32_t
     620                 :          1 : test10(void)
     621                 :            : {
     622                 :            : 
     623                 :            :         struct rte_lpm *lpm = NULL;
     624                 :            :         struct rte_lpm_config config;
     625                 :            : 
     626                 :          1 :         config.max_rules = MAX_RULES;
     627                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     628                 :          1 :         config.flags = 0;
     629                 :            :         uint32_t ip, next_hop_add, next_hop_return;
     630                 :            :         uint8_t depth;
     631                 :            :         int32_t status = 0;
     632                 :            : 
     633                 :            :         /* Add rule that covers a TBL24 range previously invalid & lookup
     634                 :            :          * (& delete & lookup) */
     635                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     636         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     637                 :            : 
     638                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     639                 :            :         depth = 16;
     640                 :            :         next_hop_add = 100;
     641                 :            : 
     642                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     643         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     644                 :            : 
     645                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     646         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     647                 :            : 
     648                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     649         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     650                 :            : 
     651                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     652                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     653                 :            : 
     654                 :          1 :         rte_lpm_delete_all(lpm);
     655                 :            : 
     656                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     657                 :            :         depth = 25;
     658                 :            :         next_hop_add = 100;
     659                 :            : 
     660                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     661         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     662                 :            : 
     663                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     664         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     665                 :            : 
     666                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     667         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     668                 :            : 
     669                 :          1 :         rte_lpm_delete_all(lpm);
     670                 :            : 
     671                 :            :         /* Add rule that extends a TBL24 valid entry & lookup for both rules
     672                 :            :          * (& delete & lookup) */
     673                 :            : 
     674                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     675                 :            :         depth = 24;
     676                 :            :         next_hop_add = 100;
     677                 :            : 
     678                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     679         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     680                 :            : 
     681                 :            :         ip = RTE_IPV4(128, 0, 0, 10);
     682                 :            :         depth = 32;
     683                 :            :         next_hop_add = 101;
     684                 :            : 
     685                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     686         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     687                 :            : 
     688                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     689         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     690                 :            : 
     691                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     692                 :            :         next_hop_add = 100;
     693                 :            : 
     694                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     695         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     696                 :            : 
     697                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     698                 :            :         depth = 24;
     699                 :            : 
     700                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     701         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     702                 :            : 
     703                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     704                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     705                 :            : 
     706                 :            :         ip = RTE_IPV4(128, 0, 0, 10);
     707                 :            :         depth = 32;
     708                 :            : 
     709                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     710         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     711                 :            : 
     712                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     713                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     714                 :            : 
     715                 :          1 :         rte_lpm_delete_all(lpm);
     716                 :            : 
     717                 :            :         /* Add rule that updates the next hop in TBL24 & lookup
     718                 :            :          * (& delete & lookup) */
     719                 :            : 
     720                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     721                 :            :         depth = 24;
     722                 :            :         next_hop_add = 100;
     723                 :            : 
     724                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     725         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     726                 :            : 
     727                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     728         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     729                 :            : 
     730                 :            :         next_hop_add = 101;
     731                 :            : 
     732                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     733         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     734                 :            : 
     735                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     736         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     737                 :            : 
     738                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     739         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     740                 :            : 
     741                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     742                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     743                 :            : 
     744                 :          1 :         rte_lpm_delete_all(lpm);
     745                 :            : 
     746                 :            :         /* Add rule that updates the next hop in TBL8 & lookup
     747                 :            :          * (& delete & lookup) */
     748                 :            : 
     749                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     750                 :            :         depth = 32;
     751                 :            :         next_hop_add = 100;
     752                 :            : 
     753                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     754         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     755                 :            : 
     756                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     757         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     758                 :            : 
     759                 :            :         next_hop_add = 101;
     760                 :            : 
     761                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     762         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     763                 :            : 
     764                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     765         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     766                 :            : 
     767                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     768         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     769                 :            : 
     770                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     771                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     772                 :            : 
     773                 :          1 :         rte_lpm_delete_all(lpm);
     774                 :            : 
     775                 :            :         /* Delete a rule that is not present in the TBL24 & lookup */
     776                 :            : 
     777                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     778                 :            :         depth = 24;
     779                 :            : 
     780                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     781         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     782                 :            : 
     783                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     784                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     785                 :            : 
     786                 :          1 :         rte_lpm_delete_all(lpm);
     787                 :            : 
     788                 :            :         /* Delete a rule that is not present in the TBL8 & lookup */
     789                 :            : 
     790                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     791                 :            :         depth = 32;
     792                 :            : 
     793                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     794         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
     795                 :            : 
     796                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     797                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     798                 :            : 
     799                 :          1 :         rte_lpm_free(lpm);
     800                 :            : 
     801                 :          1 :         return PASS;
     802                 :            : }
     803                 :            : 
     804                 :            : /*
     805                 :            :  * Add two rules, lookup to hit the more specific one, lookup to hit the less
     806                 :            :  * specific one delete the less specific rule and lookup previous values again;
     807                 :            :  * add a more specific rule than the existing rule, lookup again
     808                 :            :  *
     809                 :            :  * */
     810                 :            : int32_t
     811                 :          1 : test11(void)
     812                 :            : {
     813                 :            : 
     814                 :            :         struct rte_lpm *lpm = NULL;
     815                 :            :         struct rte_lpm_config config;
     816                 :            : 
     817                 :          1 :         config.max_rules = MAX_RULES;
     818                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     819                 :          1 :         config.flags = 0;
     820                 :            :         uint32_t ip, next_hop_add, next_hop_return;
     821                 :            :         uint8_t depth;
     822                 :            :         int32_t status = 0;
     823                 :            : 
     824                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     825         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     826                 :            : 
     827                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     828                 :            :         depth = 24;
     829                 :            :         next_hop_add = 100;
     830                 :            : 
     831                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     832         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     833                 :            : 
     834                 :            :         ip = RTE_IPV4(128, 0, 0, 10);
     835                 :            :         depth = 32;
     836                 :            :         next_hop_add = 101;
     837                 :            : 
     838                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     839         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     840                 :            : 
     841                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     842         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     843                 :            : 
     844                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     845                 :            :         next_hop_add = 100;
     846                 :            : 
     847                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     848         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
     849                 :            : 
     850                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     851                 :            :         depth = 24;
     852                 :            : 
     853                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     854         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     855                 :            : 
     856                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     857                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     858                 :            : 
     859                 :            :         ip = RTE_IPV4(128, 0, 0, 10);
     860                 :            :         depth = 32;
     861                 :            : 
     862                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     863         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     864                 :            : 
     865                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     866                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     867                 :            : 
     868                 :          1 :         rte_lpm_free(lpm);
     869                 :            : 
     870                 :          1 :         return PASS;
     871                 :            : }
     872                 :            : 
     873                 :            : /*
     874                 :            :  * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
     875                 :            :  * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
     876                 :            :  * and contraction.
     877                 :            :  *
     878                 :            :  * */
     879                 :            : 
     880                 :            : int32_t
     881                 :          1 : test12(void)
     882                 :            : {
     883                 :            :         xmm_t ipx4;
     884                 :            :         uint32_t hop[4];
     885                 :            :         struct rte_lpm *lpm = NULL;
     886                 :            :         struct rte_lpm_config config;
     887                 :            : 
     888                 :          1 :         config.max_rules = MAX_RULES;
     889                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     890                 :          1 :         config.flags = 0;
     891                 :            :         uint32_t ip, i, next_hop_add, next_hop_return;
     892                 :            :         uint8_t depth;
     893                 :            :         int32_t status = 0;
     894                 :            : 
     895                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     896         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     897                 :            : 
     898                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     899                 :            :         depth = 32;
     900                 :            :         next_hop_add = 100;
     901                 :            : 
     902         [ +  + ]:       1001 :         for (i = 0; i < 1000; i++) {
     903                 :       1000 :                 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
     904         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(status == 0);
     905                 :            : 
     906                 :            :                 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     907         [ -  + ]:       1000 :                 TEST_LPM_ASSERT((status == 0) &&
     908                 :            :                                 (next_hop_return == next_hop_add));
     909                 :            : 
     910                 :            :                 ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
     911                 :       1000 :                 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
     912         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
     913         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(hop[1] == next_hop_add);
     914         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
     915         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(hop[3] == next_hop_add);
     916                 :            : 
     917                 :       1000 :                 status = rte_lpm_delete(lpm, ip, depth);
     918         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(status == 0);
     919                 :            : 
     920                 :            :                 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     921                 :          0 :                 TEST_LPM_ASSERT(status == -ENOENT);
     922                 :            :         }
     923                 :            : 
     924                 :          1 :         rte_lpm_free(lpm);
     925                 :            : 
     926                 :          1 :         return PASS;
     927                 :            : }
     928                 :            : 
     929                 :            : /*
     930                 :            :  * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
     931                 :            :  * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
     932                 :            :  * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
     933                 :            :  * extension and contraction.
     934                 :            :  *
     935                 :            :  * */
     936                 :            : 
     937                 :            : int32_t
     938                 :          1 : test13(void)
     939                 :            : {
     940                 :            :         struct rte_lpm *lpm = NULL;
     941                 :            :         struct rte_lpm_config config;
     942                 :            : 
     943                 :          1 :         config.max_rules = MAX_RULES;
     944                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
     945                 :          1 :         config.flags = 0;
     946                 :            :         uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
     947                 :            :         uint8_t depth;
     948                 :            :         int32_t status = 0;
     949                 :            : 
     950                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
     951         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
     952                 :            : 
     953                 :            :         ip = RTE_IPV4(128, 0, 0, 0);
     954                 :            :         depth = 24;
     955                 :            :         next_hop_add_1 = 100;
     956                 :            : 
     957                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
     958         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     959                 :            : 
     960                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     961         [ -  + ]:          1 :         TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
     962                 :            : 
     963                 :            :         depth = 32;
     964                 :            :         next_hop_add_2 = 101;
     965                 :            : 
     966         [ +  + ]:       1001 :         for (i = 0; i < 1000; i++) {
     967                 :       1000 :                 status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
     968         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(status == 0);
     969                 :            : 
     970                 :            :                 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     971         [ -  + ]:       1000 :                 TEST_LPM_ASSERT((status == 0) &&
     972                 :            :                                 (next_hop_return == next_hop_add_2));
     973                 :            : 
     974                 :       1000 :                 status = rte_lpm_delete(lpm, ip, depth);
     975         [ -  + ]:       1000 :                 TEST_LPM_ASSERT(status == 0);
     976                 :            : 
     977                 :            :                 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     978         [ -  + ]:       1000 :                 TEST_LPM_ASSERT((status == 0) &&
     979                 :            :                                 (next_hop_return == next_hop_add_1));
     980                 :            :         }
     981                 :            : 
     982                 :            :         depth = 24;
     983                 :            : 
     984                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
     985         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
     986                 :            : 
     987                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
     988                 :          0 :         TEST_LPM_ASSERT(status == -ENOENT);
     989                 :            : 
     990                 :          1 :         rte_lpm_free(lpm);
     991                 :            : 
     992                 :          1 :         return PASS;
     993                 :            : }
     994                 :            : 
     995                 :            : /*
     996                 :            :  * For TBL8 extension exhaustion. Add 512 rules that require a tbl8 extension.
     997                 :            :  * No more tbl8 extensions will be allowed. Now add one more rule that required
     998                 :            :  * a tbl8 extension and get fail.
     999                 :            :  * */
    1000                 :            : int32_t
    1001                 :          1 : test14(void)
    1002                 :            : {
    1003                 :            : 
    1004                 :            :         /* We only use depth = 32 in the loop below so we must make sure
    1005                 :            :          * that we have enough storage for all rules at that depth*/
    1006                 :            : 
    1007                 :            :         struct rte_lpm *lpm = NULL;
    1008                 :            :         struct rte_lpm_config config;
    1009                 :            : 
    1010                 :          1 :         config.max_rules = 256 * 32;
    1011                 :          1 :         config.number_tbl8s = 512;
    1012                 :          1 :         config.flags = 0;
    1013                 :            :         uint32_t ip, next_hop_base, next_hop_return;
    1014                 :            :         uint8_t depth;
    1015                 :            :         int32_t status = 0;
    1016                 :            :         xmm_t ipx4;
    1017                 :            :         uint32_t hop[4];
    1018                 :            : 
    1019                 :            :         /* Add enough space for 256 rules for every depth */
    1020                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1021         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1022                 :            : 
    1023                 :            :         depth = 32;
    1024                 :            :         next_hop_base = 100;
    1025                 :            :         ip = RTE_IPV4(0, 0, 0, 0);
    1026                 :            : 
    1027                 :            :         /* Add 256 rules that require a tbl8 extension */
    1028         [ +  + ]:        513 :         for (; ip <= RTE_IPV4(0, 1, 255, 0); ip += 256) {
    1029                 :        512 :                 status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
    1030         [ -  + ]:        512 :                 TEST_LPM_ASSERT(status == 0);
    1031                 :            : 
    1032                 :            :                 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
    1033         [ -  + ]:        512 :                 TEST_LPM_ASSERT((status == 0) &&
    1034                 :            :                                 (next_hop_return == next_hop_base + ip));
    1035                 :            : 
    1036                 :        512 :                 ipx4 = vect_set_epi32(ip + 3, ip + 2, ip + 1, ip);
    1037                 :        512 :                 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
    1038         [ -  + ]:        512 :                 TEST_LPM_ASSERT(hop[0] == next_hop_base + ip);
    1039         [ -  + ]:        512 :                 TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
    1040         [ -  + ]:        512 :                 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
    1041         [ -  + ]:        512 :                 TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
    1042                 :            :         }
    1043                 :            : 
    1044                 :            :         /* All tbl8 extensions have been used above. Try to add one more and
    1045                 :            :          * we get a fail */
    1046                 :            :         ip = RTE_IPV4(1, 0, 0, 0);
    1047                 :            :         depth = 32;
    1048                 :            : 
    1049                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
    1050         [ -  + ]:          1 :         TEST_LPM_ASSERT(status < 0);
    1051                 :            : 
    1052                 :          1 :         rte_lpm_free(lpm);
    1053                 :            : 
    1054                 :          1 :         return PASS;
    1055                 :            : }
    1056                 :            : 
    1057                 :            : /*
    1058                 :            :  * Sequence of operations for find existing lpm table
    1059                 :            :  *
    1060                 :            :  *  - create table
    1061                 :            :  *  - find existing table: hit
    1062                 :            :  *  - find non-existing table: miss
    1063                 :            :  *
    1064                 :            :  */
    1065                 :            : int32_t
    1066                 :          1 : test15(void)
    1067                 :            : {
    1068                 :            :         struct rte_lpm *lpm = NULL, *result = NULL;
    1069                 :            :         struct rte_lpm_config config;
    1070                 :            : 
    1071                 :          1 :         config.max_rules = 256 * 32;
    1072                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
    1073                 :          1 :         config.flags = 0;
    1074                 :            : 
    1075                 :            :         /* Create lpm  */
    1076                 :          1 :         lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
    1077         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1078                 :            : 
    1079                 :            :         /* Try to find existing lpm */
    1080                 :          1 :         result = rte_lpm_find_existing("lpm_find_existing");
    1081         [ -  + ]:          1 :         TEST_LPM_ASSERT(result == lpm);
    1082                 :            : 
    1083                 :            :         /* Try to find non-existing lpm */
    1084                 :          1 :         result = rte_lpm_find_existing("lpm_find_non_existing");
    1085         [ -  + ]:          1 :         TEST_LPM_ASSERT(result == NULL);
    1086                 :            : 
    1087                 :            :         /* Cleanup. */
    1088                 :          1 :         rte_lpm_delete_all(lpm);
    1089                 :          1 :         rte_lpm_free(lpm);
    1090                 :            : 
    1091                 :          1 :         return PASS;
    1092                 :            : }
    1093                 :            : 
    1094                 :            : /*
    1095                 :            :  * test failure condition of overloading the tbl8 so no more will fit
    1096                 :            :  * Check we get an error return value in that case
    1097                 :            :  */
    1098                 :            : int32_t
    1099                 :          1 : test16(void)
    1100                 :            : {
    1101                 :            :         uint32_t ip;
    1102                 :            :         struct rte_lpm_config config;
    1103                 :            : 
    1104                 :          1 :         config.max_rules = 256 * 32;
    1105                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
    1106                 :          1 :         config.flags = 0;
    1107                 :          1 :         struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1108                 :            : 
    1109                 :            :         /* ip loops through all possibilities for top 24 bits of address */
    1110         [ +  - ]:        257 :         for (ip = 0; ip < 0xFFFFFF; ip++) {
    1111                 :            :                 /* add an entry within a different tbl8 each time, since
    1112                 :            :                  * depth >24 and the top 24 bits are different */
    1113         [ +  + ]:        257 :                 if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
    1114                 :            :                         break;
    1115                 :            :         }
    1116                 :            : 
    1117         [ -  + ]:          1 :         if (ip != NUMBER_TBL8S) {
    1118                 :            :                 printf("Error, unexpected failure with filling tbl8 groups\n");
    1119                 :            :                 printf("Failed after %u additions, expected after %u\n",
    1120                 :            :                                 (unsigned)ip, (unsigned)NUMBER_TBL8S);
    1121                 :            :         }
    1122                 :            : 
    1123                 :          1 :         rte_lpm_free(lpm);
    1124                 :          1 :         return 0;
    1125                 :            : }
    1126                 :            : 
    1127                 :            : /*
    1128                 :            :  * Test for overwriting of tbl8:
    1129                 :            :  *  - add rule /32 and lookup
    1130                 :            :  *  - add new rule /24 and lookup
    1131                 :            :  *      - add third rule /25 and lookup
    1132                 :            :  *      - lookup /32 and /24 rule to ensure the table has not been overwritten.
    1133                 :            :  */
    1134                 :            : int32_t
    1135                 :          1 : test17(void)
    1136                 :            : {
    1137                 :            :         struct rte_lpm *lpm = NULL;
    1138                 :            :         struct rte_lpm_config config;
    1139                 :            : 
    1140                 :          1 :         config.max_rules = MAX_RULES;
    1141                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
    1142                 :          1 :         config.flags = 0;
    1143                 :            :         const uint32_t ip_10_32 = RTE_IPV4(10, 10, 10, 2);
    1144                 :            :         const uint32_t ip_10_24 = RTE_IPV4(10, 10, 10, 0);
    1145                 :            :         const uint32_t ip_20_25 = RTE_IPV4(10, 10, 20, 2);
    1146                 :            :         const uint8_t d_ip_10_32 = 32,
    1147                 :            :                         d_ip_10_24 = 24,
    1148                 :            :                         d_ip_20_25 = 25;
    1149                 :            :         const uint32_t next_hop_ip_10_32 = 100,
    1150                 :            :                         next_hop_ip_10_24 = 105,
    1151                 :            :                         next_hop_ip_20_25 = 111;
    1152                 :            :         uint32_t next_hop_return = 0;
    1153                 :            :         int32_t status = 0;
    1154                 :            : 
    1155                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1156         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1157                 :            : 
    1158         [ +  - ]:          1 :         if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
    1159                 :            :                         next_hop_ip_10_32)) < 0)
    1160                 :            :                 return -1;
    1161                 :            : 
    1162                 :            :         status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
    1163                 :            :         uint32_t test_hop_10_32 = next_hop_return;
    1164                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1165         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
    1166                 :            : 
    1167         [ +  - ]:          1 :         if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
    1168                 :            :                         next_hop_ip_10_24)) < 0)
    1169                 :            :                         return -1;
    1170                 :            : 
    1171                 :            :         status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
    1172                 :            :         uint32_t test_hop_10_24 = next_hop_return;
    1173                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1174         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
    1175                 :            : 
    1176         [ +  - ]:          1 :         if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
    1177                 :            :                         next_hop_ip_20_25)) < 0)
    1178                 :            :                 return -1;
    1179                 :            : 
    1180                 :            :         status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
    1181                 :            :         uint32_t test_hop_20_25 = next_hop_return;
    1182                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1183         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
    1184                 :            : 
    1185                 :            :         if (test_hop_10_32 == test_hop_10_24) {
    1186                 :            :                 printf("Next hop return equal\n");
    1187                 :            :                 return -1;
    1188                 :            :         }
    1189                 :            : 
    1190                 :            :         if (test_hop_10_24 == test_hop_20_25) {
    1191                 :            :                 printf("Next hop return equal\n");
    1192                 :            :                 return -1;
    1193                 :            :         }
    1194                 :            : 
    1195                 :            :         status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
    1196                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1197         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
    1198                 :            : 
    1199                 :            :         status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
    1200                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1201         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
    1202                 :            : 
    1203                 :          1 :         rte_lpm_free(lpm);
    1204                 :            : 
    1205                 :          1 :         return PASS;
    1206                 :            : }
    1207                 :            : 
    1208                 :            : /*
    1209                 :            :  * Test for recycle of tbl8
    1210                 :            :  *  - step 1: add a rule with depth=28 (> 24)
    1211                 :            :  *  - step 2: add a rule with same 24-bit prefix and depth=23 (< 24)
    1212                 :            :  *  - step 3: delete the first rule
    1213                 :            :  *  - step 4: check tbl8 is freed
    1214                 :            :  *  - step 5: add a rule same as the first one (depth=28)
    1215                 :            :  *  - step 6: check same tbl8 is allocated
    1216                 :            :  *  - step 7: add a rule with same 24-bit prefix and depth=24
    1217                 :            :  *  - step 8: delete the rule (depth=28) added in step 5
    1218                 :            :  *  - step 9: check tbl8 is freed
    1219                 :            :  *  - step 10: add a rule with same 24-bit prefix and depth = 28
    1220                 :            :  *  - setp 11: check same tbl8 is allocated again
    1221                 :            :  */
    1222                 :            : int32_t
    1223                 :          1 : test18(void)
    1224                 :            : {
    1225                 :            : #define group_idx next_hop
    1226                 :            :         struct rte_lpm *lpm = NULL;
    1227                 :            :         struct rte_lpm_config config;
    1228                 :            :         uint32_t ip, next_hop;
    1229                 :            :         uint8_t depth;
    1230                 :            :         uint32_t tbl8_group_index;
    1231                 :            : 
    1232                 :          1 :         config.max_rules = MAX_RULES;
    1233                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
    1234                 :          1 :         config.flags = 0;
    1235                 :            : 
    1236                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1237         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1238                 :            : 
    1239                 :            :         ip = RTE_IPV4(192, 168, 100, 100);
    1240                 :            :         depth = 28;
    1241                 :            :         next_hop = 1;
    1242                 :          1 :         rte_lpm_add(lpm, ip, depth, next_hop);
    1243                 :            : 
    1244         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1245                 :          1 :         tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
    1246                 :            : 
    1247                 :            :         depth = 23;
    1248                 :            :         next_hop = 2;
    1249                 :          1 :         rte_lpm_add(lpm, ip, depth, next_hop);
    1250         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1251                 :            : 
    1252                 :            :         depth = 28;
    1253                 :          1 :         rte_lpm_delete(lpm, ip, depth);
    1254                 :            : 
    1255         [ -  + ]:          1 :         TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
    1256                 :            : 
    1257                 :            :         next_hop = 3;
    1258                 :          1 :         rte_lpm_add(lpm, ip, depth, next_hop);
    1259                 :            : 
    1260         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1261         [ -  + ]:          1 :         TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
    1262                 :            : 
    1263                 :            :         depth = 24;
    1264                 :            :         next_hop = 4;
    1265                 :          1 :         rte_lpm_add(lpm, ip, depth, next_hop);
    1266         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1267                 :            : 
    1268                 :            :         depth = 28;
    1269                 :          1 :         rte_lpm_delete(lpm, ip, depth);
    1270                 :            : 
    1271         [ -  + ]:          1 :         TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
    1272                 :            : 
    1273                 :            :         next_hop = 5;
    1274                 :          1 :         rte_lpm_add(lpm, ip, depth, next_hop);
    1275                 :            : 
    1276         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1277         [ -  + ]:          1 :         TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
    1278                 :            : 
    1279                 :          1 :         rte_lpm_free(lpm);
    1280                 :            : #undef group_idx
    1281                 :          1 :         return PASS;
    1282                 :            : }
    1283                 :            : 
    1284                 :            : /*
    1285                 :            :  * rte_lpm_rcu_qsbr_add positive and negative tests.
    1286                 :            :  *  - Add RCU QSBR variable to LPM
    1287                 :            :  *  - Add another RCU QSBR variable to LPM
    1288                 :            :  *  - Check returns
    1289                 :            :  */
    1290                 :            : int32_t
    1291                 :          1 : test19(void)
    1292                 :            : {
    1293                 :            :         struct rte_lpm *lpm = NULL;
    1294                 :            :         struct rte_lpm_config config;
    1295                 :            :         size_t sz;
    1296                 :            :         struct rte_rcu_qsbr *qsv;
    1297                 :            :         struct rte_rcu_qsbr *qsv2;
    1298                 :            :         int32_t status;
    1299                 :          1 :         struct rte_lpm_rcu_config rcu_cfg = {0};
    1300                 :            : 
    1301                 :          1 :         config.max_rules = MAX_RULES;
    1302                 :          1 :         config.number_tbl8s = NUMBER_TBL8S;
    1303                 :          1 :         config.flags = 0;
    1304                 :            : 
    1305                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1306         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1307                 :            : 
    1308                 :            :         /* Create RCU QSBR variable */
    1309                 :          1 :         sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
    1310                 :          1 :         qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
    1311                 :            :                                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
    1312         [ -  + ]:          1 :         TEST_LPM_ASSERT(qsv != NULL);
    1313                 :            : 
    1314                 :          1 :         status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
    1315         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1316                 :            : 
    1317                 :          1 :         rcu_cfg.v = qsv;
    1318                 :            :         /* Invalid QSBR mode */
    1319                 :          1 :         rcu_cfg.mode = 2;
    1320                 :          1 :         status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
    1321         [ -  + ]:          1 :         TEST_LPM_ASSERT(status != 0);
    1322                 :            : 
    1323                 :          1 :         rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
    1324                 :            :         /* Attach RCU QSBR to LPM table */
    1325                 :          1 :         status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
    1326         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1327                 :            : 
    1328                 :            :         /* Create and attach another RCU QSBR to LPM table */
    1329                 :          1 :         qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
    1330                 :            :                                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
    1331         [ -  + ]:          1 :         TEST_LPM_ASSERT(qsv2 != NULL);
    1332                 :            : 
    1333                 :          1 :         rcu_cfg.v = qsv2;
    1334                 :          1 :         rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
    1335                 :          1 :         status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
    1336         [ -  + ]:          1 :         TEST_LPM_ASSERT(status != 0);
    1337                 :            : 
    1338                 :          1 :         rte_lpm_free(lpm);
    1339                 :          1 :         rte_free(qsv);
    1340                 :          1 :         rte_free(qsv2);
    1341                 :            : 
    1342                 :          1 :         return PASS;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : /*
    1346                 :            :  * rte_lpm_rcu_qsbr_add DQ mode functional test.
    1347                 :            :  * Reader and writer are in the same thread in this test.
    1348                 :            :  *  - Create LPM which supports 1 tbl8 group at max
    1349                 :            :  *  - Add RCU QSBR variable to LPM
    1350                 :            :  *  - Add a rule with depth=28 (> 24)
    1351                 :            :  *  - Register a reader thread (not a real thread)
    1352                 :            :  *  - Reader lookup existing rule
    1353                 :            :  *  - Writer delete the rule
    1354                 :            :  *  - Reader lookup the rule
    1355                 :            :  *  - Writer re-add the rule (no available tbl8 group)
    1356                 :            :  *  - Reader report quiescent state and unregister
    1357                 :            :  *  - Writer re-add the rule
    1358                 :            :  *  - Reader lookup the rule
    1359                 :            :  */
    1360                 :            : int32_t
    1361                 :          1 : test20(void)
    1362                 :            : {
    1363                 :            :         struct rte_lpm *lpm = NULL;
    1364                 :            :         struct rte_lpm_config config;
    1365                 :            :         size_t sz;
    1366                 :            :         struct rte_rcu_qsbr *qsv;
    1367                 :            :         int32_t status;
    1368                 :            :         uint32_t ip, next_hop, next_hop_return;
    1369                 :            :         uint8_t depth;
    1370                 :          1 :         struct rte_lpm_rcu_config rcu_cfg = {0};
    1371                 :            : 
    1372                 :          1 :         config.max_rules = MAX_RULES;
    1373                 :          1 :         config.number_tbl8s = 1;
    1374                 :          1 :         config.flags = 0;
    1375                 :            : 
    1376                 :          1 :         lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1377         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm != NULL);
    1378                 :            : 
    1379                 :            :         /* Create RCU QSBR variable */
    1380                 :          1 :         sz = rte_rcu_qsbr_get_memsize(1);
    1381                 :          1 :         qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
    1382                 :            :                                 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
    1383         [ -  + ]:          1 :         TEST_LPM_ASSERT(qsv != NULL);
    1384                 :            : 
    1385                 :          1 :         status = rte_rcu_qsbr_init(qsv, 1);
    1386         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1387                 :            : 
    1388                 :          1 :         rcu_cfg.v = qsv;
    1389                 :          1 :         rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
    1390                 :            :         /* Attach RCU QSBR to LPM table */
    1391                 :          1 :         status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
    1392         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1393                 :            : 
    1394                 :            :         ip = RTE_IPV4(192, 0, 2, 100);
    1395                 :            :         depth = 28;
    1396                 :            :         next_hop = 1;
    1397                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop);
    1398         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1399         [ -  + ]:          1 :         TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
    1400                 :            : 
    1401                 :            :         /* Register pseudo reader */
    1402                 :          1 :         status = rte_rcu_qsbr_thread_register(qsv, 0);
    1403         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1404                 :            :         rte_rcu_qsbr_thread_online(qsv, 0);
    1405                 :            : 
    1406                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
    1407                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1408         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop);
    1409                 :            : 
    1410                 :            :         /* Writer update */
    1411                 :          1 :         status = rte_lpm_delete(lpm, ip, depth);
    1412         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1413         [ -  + ]:          1 :         TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid);
    1414                 :            : 
    1415                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
    1416                 :          0 :         TEST_LPM_ASSERT(status != 0);
    1417                 :            : 
    1418                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop);
    1419         [ -  + ]:          1 :         TEST_LPM_ASSERT(status != 0);
    1420                 :            : 
    1421                 :            :         /* Reader quiescent */
    1422                 :            :         rte_rcu_qsbr_quiescent(qsv, 0);
    1423                 :            : 
    1424                 :          1 :         status = rte_lpm_add(lpm, ip, depth, next_hop);
    1425         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1426                 :            : 
    1427                 :            :         rte_rcu_qsbr_thread_offline(qsv, 0);
    1428                 :          1 :         status = rte_rcu_qsbr_thread_unregister(qsv, 0);
    1429         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1430                 :            : 
    1431                 :            :         status = rte_lpm_lookup(lpm, ip, &next_hop_return);
    1432                 :          0 :         TEST_LPM_ASSERT(status == 0);
    1433         [ -  + ]:          1 :         TEST_LPM_ASSERT(next_hop_return == next_hop);
    1434                 :            : 
    1435                 :          1 :         rte_lpm_free(lpm);
    1436                 :          1 :         rte_free(qsv);
    1437                 :            : 
    1438                 :          1 :         return PASS;
    1439                 :            : }
    1440                 :            : 
    1441                 :            : static struct rte_lpm *g_lpm;
    1442                 :            : static struct rte_rcu_qsbr *g_v;
    1443                 :            : static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
    1444                 :            : static volatile uint8_t writer_done;
    1445                 :            : /* Report quiescent state interval every 1024 lookups. Larger critical
    1446                 :            :  * sections in reader will result in writer polling multiple times.
    1447                 :            :  */
    1448                 :            : #define QSBR_REPORTING_INTERVAL 1024
    1449                 :            : #define WRITER_ITERATIONS       512
    1450                 :            : 
    1451                 :            : /*
    1452                 :            :  * Reader thread using rte_lpm data structure with RCU.
    1453                 :            :  */
    1454                 :            : static int
    1455                 :          1 : test_lpm_rcu_qsbr_reader(void *arg)
    1456                 :            : {
    1457                 :            :         int i;
    1458                 :            :         uint32_t next_hop_return = 0;
    1459                 :            : 
    1460                 :            :         RTE_SET_USED(arg);
    1461                 :            :         /* Register this thread to report quiescent state */
    1462                 :          1 :         rte_rcu_qsbr_thread_register(g_v, 0);
    1463                 :          1 :         rte_rcu_qsbr_thread_online(g_v, 0);
    1464                 :            : 
    1465                 :            :         do {
    1466                 :            :                 for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
    1467                 :            :                         rte_lpm_lookup(g_lpm, g_ip, &next_hop_return);
    1468                 :            : 
    1469                 :            :                 /* Update quiescent state */
    1470         [ +  + ]:     186677 :                 rte_rcu_qsbr_quiescent(g_v, 0);
    1471         [ +  + ]:     186677 :         } while (!writer_done);
    1472                 :            : 
    1473                 :          1 :         rte_rcu_qsbr_thread_offline(g_v, 0);
    1474                 :          1 :         rte_rcu_qsbr_thread_unregister(g_v, 0);
    1475                 :            : 
    1476                 :          1 :         return 0;
    1477                 :            : }
    1478                 :            : 
    1479                 :            : /*
    1480                 :            :  * rte_lpm_rcu_qsbr_add sync mode functional test.
    1481                 :            :  * 1 Reader and 1 writer. They cannot be in the same thread in this test.
    1482                 :            :  *  - Create LPM which supports 1 tbl8 group at max
    1483                 :            :  *  - Add RCU QSBR variable with sync mode to LPM
    1484                 :            :  *  - Register a reader thread. Reader keeps looking up a specific rule.
    1485                 :            :  *  - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
    1486                 :            :  */
    1487                 :            : int32_t
    1488                 :          1 : test21(void)
    1489                 :            : {
    1490                 :            :         struct rte_lpm_config config;
    1491                 :            :         size_t sz;
    1492                 :            :         int32_t status;
    1493                 :            :         uint32_t i, next_hop;
    1494                 :            :         uint8_t depth;
    1495                 :          1 :         struct rte_lpm_rcu_config rcu_cfg = {0};
    1496                 :            : 
    1497         [ -  + ]:          1 :         if (rte_lcore_count() < 2) {
    1498                 :            :                 printf("Not enough cores for %s, expecting at least 2\n",
    1499                 :            :                         __func__);
    1500                 :          0 :                 return TEST_SKIPPED;
    1501                 :            :         }
    1502                 :            : 
    1503                 :          1 :         config.max_rules = MAX_RULES;
    1504                 :          1 :         config.number_tbl8s = 1;
    1505                 :          1 :         config.flags = 0;
    1506                 :            : 
    1507                 :          1 :         g_lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
    1508         [ -  + ]:          1 :         TEST_LPM_ASSERT(g_lpm != NULL);
    1509                 :            : 
    1510                 :            :         /* Create RCU QSBR variable */
    1511                 :          1 :         sz = rte_rcu_qsbr_get_memsize(1);
    1512                 :          1 :         g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
    1513                 :            :                                 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
    1514         [ -  + ]:          1 :         TEST_LPM_ASSERT(g_v != NULL);
    1515                 :            : 
    1516                 :          1 :         status = rte_rcu_qsbr_init(g_v, 1);
    1517         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1518                 :            : 
    1519                 :          1 :         rcu_cfg.v = g_v;
    1520                 :          1 :         rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
    1521                 :            :         /* Attach RCU QSBR to LPM table */
    1522                 :          1 :         status = rte_lpm_rcu_qsbr_add(g_lpm, &rcu_cfg);
    1523         [ -  + ]:          1 :         TEST_LPM_ASSERT(status == 0);
    1524                 :            : 
    1525                 :          1 :         writer_done = 0;
    1526                 :            :         /* Launch reader thread */
    1527                 :          1 :         rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL,
    1528                 :            :                                 rte_get_next_lcore(-1, 1, 0));
    1529                 :            : 
    1530                 :            :         depth = 28;
    1531                 :            :         next_hop = 1;
    1532                 :          1 :         status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
    1533         [ -  + ]:          1 :         if (status != 0) {
    1534                 :            :                 printf("%s: Failed to add rule\n", __func__);
    1535                 :          0 :                 goto error;
    1536                 :            :         }
    1537                 :            : 
    1538                 :            :         /* Writer update */
    1539         [ +  + ]:        513 :         for (i = 0; i < WRITER_ITERATIONS; i++) {
    1540                 :        512 :                 status = rte_lpm_delete(g_lpm, g_ip, depth);
    1541         [ -  + ]:        512 :                 if (status != 0) {
    1542                 :            :                         printf("%s: Failed to delete rule at iteration %d\n",
    1543                 :            :                                 __func__, i);
    1544                 :          0 :                         goto error;
    1545                 :            :                 }
    1546                 :            : 
    1547                 :        512 :                 status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
    1548         [ -  + ]:        512 :                 if (status != 0) {
    1549                 :            :                         printf("%s: Failed to add rule at iteration %d\n",
    1550                 :            :                                 __func__, i);
    1551                 :          0 :                         goto error;
    1552                 :            :                 }
    1553                 :            :         }
    1554                 :            : 
    1555                 :          1 : error:
    1556                 :          1 :         writer_done = 1;
    1557                 :            :         /* Wait until reader exited. */
    1558                 :          1 :         rte_eal_mp_wait_lcore();
    1559                 :            : 
    1560                 :          1 :         rte_lpm_free(g_lpm);
    1561                 :          1 :         rte_free(g_v);
    1562                 :            : 
    1563         [ -  + ]:          1 :         return (status == 0) ? PASS : -1;
    1564                 :            : }
    1565                 :            : 
    1566                 :            : /*
    1567                 :            :  * Do all unit tests.
    1568                 :            :  */
    1569                 :            : 
    1570                 :            : static int
    1571                 :          1 : test_lpm(void)
    1572                 :            : {
    1573                 :            :         unsigned i;
    1574                 :            :         int status, global_status = 0;
    1575                 :            : 
    1576         [ +  + ]:         23 :         for (i = 0; i < RTE_DIM(tests); i++) {
    1577                 :         22 :                 status = tests[i]();
    1578         [ -  + ]:         22 :                 if (status < 0) {
    1579                 :            :                         printf("ERROR: LPM Test %u: FAIL\n", i);
    1580                 :            :                         global_status = status;
    1581                 :            :                 }
    1582                 :            :         }
    1583                 :            : 
    1584                 :          1 :         return global_status;
    1585                 :            : }
    1586                 :            : 
    1587                 :        251 : REGISTER_FAST_TEST(lpm_autotest, true, true, test_lpm);

Generated by: LCOV version 1.14