dpdk/app/test/test_rib.c
<<
>>
Prefs
   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_rib.h>
  12
  13#include "test.h"
  14
  15typedef int32_t (*rte_rib_test)(void);
  16
  17static int32_t test_create_invalid(void);
  18static int32_t test_multiple_create(void);
  19static int32_t test_free_null(void);
  20static int32_t test_insert_invalid(void);
  21static int32_t test_get_fn(void);
  22static int32_t test_basic(void);
  23static int32_t test_tree_traversal(void);
  24
  25#define MAX_DEPTH 32
  26#define MAX_RULES (1 << 22)
  27
  28/*
  29 * Check that rte_rib_create fails gracefully for incorrect user input
  30 * arguments
  31 */
  32int32_t
  33test_create_invalid(void)
  34{
  35        struct rte_rib *rib = NULL;
  36        struct rte_rib_conf config;
  37
  38        config.max_nodes = MAX_RULES;
  39        config.ext_sz = 0;
  40
  41        /* rte_rib_create: rib name == NULL */
  42        rib = rte_rib_create(NULL, SOCKET_ID_ANY, &config);
  43        RTE_TEST_ASSERT(rib == NULL,
  44                "Call succeeded with invalid parameters\n");
  45
  46        /* rte_rib_create: config == NULL */
  47        rib = rte_rib_create(__func__, SOCKET_ID_ANY, NULL);
  48        RTE_TEST_ASSERT(rib == NULL,
  49                "Call succeeded with invalid parameters\n");
  50
  51        /* socket_id < -1 is invalid */
  52        rib = rte_rib_create(__func__, -2, &config);
  53        RTE_TEST_ASSERT(rib == NULL,
  54                "Call succeeded with invalid parameters\n");
  55
  56        /* rte_rib_create: max_nodes = 0 */
  57        config.max_nodes = 0;
  58        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
  59        RTE_TEST_ASSERT(rib == NULL,
  60                "Call succeeded with invalid parameters\n");
  61        config.max_nodes = MAX_RULES;
  62
  63        return TEST_SUCCESS;
  64}
  65
  66/*
  67 * Create rib table then delete rib table 10 times
  68 * Use a slightly different rules size each time
  69 */
  70int32_t
  71test_multiple_create(void)
  72{
  73        struct rte_rib *rib = NULL;
  74        struct rte_rib_conf config;
  75        int32_t i;
  76
  77        config.ext_sz = 0;
  78
  79        for (i = 0; i < 100; i++) {
  80                config.max_nodes = MAX_RULES - i;
  81                rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
  82                RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
  83                rte_rib_free(rib);
  84        }
  85        /* Can not test free so return success */
  86        return TEST_SUCCESS;
  87}
  88
  89/*
  90 * Call rte_rib_free for NULL pointer user input. Note: free has no return and
  91 * therefore it is impossible to check for failure but this test is added to
  92 * increase function coverage metrics and to validate that freeing null does
  93 * not crash.
  94 */
  95int32_t
  96test_free_null(void)
  97{
  98        struct rte_rib *rib = NULL;
  99        struct rte_rib_conf config;
 100
 101        config.max_nodes = MAX_RULES;
 102        config.ext_sz = 0;
 103
 104        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
 105        RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 106
 107        rte_rib_free(rib);
 108        rte_rib_free(NULL);
 109        return TEST_SUCCESS;
 110}
 111
 112/*
 113 * Check that rte_rib_insert fails gracefully for incorrect user input arguments
 114 */
 115int32_t
 116test_insert_invalid(void)
 117{
 118        struct rte_rib *rib = NULL;
 119        struct rte_rib_node *node, *node1;
 120        struct rte_rib_conf config;
 121        uint32_t ip = RTE_IPV4(0, 0, 0, 0);
 122        uint8_t depth = 24;
 123
 124        config.max_nodes = MAX_RULES;
 125        config.ext_sz = 0;
 126
 127        /* rte_rib_insert: rib == NULL */
 128        node = rte_rib_insert(NULL, ip, depth);
 129        RTE_TEST_ASSERT(node == NULL,
 130                "Call succeeded with invalid parameters\n");
 131
 132        /*Create valid rib to use in rest of test. */
 133        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
 134        RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 135
 136        /* rte_rib_insert: depth > MAX_DEPTH */
 137        node = rte_rib_insert(rib, ip, MAX_DEPTH + 1);
 138        RTE_TEST_ASSERT(node == NULL,
 139                "Call succeeded with invalid parameters\n");
 140
 141        /* insert the same ip/depth twice*/
 142        node = rte_rib_insert(rib, ip, depth);
 143        RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 144        node1 = rte_rib_insert(rib, ip, depth);
 145        RTE_TEST_ASSERT(node1 == NULL,
 146                "Call succeeded with invalid parameters\n");
 147
 148        rte_rib_free(rib);
 149
 150        return TEST_SUCCESS;
 151}
 152
 153/*
 154 * Call rte_rib_node access functions with incorrect input.
 155 * After call rte_rib_node access functions with correct args
 156 * and check the return values for correctness
 157 */
 158int32_t
 159test_get_fn(void)
 160{
 161        struct rte_rib *rib = NULL;
 162        struct rte_rib_node *node;
 163        struct rte_rib_conf config;
 164        void *ext;
 165        uint32_t ip = RTE_IPV4(192, 0, 2, 0);
 166        uint32_t ip_ret;
 167        uint64_t nh_set = 10;
 168        uint64_t nh_ret;
 169        uint8_t depth = 24;
 170        uint8_t depth_ret;
 171        int ret;
 172
 173        config.max_nodes = MAX_RULES;
 174        config.ext_sz = 0;
 175
 176        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
 177        RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 178
 179        node = rte_rib_insert(rib, ip, depth);
 180        RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 181
 182        /* test rte_rib_get_ip() with incorrect args */
 183        ret = rte_rib_get_ip(NULL, &ip_ret);
 184        RTE_TEST_ASSERT(ret < 0,
 185                "Call succeeded with invalid parameters\n");
 186        ret = rte_rib_get_ip(node, NULL);
 187        RTE_TEST_ASSERT(ret < 0,
 188                "Call succeeded with invalid parameters\n");
 189
 190        /* test rte_rib_get_depth() with incorrect args */
 191        ret = rte_rib_get_depth(NULL, &depth_ret);
 192        RTE_TEST_ASSERT(ret < 0,
 193                "Call succeeded with invalid parameters\n");
 194        ret = rte_rib_get_depth(node, NULL);
 195        RTE_TEST_ASSERT(ret < 0,
 196                "Call succeeded with invalid parameters\n");
 197
 198        /* test rte_rib_set_nh() with incorrect args */
 199        ret = rte_rib_set_nh(NULL, nh_set);
 200        RTE_TEST_ASSERT(ret < 0,
 201                "Call succeeded with invalid parameters\n");
 202
 203        /* test rte_rib_get_nh() with incorrect args */
 204        ret = rte_rib_get_nh(NULL, &nh_ret);
 205        RTE_TEST_ASSERT(ret < 0,
 206                "Call succeeded with invalid parameters\n");
 207        ret = rte_rib_get_nh(node, NULL);
 208        RTE_TEST_ASSERT(ret < 0,
 209                "Call succeeded with invalid parameters\n");
 210
 211        /* test rte_rib_get_ext() with incorrect args */
 212        ext = rte_rib_get_ext(NULL);
 213        RTE_TEST_ASSERT(ext == NULL,
 214                "Call succeeded with invalid parameters\n");
 215
 216        /* check the return values */
 217        ret = rte_rib_get_ip(node, &ip_ret);
 218        RTE_TEST_ASSERT((ret == 0) && (ip_ret == ip),
 219                "Failed to get proper node ip\n");
 220        ret = rte_rib_get_depth(node, &depth_ret);
 221        RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
 222                "Failed to get proper node depth\n");
 223        ret = rte_rib_set_nh(node, nh_set);
 224        RTE_TEST_ASSERT(ret == 0,
 225                "Failed to set rte_rib_node nexthop\n");
 226        ret = rte_rib_get_nh(node, &nh_ret);
 227        RTE_TEST_ASSERT((ret == 0) && (nh_ret == nh_set),
 228                "Failed to get proper nexthop\n");
 229
 230        rte_rib_free(rib);
 231
 232        return TEST_SUCCESS;
 233}
 234
 235/*
 236 * Call insert, lookup/lookup_exact and delete for a single rule
 237 */
 238int32_t
 239test_basic(void)
 240{
 241        struct rte_rib *rib = NULL;
 242        struct rte_rib_node *node;
 243        struct rte_rib_conf config;
 244
 245        uint32_t ip = RTE_IPV4(192, 0, 2, 0);
 246        uint64_t next_hop_add = 10;
 247        uint64_t next_hop_return;
 248        uint8_t depth = 24;
 249        int ret;
 250
 251        config.max_nodes = MAX_RULES;
 252        config.ext_sz = 0;
 253
 254        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
 255        RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 256
 257        node = rte_rib_insert(rib, ip, depth);
 258        RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 259
 260        ret = rte_rib_set_nh(node, next_hop_add);
 261        RTE_TEST_ASSERT(ret == 0,
 262                "Failed to set rte_rib_node field\n");
 263
 264        node = rte_rib_lookup(rib, ip);
 265        RTE_TEST_ASSERT(node != NULL, "Failed to lookup\n");
 266
 267        ret = rte_rib_get_nh(node, &next_hop_return);
 268        RTE_TEST_ASSERT((ret == 0) && (next_hop_add == next_hop_return),
 269                "Failed to get proper nexthop\n");
 270
 271        node = rte_rib_lookup_exact(rib, ip, depth);
 272        RTE_TEST_ASSERT(node != NULL,
 273                "Failed to lookup\n");
 274
 275        ret = rte_rib_get_nh(node, &next_hop_return);
 276        RTE_TEST_ASSERT((ret == 0) && (next_hop_add == next_hop_return),
 277                "Failed to get proper nexthop\n");
 278
 279        rte_rib_remove(rib, ip, depth);
 280
 281        node = rte_rib_lookup(rib, ip);
 282        RTE_TEST_ASSERT(node == NULL,
 283                "Lookup returns non existent rule\n");
 284        node = rte_rib_lookup_exact(rib, ip, depth);
 285        RTE_TEST_ASSERT(node == NULL,
 286                "Lookup returns non existent rule\n");
 287
 288        rte_rib_free(rib);
 289
 290        return TEST_SUCCESS;
 291}
 292
 293int32_t
 294test_tree_traversal(void)
 295{
 296        struct rte_rib *rib = NULL;
 297        struct rte_rib_node *node;
 298        struct rte_rib_conf config;
 299
 300        uint32_t ip1 = RTE_IPV4(10, 10, 10, 0);
 301        uint32_t ip2 = RTE_IPV4(10, 10, 130, 80);
 302        uint8_t depth = 30;
 303
 304        config.max_nodes = MAX_RULES;
 305        config.ext_sz = 0;
 306
 307        rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
 308        RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 309
 310        node = rte_rib_insert(rib, ip1, depth);
 311        RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 312
 313        node = rte_rib_insert(rib, ip2, depth);
 314        RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 315
 316        node = NULL;
 317        node = rte_rib_get_nxt(rib, RTE_IPV4(10, 10, 130, 0), 24, node,
 318                        RTE_RIB_GET_NXT_ALL);
 319        RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 320
 321        rte_rib_free(rib);
 322
 323        return TEST_SUCCESS;
 324}
 325
 326static struct unit_test_suite rib_tests = {
 327        .suite_name = "rib autotest",
 328        .setup = NULL,
 329        .teardown = NULL,
 330        .unit_test_cases = {
 331                TEST_CASE(test_create_invalid),
 332                TEST_CASE(test_free_null),
 333                TEST_CASE(test_insert_invalid),
 334                TEST_CASE(test_get_fn),
 335                TEST_CASE(test_basic),
 336                TEST_CASE(test_tree_traversal),
 337                TEST_CASES_END()
 338        }
 339};
 340
 341static struct unit_test_suite rib_slow_tests = {
 342        .suite_name = "rib slow autotest",
 343        .setup = NULL,
 344        .teardown = NULL,
 345        .unit_test_cases = {
 346                TEST_CASE(test_multiple_create),
 347                TEST_CASES_END()
 348        }
 349};
 350
 351/*
 352 * Do all unit tests.
 353 */
 354static int
 355test_rib(void)
 356{
 357        return unit_test_suite_runner(&rib_tests);
 358}
 359
 360static int
 361test_slow_rib(void)
 362{
 363        return unit_test_suite_runner(&rib_slow_tests);
 364}
 365
 366REGISTER_TEST_COMMAND(rib_autotest, test_rib);
 367REGISTER_TEST_COMMAND(rib_slow_autotest, test_slow_rib);
 368