LCOV - code coverage report
Current view: top level - app/test - test_fib.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 234 247 94.7 %
Date: 2025-03-01 20:23:48 Functions: 14 16 87.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 92 162 56.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
       3                 :            :  * Copyright(c) 2019 Intel Corporation
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <stdio.h>
       7                 :            : #include <stdint.h>
       8                 :            : #include <stdlib.h>
       9                 :            : 
      10                 :            : #include <rte_ip.h>
      11                 :            : #include <rte_log.h>
      12                 :            : #include <rte_fib.h>
      13                 :            : #include <rte_malloc.h>
      14                 :            : 
      15                 :            : #include "test.h"
      16                 :            : 
      17                 :            : typedef int32_t (*rte_fib_test)(void);
      18                 :            : 
      19                 :            : static int32_t test_create_invalid(void);
      20                 :            : static int32_t test_multiple_create(void);
      21                 :            : static int32_t test_free_null(void);
      22                 :            : static int32_t test_add_del_invalid(void);
      23                 :            : static int32_t test_get_invalid(void);
      24                 :            : static int32_t test_lookup(void);
      25                 :            : static int32_t test_invalid_rcu(void);
      26                 :            : static int32_t test_fib_rcu_sync_rw(void);
      27                 :            : 
      28                 :            : #define MAX_ROUTES      (1 << 16)
      29                 :            : #define MAX_TBL8        (1 << 15)
      30                 :            : 
      31                 :            : /*
      32                 :            :  * Check that rte_fib_create fails gracefully for incorrect user input
      33                 :            :  * arguments
      34                 :            :  */
      35                 :            : int32_t
      36                 :          1 : test_create_invalid(void)
      37                 :            : {
      38                 :            :         struct rte_fib *fib = NULL;
      39                 :          1 :         struct rte_fib_conf config = { 0 };
      40                 :            : 
      41                 :          1 :         config.max_routes = MAX_ROUTES;
      42                 :            :         config.rib_ext_sz = 0;
      43                 :            :         config.default_nh = 0;
      44                 :            :         config.type = RTE_FIB_DUMMY;
      45                 :            : 
      46                 :            :         /* rte_fib_create: fib name == NULL */
      47                 :          1 :         fib = rte_fib_create(NULL, SOCKET_ID_ANY, &config);
      48         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      49                 :            :                 "Call succeeded with invalid parameters\n");
      50                 :            : 
      51                 :            :         /* rte_fib_create: config == NULL */
      52                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, NULL);
      53         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      54                 :            :                 "Call succeeded with invalid parameters\n");
      55                 :            : 
      56                 :            :         /* socket_id < -1 is invalid */
      57                 :          1 :         fib = rte_fib_create(__func__, -2, &config);
      58         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      59                 :            :                 "Call succeeded with invalid parameters\n");
      60                 :            : 
      61                 :            :         /* rte_fib_create: max_routes = 0 */
      62                 :          1 :         config.max_routes = 0;
      63                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
      64         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      65                 :            :                 "Call succeeded with invalid parameters\n");
      66                 :          1 :         config.max_routes = MAX_ROUTES;
      67                 :            : 
      68                 :          1 :         config.type = RTE_FIB_DIR24_8 + 1;
      69                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
      70         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      71                 :            :                 "Call succeeded with invalid parameters\n");
      72                 :            : 
      73                 :          1 :         config.type = RTE_FIB_DIR24_8;
      74                 :          1 :         config.dir24_8.num_tbl8 = MAX_TBL8;
      75                 :            : 
      76                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B + 1;
      77                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
      78         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      79                 :            :                 "Call succeeded with invalid parameters\n");
      80                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
      81                 :            : 
      82                 :          1 :         config.dir24_8.num_tbl8 = 0;
      83                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
      84         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib == NULL,
      85                 :            :                 "Call succeeded with invalid parameters\n");
      86                 :            : 
      87                 :            :         return TEST_SUCCESS;
      88                 :            : }
      89                 :            : 
      90                 :            : /*
      91                 :            :  * Create fib table then delete fib table 10 times
      92                 :            :  * Use a slightly different rules size each time
      93                 :            :  */
      94                 :            : int32_t
      95                 :          0 : test_multiple_create(void)
      96                 :            : {
      97                 :            :         struct rte_fib *fib = NULL;
      98                 :          0 :         struct rte_fib_conf config = { 0 };
      99                 :            :         int32_t i;
     100                 :            : 
     101                 :            :         config.rib_ext_sz = 0;
     102                 :            :         config.default_nh = 0;
     103                 :            :         config.type = RTE_FIB_DUMMY;
     104                 :            : 
     105         [ #  # ]:          0 :         for (i = 0; i < 100; i++) {
     106                 :          0 :                 config.max_routes = MAX_ROUTES - i;
     107                 :          0 :                 fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     108         [ #  # ]:          0 :                 RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     109                 :          0 :                 rte_fib_free(fib);
     110                 :            :         }
     111                 :            :         /* Can not test free so return success */
     112                 :            :         return TEST_SUCCESS;
     113                 :            : }
     114                 :            : 
     115                 :            : /*
     116                 :            :  * Call rte_fib_free for NULL pointer user input. Note: free has no return and
     117                 :            :  * therefore it is impossible to check for failure but this test is added to
     118                 :            :  * increase function coverage metrics and to validate that freeing null does
     119                 :            :  * not crash.
     120                 :            :  */
     121                 :            : int32_t
     122                 :          1 : test_free_null(void)
     123                 :            : {
     124                 :            :         struct rte_fib *fib = NULL;
     125                 :          1 :         struct rte_fib_conf config = { 0 };
     126                 :            : 
     127                 :          1 :         config.max_routes = MAX_ROUTES;
     128                 :            :         config.rib_ext_sz = 0;
     129                 :            :         config.default_nh = 0;
     130                 :            :         config.type = RTE_FIB_DUMMY;
     131                 :            : 
     132                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     133         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     134                 :            : 
     135                 :          1 :         rte_fib_free(fib);
     136                 :          1 :         rte_fib_free(NULL);
     137                 :          1 :         return TEST_SUCCESS;
     138                 :            : }
     139                 :            : 
     140                 :            : /*
     141                 :            :  * Check that rte_fib_add and rte_fib_delete fails gracefully
     142                 :            :  * for incorrect user input arguments
     143                 :            :  */
     144                 :            : int32_t
     145                 :          1 : test_add_del_invalid(void)
     146                 :            : {
     147                 :            :         struct rte_fib *fib = NULL;
     148                 :          1 :         struct rte_fib_conf config = { 0 };
     149                 :            :         uint64_t nh = 100;
     150                 :            :         uint32_t ip = RTE_IPV4(0, 0, 0, 0);
     151                 :            :         int ret;
     152                 :            :         uint8_t depth = 24;
     153                 :            : 
     154                 :          1 :         config.max_routes = MAX_ROUTES;
     155                 :            :         config.rib_ext_sz = 0;
     156                 :            :         config.default_nh = 0;
     157                 :            :         config.type = RTE_FIB_DUMMY;
     158                 :            : 
     159                 :            :         /* rte_fib_add: fib == NULL */
     160                 :          1 :         ret = rte_fib_add(NULL, ip, depth, nh);
     161         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret < 0,
     162                 :            :                 "Call succeeded with invalid parameters\n");
     163                 :            : 
     164                 :            :         /* rte_fib_delete: fib == NULL */
     165                 :          1 :         ret = rte_fib_delete(NULL, ip, depth);
     166         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret < 0,
     167                 :            :                 "Call succeeded with invalid parameters\n");
     168                 :            : 
     169                 :            :         /*Create valid fib to use in rest of test. */
     170                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     171         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     172                 :            : 
     173                 :            :         /* rte_fib_add: depth > RTE_FIB_MAXDEPTH */
     174                 :          1 :         ret = rte_fib_add(fib, ip, RTE_FIB_MAXDEPTH + 1, nh);
     175         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret < 0,
     176                 :            :                 "Call succeeded with invalid parameters\n");
     177                 :            : 
     178                 :            :         /* rte_fib_delete: depth > RTE_FIB_MAXDEPTH */
     179                 :          1 :         ret = rte_fib_delete(fib, ip, RTE_FIB_MAXDEPTH + 1);
     180         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret < 0,
     181                 :            :                 "Call succeeded with invalid parameters\n");
     182                 :            : 
     183                 :          1 :         rte_fib_free(fib);
     184                 :            : 
     185                 :          1 :         return TEST_SUCCESS;
     186                 :            : }
     187                 :            : 
     188                 :            : /*
     189                 :            :  * Check that rte_fib_get_dp and rte_fib_get_rib fails gracefully
     190                 :            :  * for incorrect user input arguments
     191                 :            :  */
     192                 :            : int32_t
     193                 :          1 : test_get_invalid(void)
     194                 :            : {
     195                 :            :         void *p;
     196                 :            : 
     197                 :          1 :         p = rte_fib_get_dp(NULL);
     198         [ -  + ]:          1 :         RTE_TEST_ASSERT(p == NULL,
     199                 :            :                 "Call succeeded with invalid parameters\n");
     200                 :            : 
     201                 :          1 :         p = rte_fib_get_rib(NULL);
     202         [ -  + ]:          1 :         RTE_TEST_ASSERT(p == NULL,
     203                 :            :                 "Call succeeded with invalid parameters\n");
     204                 :            : 
     205                 :            :         return TEST_SUCCESS;
     206                 :            : }
     207                 :            : 
     208                 :            : /*
     209                 :            :  * Add routes for one supernet with all possible depths and do lookup
     210                 :            :  * on each step
     211                 :            :  * After delete routes with doing lookup on each step
     212                 :            :  */
     213                 :            : static int
     214                 :        315 : lookup_and_check_asc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
     215                 :            :         uint32_t ip_missing, uint64_t def_nh, uint32_t n)
     216                 :            : {
     217                 :            :         uint64_t nh_arr[RTE_FIB_MAXDEPTH];
     218                 :            :         int ret;
     219                 :            :         uint32_t i = 0;
     220                 :            : 
     221                 :        315 :         ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
     222         [ -  + ]:        315 :         RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
     223                 :            : 
     224         [ +  + ]:       5590 :         for (; i <= RTE_FIB_MAXDEPTH - n; i++)
     225         [ -  + ]:       5275 :                 RTE_TEST_ASSERT(nh_arr[i] == n,
     226                 :            :                         "Failed to get proper nexthop\n");
     227                 :            : 
     228         [ +  + ]:       5120 :         for (; i < RTE_FIB_MAXDEPTH; i++)
     229         [ -  + ]:       4805 :                 RTE_TEST_ASSERT(nh_arr[i] == --n,
     230                 :            :                         "Failed to get proper nexthop\n");
     231                 :            : 
     232                 :        315 :         ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
     233   [ +  -  -  + ]:        315 :         RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
     234                 :            :                 "Failed to get proper nexthop\n");
     235                 :            : 
     236                 :            :         return TEST_SUCCESS;
     237                 :            : }
     238                 :            : 
     239                 :            : static int
     240                 :        330 : lookup_and_check_desc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
     241                 :            :         uint32_t ip_missing, uint64_t def_nh, uint32_t n)
     242                 :            : {
     243                 :            :         uint64_t nh_arr[RTE_FIB_MAXDEPTH];
     244                 :            :         int ret;
     245                 :            :         uint32_t i = 0;
     246                 :            : 
     247                 :        330 :         ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
     248         [ -  + ]:        330 :         RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
     249                 :            : 
     250         [ +  + ]:       5450 :         for (; i < n; i++)
     251         [ -  + ]:       5120 :                 RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB_MAXDEPTH - i,
     252                 :            :                         "Failed to get proper nexthop\n");
     253                 :            : 
     254         [ +  + ]:       5770 :         for (; i < RTE_FIB_MAXDEPTH; i++)
     255         [ -  + ]:       5440 :                 RTE_TEST_ASSERT(nh_arr[i] == def_nh,
     256                 :            :                         "Failed to get proper nexthop\n");
     257                 :            : 
     258                 :        330 :         ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
     259   [ +  -  -  + ]:        330 :         RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
     260                 :            :                 "Failed to get proper nexthop\n");
     261                 :            : 
     262                 :            :         return TEST_SUCCESS;
     263                 :            : }
     264                 :            : 
     265                 :            : static int
     266                 :          5 : check_fib(struct rte_fib *fib)
     267                 :            : {
     268                 :            :         uint64_t def_nh = 100;
     269                 :            :         uint32_t ip_arr[RTE_FIB_MAXDEPTH];
     270                 :            :         uint32_t ip_add = RTE_IPV4(128, 0, 0, 0);
     271                 :            :         uint32_t i, ip_missing = RTE_IPV4(127, 255, 255, 255);
     272                 :            :         int ret;
     273                 :            : 
     274         [ +  + ]:        165 :         for (i = 0; i < RTE_FIB_MAXDEPTH; i++)
     275                 :        160 :                 ip_arr[i] = ip_add + (1ULL << i) - 1;
     276                 :            : 
     277                 :          5 :         ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
     278         [ -  + ]:          5 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     279                 :            : 
     280         [ +  + ]:        165 :         for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
     281                 :        160 :                 ret = rte_fib_add(fib, ip_add, i, i);
     282         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
     283                 :        160 :                 ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
     284                 :            :                                 def_nh, i);
     285         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     286                 :            :         }
     287                 :            : 
     288         [ +  + ]:        160 :         for (i = RTE_FIB_MAXDEPTH; i > 1; i--) {
     289                 :        155 :                 ret = rte_fib_delete(fib, ip_add, i);
     290         [ -  + ]:        155 :                 RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
     291                 :        155 :                 ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
     292                 :            :                         def_nh, i - 1);
     293                 :            : 
     294         [ -  + ]:        155 :                 RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     295                 :            :         }
     296                 :          5 :         ret = rte_fib_delete(fib, ip_add, i);
     297         [ -  + ]:          5 :         RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
     298                 :          5 :         ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
     299         [ -  + ]:          5 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     300                 :            : 
     301         [ +  + ]:        165 :         for (i = 0; i < RTE_FIB_MAXDEPTH; i++) {
     302                 :        160 :                 ret = rte_fib_add(fib, ip_add, RTE_FIB_MAXDEPTH - i,
     303                 :        160 :                         RTE_FIB_MAXDEPTH - i);
     304         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
     305                 :        160 :                 ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
     306                 :            :                         def_nh, i + 1);
     307         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     308                 :            :         }
     309                 :            : 
     310         [ +  + ]:        165 :         for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
     311                 :        160 :                 ret = rte_fib_delete(fib, ip_add, i);
     312         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
     313                 :        160 :                 ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
     314                 :            :                         RTE_FIB_MAXDEPTH - i);
     315         [ -  + ]:        160 :                 RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
     316                 :            :         }
     317                 :            : 
     318                 :            :         return TEST_SUCCESS;
     319                 :            : }
     320                 :            : 
     321                 :            : int32_t
     322                 :          1 : test_lookup(void)
     323                 :            : {
     324                 :            :         struct rte_fib *fib = NULL;
     325                 :          1 :         struct rte_fib_conf config = { 0 };
     326                 :            :         uint64_t def_nh = 100;
     327                 :            :         int ret;
     328                 :            : 
     329                 :          1 :         config.max_routes = MAX_ROUTES;
     330                 :            :         config.rib_ext_sz = 0;
     331                 :          1 :         config.default_nh = def_nh;
     332                 :            :         config.type = RTE_FIB_DUMMY;
     333                 :            : 
     334                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     335         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     336                 :          1 :         ret = check_fib(fib);
     337         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS,
     338                 :            :                 "Check_fib fails for DUMMY type\n");
     339                 :          1 :         rte_fib_free(fib);
     340                 :            : 
     341                 :          1 :         config.type = RTE_FIB_DIR24_8;
     342                 :            : 
     343                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_1B;
     344                 :          1 :         config.dir24_8.num_tbl8 = 127;
     345                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     346         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     347                 :          1 :         ret = check_fib(fib);
     348         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS,
     349                 :            :                 "Check_fib fails for DIR24_8_1B type\n");
     350                 :          1 :         rte_fib_free(fib);
     351                 :            : 
     352                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_2B;
     353                 :          1 :         config.dir24_8.num_tbl8 = MAX_TBL8 - 1;
     354                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     355         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     356                 :          1 :         ret = check_fib(fib);
     357         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS,
     358                 :            :                 "Check_fib fails for DIR24_8_2B type\n");
     359                 :          1 :         rte_fib_free(fib);
     360                 :            : 
     361                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
     362                 :          1 :         config.dir24_8.num_tbl8 = MAX_TBL8;
     363                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     364         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     365                 :          1 :         ret = check_fib(fib);
     366         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS,
     367                 :            :                 "Check_fib fails for DIR24_8_4B type\n");
     368                 :          1 :         rte_fib_free(fib);
     369                 :            : 
     370                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
     371                 :          1 :         config.dir24_8.num_tbl8 = MAX_TBL8;
     372                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     373         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     374                 :          1 :         ret = check_fib(fib);
     375         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == TEST_SUCCESS,
     376                 :            :                 "Check_fib fails for DIR24_8_8B type\n");
     377                 :          1 :         rte_fib_free(fib);
     378                 :            : 
     379                 :          1 :         return TEST_SUCCESS;
     380                 :            : }
     381                 :            : 
     382                 :            : /*
     383                 :            :  * rte_fib_rcu_qsbr_add positive and negative tests.
     384                 :            :  *  - Add RCU QSBR variable to FIB
     385                 :            :  *  - Add another RCU QSBR variable to FIB
     386                 :            :  *  - Check returns
     387                 :            :  */
     388                 :            : int32_t
     389                 :          1 : test_invalid_rcu(void)
     390                 :            : {
     391                 :            :         struct rte_fib *fib = NULL;
     392                 :          1 :         struct rte_fib_conf config = { 0 };
     393                 :            :         size_t sz;
     394                 :            :         struct rte_rcu_qsbr *qsv;
     395                 :            :         struct rte_rcu_qsbr *qsv2;
     396                 :            :         int32_t status;
     397                 :          1 :         struct rte_fib_rcu_config rcu_cfg = {0};
     398                 :            :         uint64_t def_nh = 100;
     399                 :            : 
     400                 :          1 :         config.max_routes = MAX_ROUTES;
     401                 :            :         config.rib_ext_sz = 0;
     402                 :          1 :         config.default_nh = def_nh;
     403                 :            : 
     404                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     405         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     406                 :            : 
     407                 :            :         /* Create RCU QSBR variable */
     408                 :          1 :         sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
     409                 :          1 :         qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
     410                 :            :                 SOCKET_ID_ANY);
     411         [ -  + ]:          1 :         RTE_TEST_ASSERT(qsv != NULL, "Can not allocate memory for RCU\n");
     412                 :            : 
     413                 :          1 :         status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
     414         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == 0, "Can not initialize RCU\n");
     415                 :            : 
     416                 :          1 :         rcu_cfg.v = qsv;
     417                 :            : 
     418                 :            :         /* adding rcu to RTE_FIB_DUMMY FIB type */
     419                 :          1 :         config.type = RTE_FIB_DUMMY;
     420                 :          1 :         rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
     421                 :          1 :         status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
     422         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == -ENOTSUP,
     423                 :            :                 "rte_fib_rcu_qsbr_add returned wrong error status when called with DUMMY type FIB\n");
     424                 :          1 :         rte_fib_free(fib);
     425                 :            : 
     426                 :          1 :         config.type = RTE_FIB_DIR24_8;
     427                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
     428                 :          1 :         config.dir24_8.num_tbl8 = MAX_TBL8;
     429                 :          1 :         fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     430         [ -  + ]:          1 :         RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
     431                 :            : 
     432                 :            :         /* Call rte_fib_rcu_qsbr_add without fib or config */
     433                 :          1 :         status = rte_fib_rcu_qsbr_add(NULL, &rcu_cfg);
     434         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == -EINVAL, "RCU added without fib\n");
     435                 :          1 :         status = rte_fib_rcu_qsbr_add(fib, NULL);
     436         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == -EINVAL, "RCU added without config\n");
     437                 :            : 
     438                 :            :         /* Invalid QSBR mode */
     439                 :          1 :         rcu_cfg.mode = 2;
     440                 :          1 :         status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
     441         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == -EINVAL, "RCU added with incorrect mode\n");
     442                 :            : 
     443                 :          1 :         rcu_cfg.mode = RTE_FIB_QSBR_MODE_DQ;
     444                 :            : 
     445                 :            :         /* Attach RCU QSBR to FIB to check for double attach */
     446                 :          1 :         status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
     447         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == 0, "Can not attach RCU to FIB\n");
     448                 :            : 
     449                 :            :         /* Create and attach another RCU QSBR to FIB table */
     450                 :          1 :         qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
     451                 :            :                 SOCKET_ID_ANY);
     452         [ -  + ]:          1 :         RTE_TEST_ASSERT(qsv2 != NULL, "Can not allocate memory for RCU\n");
     453                 :            : 
     454                 :          1 :         rcu_cfg.v = qsv2;
     455                 :          1 :         rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
     456                 :          1 :         status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
     457         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == -EEXIST, "Secondary RCU was mistakenly attached\n");
     458                 :            : 
     459                 :          1 :         rte_fib_free(fib);
     460                 :          1 :         rte_free(qsv);
     461                 :          1 :         rte_free(qsv2);
     462                 :            : 
     463                 :          1 :         return TEST_SUCCESS;
     464                 :            : }
     465                 :            : 
     466                 :            : static struct rte_fib *g_fib;
     467                 :            : static struct rte_rcu_qsbr *g_v;
     468                 :            : static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
     469                 :            : static volatile uint8_t writer_done;
     470                 :            : /* Report quiescent state interval every 1024 lookups. Larger critical
     471                 :            :  * sections in reader will result in writer polling multiple times.
     472                 :            :  */
     473                 :            : #define QSBR_REPORTING_INTERVAL 1024
     474                 :            : #define WRITER_ITERATIONS       512
     475                 :            : 
     476                 :            : /*
     477                 :            :  * Reader thread using rte_fib data structure with RCU.
     478                 :            :  */
     479                 :            : static int
     480                 :          1 : test_fib_rcu_qsbr_reader(void *arg)
     481                 :            : {
     482                 :            :         int i;
     483                 :          1 :         uint64_t next_hop_return = 0;
     484                 :            : 
     485                 :            :         RTE_SET_USED(arg);
     486                 :            :         /* Register this thread to report quiescent state */
     487                 :          1 :         rte_rcu_qsbr_thread_register(g_v, 0);
     488                 :          1 :         rte_rcu_qsbr_thread_online(g_v, 0);
     489                 :            : 
     490                 :            :         do {
     491         [ +  + ]:     602700 :                 for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
     492                 :     602112 :                         rte_fib_lookup_bulk(g_fib, &g_ip, &next_hop_return, 1);
     493                 :            : 
     494                 :            :                 /* Update quiescent state */
     495         [ +  + ]:        588 :                 rte_rcu_qsbr_quiescent(g_v, 0);
     496         [ +  + ]:        588 :         } while (!writer_done);
     497                 :            : 
     498                 :          1 :         rte_rcu_qsbr_thread_offline(g_v, 0);
     499                 :          1 :         rte_rcu_qsbr_thread_unregister(g_v, 0);
     500                 :            : 
     501                 :          1 :         return 0;
     502                 :            : }
     503                 :            : 
     504                 :            : /*
     505                 :            :  * rte_fib_rcu_qsbr_add sync mode functional test.
     506                 :            :  * 1 Reader and 1 writer. They cannot be in the same thread in this test.
     507                 :            :  *  - Create FIB which supports 1 tbl8 group at max
     508                 :            :  *  - Add RCU QSBR variable with sync mode to FIB
     509                 :            :  *  - Register a reader thread. Reader keeps looking up a specific rule.
     510                 :            :  *  - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
     511                 :            :  */
     512                 :            : int32_t
     513                 :          1 : test_fib_rcu_sync_rw(void)
     514                 :            : {
     515                 :          1 :         struct rte_fib_conf config = { 0 };
     516                 :            :         size_t sz;
     517                 :            :         int32_t status;
     518                 :            :         uint32_t i, next_hop;
     519                 :            :         uint8_t depth;
     520                 :          1 :         struct rte_fib_rcu_config rcu_cfg = {0};
     521                 :            :         uint64_t def_nh = 100;
     522                 :            : 
     523         [ -  + ]:          1 :         if (rte_lcore_count() < 2) {
     524                 :            :                 printf("Not enough cores for %s, expecting at least 2\n", __func__);
     525                 :          0 :                 return TEST_SKIPPED;
     526                 :            :         }
     527                 :            : 
     528                 :          1 :         config.max_routes = MAX_ROUTES;
     529                 :          1 :         config.rib_ext_sz = 0;
     530                 :          1 :         config.default_nh = def_nh;
     531                 :          1 :         config.type = RTE_FIB_DIR24_8;
     532                 :          1 :         config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
     533                 :          1 :         config.dir24_8.num_tbl8 = 1;
     534                 :            : 
     535                 :          1 :         g_fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
     536         [ -  + ]:          1 :         RTE_TEST_ASSERT(g_fib != NULL, "Failed to create FIB\n");
     537                 :            : 
     538                 :            :         /* Create RCU QSBR variable */
     539                 :          1 :         sz = rte_rcu_qsbr_get_memsize(1);
     540                 :          1 :         g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
     541                 :            :                 SOCKET_ID_ANY);
     542         [ -  + ]:          1 :         RTE_TEST_ASSERT(g_v != NULL, "Can not allocate memory for RCU\n");
     543                 :            : 
     544                 :          1 :         status = rte_rcu_qsbr_init(g_v, 1);
     545         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == 0, "Can not initialize RCU\n");
     546                 :            : 
     547                 :          1 :         rcu_cfg.v = g_v;
     548                 :          1 :         rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
     549                 :            :         /* Attach RCU QSBR to FIB table */
     550                 :          1 :         status = rte_fib_rcu_qsbr_add(g_fib, &rcu_cfg);
     551         [ -  + ]:          1 :         RTE_TEST_ASSERT(status == 0, "Can not attach RCU to FIB\n");
     552                 :            : 
     553                 :          1 :         writer_done = 0;
     554                 :            :         /* Launch reader thread */
     555                 :          1 :         rte_eal_remote_launch(test_fib_rcu_qsbr_reader, NULL, rte_get_next_lcore(-1, 1, 0));
     556                 :            : 
     557                 :            :         depth = 28;
     558                 :            :         next_hop = 1;
     559                 :          1 :         status = rte_fib_add(g_fib, g_ip, depth, next_hop);
     560         [ -  + ]:          1 :         if (status != 0) {
     561                 :            :                 printf("%s: Failed to add rule\n", __func__);
     562                 :          0 :                 goto error;
     563                 :            :         }
     564                 :            : 
     565                 :            :         /* Writer update */
     566         [ +  + ]:        513 :         for (i = 0; i < WRITER_ITERATIONS; i++) {
     567                 :        512 :                 status = rte_fib_delete(g_fib, g_ip, depth);
     568         [ -  + ]:        512 :                 if (status != 0) {
     569                 :            :                         printf("%s: Failed to delete rule at iteration %d\n", __func__, i);
     570                 :          0 :                         goto error;
     571                 :            :                 }
     572                 :            : 
     573                 :        512 :                 status = rte_fib_add(g_fib, g_ip, depth, next_hop);
     574         [ -  + ]:        512 :                 if (status != 0) {
     575                 :            :                         printf("%s: Failed to add rule at iteration %d\n", __func__, i);
     576                 :          0 :                         goto error;
     577                 :            :                 }
     578                 :            :         }
     579                 :            : 
     580                 :          1 : error:
     581                 :          1 :         writer_done = 1;
     582                 :            :         /* Wait until reader exited. */
     583                 :          1 :         rte_eal_mp_wait_lcore();
     584                 :            : 
     585                 :          1 :         rte_fib_free(g_fib);
     586                 :          1 :         rte_free(g_v);
     587                 :            : 
     588         [ -  + ]:          1 :         return status == 0 ? TEST_SUCCESS : TEST_FAILED;
     589                 :            : }
     590                 :            : 
     591                 :            : static struct unit_test_suite fib_fast_tests = {
     592                 :            :         .suite_name = "fib autotest",
     593                 :            :         .setup = NULL,
     594                 :            :         .teardown = NULL,
     595                 :            :         .unit_test_cases = {
     596                 :            :         TEST_CASE(test_create_invalid),
     597                 :            :         TEST_CASE(test_free_null),
     598                 :            :         TEST_CASE(test_add_del_invalid),
     599                 :            :         TEST_CASE(test_get_invalid),
     600                 :            :         TEST_CASE(test_lookup),
     601                 :            :         TEST_CASE(test_invalid_rcu),
     602                 :            :         TEST_CASE(test_fib_rcu_sync_rw),
     603                 :            :         TEST_CASES_END()
     604                 :            :         }
     605                 :            : };
     606                 :            : 
     607                 :            : static struct unit_test_suite fib_slow_tests = {
     608                 :            :         .suite_name = "fib slow autotest",
     609                 :            :         .setup = NULL,
     610                 :            :         .teardown = NULL,
     611                 :            :         .unit_test_cases = {
     612                 :            :         TEST_CASE(test_multiple_create),
     613                 :            :         TEST_CASES_END()
     614                 :            :         }
     615                 :            : };
     616                 :            : 
     617                 :            : /*
     618                 :            :  * Do all unit tests.
     619                 :            :  */
     620                 :            : static int
     621                 :          1 : test_fib(void)
     622                 :            : {
     623                 :          1 :         return unit_test_suite_runner(&fib_fast_tests);
     624                 :            : }
     625                 :            : 
     626                 :            : static int
     627                 :          0 : test_slow_fib(void)
     628                 :            : {
     629                 :          0 :         return unit_test_suite_runner(&fib_slow_tests);
     630                 :            : }
     631                 :            : 
     632                 :        252 : REGISTER_FAST_TEST(fib_autotest, true, true, test_fib);
     633                 :        252 : REGISTER_PERF_TEST(fib_slow_autotest, test_slow_fib);

Generated by: LCOV version 1.14