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