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