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 "test.h" 7 8 #include <stdio.h> 9 #include <stdint.h> 10 #include <stdlib.h> 11 12 #include <rte_ip.h> 13 #include <rte_rib.h> 14 15 typedef int32_t (*rte_rib_test)(void); 16 17 static int32_t test_create_invalid(void); 18 static int32_t test_multiple_create(void); 19 static int32_t test_free_null(void); 20 static int32_t test_insert_invalid(void); 21 static int32_t test_get_fn(void); 22 static int32_t test_basic(void); 23 static 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 */ 32 int32_t 33 test_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 */ 70 int32_t 71 test_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 */ 95 int32_t 96 test_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 */ 115 int32_t 116 test_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 */ 158 int32_t 159 test_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 */ 238 int32_t 239 test_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 293 int32_t 294 test_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 326 static 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 341 static 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 */ 354 static int 355 test_rib(void) 356 { 357 return unit_test_suite_runner(&rib_tests); 358 } 359 360 static int 361 test_slow_rib(void) 362 { 363 return unit_test_suite_runner(&rib_slow_tests); 364 } 365 366 REGISTER_FAST_TEST(rib_autotest, true, true, test_rib); 367 REGISTER_PERF_TEST(rib_slow_autotest, test_slow_rib); 368