1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <errno.h> 7 8 #include "test.h" 9 10 #include <rte_string_fns.h> 11 #include <rte_mbuf.h> 12 #include <rte_byteorder.h> 13 #include <rte_ip.h> 14 #include <rte_acl.h> 15 #include <rte_common.h> 16 17 #include "test_acl.h" 18 19 #define BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT) 20 21 #define LEN RTE_ACL_MAX_CATEGORIES 22 23 RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS); 24 25 struct rte_acl_param acl_param = { 26 .name = "acl_ctx", 27 .socket_id = SOCKET_ID_ANY, 28 .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ, 29 .max_rule_num = 0x30000, 30 }; 31 32 struct rte_acl_ipv4vlan_rule acl_rule = { 33 .data = { .priority = 1, .category_mask = 0xff }, 34 .src_port_low = 0, 35 .src_port_high = UINT16_MAX, 36 .dst_port_low = 0, 37 .dst_port_high = UINT16_MAX, 38 }; 39 40 const uint32_t ipv4_7tuple_layout[RTE_ACL_IPV4VLAN_NUM] = { 41 offsetof(struct ipv4_7tuple, proto), 42 offsetof(struct ipv4_7tuple, vlan), 43 offsetof(struct ipv4_7tuple, ip_src), 44 offsetof(struct ipv4_7tuple, ip_dst), 45 offsetof(struct ipv4_7tuple, port_src), 46 }; 47 48 49 /* byteswap to cpu or network order */ 50 static void 51 bswap_test_data(struct ipv4_7tuple *data, int len, int to_be) 52 { 53 int i; 54 55 for (i = 0; i < len; i++) { 56 57 if (to_be) { 58 /* swap all bytes so that they are in network order */ 59 data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst); 60 data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src); 61 data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst); 62 data[i].port_src = rte_cpu_to_be_16(data[i].port_src); 63 data[i].vlan = rte_cpu_to_be_16(data[i].vlan); 64 data[i].domain = rte_cpu_to_be_16(data[i].domain); 65 } else { 66 data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst); 67 data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src); 68 data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst); 69 data[i].port_src = rte_be_to_cpu_16(data[i].port_src); 70 data[i].vlan = rte_be_to_cpu_16(data[i].vlan); 71 data[i].domain = rte_be_to_cpu_16(data[i].domain); 72 } 73 } 74 } 75 76 static int 77 acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule) 78 { 79 if (rule->src_port_low > rule->src_port_high || 80 rule->dst_port_low > rule->dst_port_high || 81 rule->src_mask_len > BIT_SIZEOF(rule->src_addr) || 82 rule->dst_mask_len > BIT_SIZEOF(rule->dst_addr)) 83 return -EINVAL; 84 return 0; 85 } 86 87 static void 88 acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule *ri, 89 struct acl_ipv4vlan_rule *ro) 90 { 91 ro->data = ri->data; 92 93 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto; 94 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan; 95 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain; 96 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr; 97 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr; 98 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low; 99 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low; 100 101 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask; 102 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask; 103 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 = 104 ri->domain_mask; 105 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = 106 ri->src_mask_len; 107 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len; 108 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 = 109 ri->src_port_high; 110 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 = 111 ri->dst_port_high; 112 } 113 114 /* 115 * Add ipv4vlan rules to an existing ACL context. 116 * This function is not multi-thread safe. 117 * 118 * @param ctx 119 * ACL context to add patterns to. 120 * @param rules 121 * Array of rules to add to the ACL context. 122 * Note that all fields in rte_acl_ipv4vlan_rule structures are expected 123 * to be in host byte order. 124 * @param num 125 * Number of elements in the input array of rules. 126 * @return 127 * - -ENOMEM if there is no space in the ACL context for these rules. 128 * - -EINVAL if the parameters are invalid. 129 * - Zero if operation completed successfully. 130 */ 131 static int 132 rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx, 133 const struct rte_acl_ipv4vlan_rule *rules, 134 uint32_t num) 135 { 136 int32_t rc; 137 uint32_t i; 138 struct acl_ipv4vlan_rule rv; 139 140 if (ctx == NULL || rules == NULL) 141 return -EINVAL; 142 143 /* check input rules. */ 144 for (i = 0; i != num; i++) { 145 rc = acl_ipv4vlan_check_rule(rules + i); 146 if (rc != 0) { 147 RTE_LOG(ERR, ACL, "%s: rule #%u is invalid\n", 148 __func__, i + 1); 149 return rc; 150 } 151 } 152 153 /* perform conversion to the internal format and add to the context. */ 154 for (i = 0, rc = 0; i != num && rc == 0; i++) { 155 acl_ipv4vlan_convert_rule(rules + i, &rv); 156 rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&rv, 1); 157 } 158 159 return rc; 160 } 161 162 static void 163 acl_ipv4vlan_config(struct rte_acl_config *cfg, 164 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], 165 uint32_t num_categories) 166 { 167 static const struct rte_acl_field_def 168 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = { 169 { 170 .type = RTE_ACL_FIELD_TYPE_BITMASK, 171 .size = sizeof(uint8_t), 172 .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD, 173 .input_index = RTE_ACL_IPV4VLAN_PROTO, 174 }, 175 { 176 .type = RTE_ACL_FIELD_TYPE_BITMASK, 177 .size = sizeof(uint16_t), 178 .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD, 179 .input_index = RTE_ACL_IPV4VLAN_VLAN, 180 }, 181 { 182 .type = RTE_ACL_FIELD_TYPE_BITMASK, 183 .size = sizeof(uint16_t), 184 .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD, 185 .input_index = RTE_ACL_IPV4VLAN_VLAN, 186 }, 187 { 188 .type = RTE_ACL_FIELD_TYPE_MASK, 189 .size = sizeof(uint32_t), 190 .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD, 191 .input_index = RTE_ACL_IPV4VLAN_SRC, 192 }, 193 { 194 .type = RTE_ACL_FIELD_TYPE_MASK, 195 .size = sizeof(uint32_t), 196 .field_index = RTE_ACL_IPV4VLAN_DST_FIELD, 197 .input_index = RTE_ACL_IPV4VLAN_DST, 198 }, 199 { 200 .type = RTE_ACL_FIELD_TYPE_RANGE, 201 .size = sizeof(uint16_t), 202 .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD, 203 .input_index = RTE_ACL_IPV4VLAN_PORTS, 204 }, 205 { 206 .type = RTE_ACL_FIELD_TYPE_RANGE, 207 .size = sizeof(uint16_t), 208 .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD, 209 .input_index = RTE_ACL_IPV4VLAN_PORTS, 210 }, 211 }; 212 213 memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs)); 214 cfg->num_fields = RTE_DIM(ipv4_defs); 215 216 cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset = 217 layout[RTE_ACL_IPV4VLAN_PROTO]; 218 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset = 219 layout[RTE_ACL_IPV4VLAN_VLAN]; 220 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset = 221 layout[RTE_ACL_IPV4VLAN_VLAN] + 222 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size; 223 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset = 224 layout[RTE_ACL_IPV4VLAN_SRC]; 225 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = 226 layout[RTE_ACL_IPV4VLAN_DST]; 227 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = 228 layout[RTE_ACL_IPV4VLAN_PORTS]; 229 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = 230 layout[RTE_ACL_IPV4VLAN_PORTS] + 231 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size; 232 233 cfg->num_categories = num_categories; 234 } 235 236 /* 237 * Analyze set of ipv4vlan rules and build required internal 238 * run-time structures. 239 * This function is not multi-thread safe. 240 * 241 * @param ctx 242 * ACL context to build. 243 * @param layout 244 * Layout of input data to search through. 245 * @param num_categories 246 * Maximum number of categories to use in that build. 247 * @return 248 * - -ENOMEM if couldn't allocate enough memory. 249 * - -EINVAL if the parameters are invalid. 250 * - Negative error code if operation failed. 251 * - Zero if operation completed successfully. 252 */ 253 static int 254 rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx, 255 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], 256 uint32_t num_categories) 257 { 258 struct rte_acl_config cfg; 259 260 if (ctx == NULL || layout == NULL) 261 return -EINVAL; 262 263 memset(&cfg, 0, sizeof(cfg)); 264 acl_ipv4vlan_config(&cfg, layout, num_categories); 265 return rte_acl_build(ctx, &cfg); 266 } 267 268 /* 269 * Test scalar and SSE ACL lookup. 270 */ 271 static int 272 test_classify_run(struct rte_acl_ctx *acx) 273 { 274 int ret, i; 275 uint32_t result, count; 276 uint32_t results[RTE_DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES]; 277 const uint8_t *data[RTE_DIM(acl_test_data)]; 278 279 /* swap all bytes in the data to network order */ 280 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1); 281 282 /* store pointers to test data */ 283 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) 284 data[i] = (uint8_t *)&acl_test_data[i]; 285 286 /** 287 * these will run quite a few times, it's necessary to test code paths 288 * from num=0 to num>8 289 */ 290 for (count = 0; count <= RTE_DIM(acl_test_data); count++) { 291 ret = rte_acl_classify(acx, data, results, 292 count, RTE_ACL_MAX_CATEGORIES); 293 if (ret != 0) { 294 printf("Line %i: SSE classify failed!\n", __LINE__); 295 goto err; 296 } 297 298 /* check if we allow everything we should allow */ 299 for (i = 0; i < (int) count; i++) { 300 result = 301 results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW]; 302 if (result != acl_test_data[i].allow) { 303 printf("Line %i: Error in allow results at %i " 304 "(expected %"PRIu32" got %"PRIu32")!\n", 305 __LINE__, i, acl_test_data[i].allow, 306 result); 307 ret = -EINVAL; 308 goto err; 309 } 310 } 311 312 /* check if we deny everything we should deny */ 313 for (i = 0; i < (int) count; i++) { 314 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY]; 315 if (result != acl_test_data[i].deny) { 316 printf("Line %i: Error in deny results at %i " 317 "(expected %"PRIu32" got %"PRIu32")!\n", 318 __LINE__, i, acl_test_data[i].deny, 319 result); 320 ret = -EINVAL; 321 goto err; 322 } 323 } 324 } 325 326 /* make a quick check for scalar */ 327 ret = rte_acl_classify_alg(acx, data, results, 328 RTE_DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES, 329 RTE_ACL_CLASSIFY_SCALAR); 330 if (ret != 0) { 331 printf("Line %i: scalar classify failed!\n", __LINE__); 332 goto err; 333 } 334 335 /* check if we allow everything we should allow */ 336 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) { 337 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW]; 338 if (result != acl_test_data[i].allow) { 339 printf("Line %i: Error in allow results at %i " 340 "(expected %"PRIu32" got %"PRIu32")!\n", 341 __LINE__, i, acl_test_data[i].allow, 342 result); 343 ret = -EINVAL; 344 goto err; 345 } 346 } 347 348 /* check if we deny everything we should deny */ 349 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) { 350 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY]; 351 if (result != acl_test_data[i].deny) { 352 printf("Line %i: Error in deny results at %i " 353 "(expected %"PRIu32" got %"PRIu32")!\n", 354 __LINE__, i, acl_test_data[i].deny, 355 result); 356 ret = -EINVAL; 357 goto err; 358 } 359 } 360 361 ret = 0; 362 363 err: 364 /* swap data back to cpu order so that next time tests don't fail */ 365 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0); 366 return ret; 367 } 368 369 static int 370 test_classify_buid(struct rte_acl_ctx *acx, 371 const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) 372 { 373 int ret; 374 375 /* add rules to the context */ 376 ret = rte_acl_ipv4vlan_add_rules(acx, rules, num); 377 if (ret != 0) { 378 printf("Line %i: Adding rules to ACL context failed!\n", 379 __LINE__); 380 return ret; 381 } 382 383 /* try building the context */ 384 ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout, 385 RTE_ACL_MAX_CATEGORIES); 386 if (ret != 0) { 387 printf("Line %i: Building ACL context failed!\n", __LINE__); 388 return ret; 389 } 390 391 return 0; 392 } 393 394 #define TEST_CLASSIFY_ITER 4 395 396 /* 397 * Test scalar and SSE ACL lookup. 398 */ 399 static int 400 test_classify(void) 401 { 402 struct rte_acl_ctx *acx; 403 int i, ret; 404 405 acx = rte_acl_create(&acl_param); 406 if (acx == NULL) { 407 printf("Line %i: Error creating ACL context!\n", __LINE__); 408 return -1; 409 } 410 411 ret = 0; 412 for (i = 0; i != TEST_CLASSIFY_ITER; i++) { 413 414 if ((i & 1) == 0) 415 rte_acl_reset(acx); 416 else 417 rte_acl_reset_rules(acx); 418 419 ret = test_classify_buid(acx, acl_test_rules, 420 RTE_DIM(acl_test_rules)); 421 if (ret != 0) { 422 printf("Line %i, iter: %d: " 423 "Adding rules to ACL context failed!\n", 424 __LINE__, i); 425 break; 426 } 427 428 ret = test_classify_run(acx); 429 if (ret != 0) { 430 printf("Line %i, iter: %d: %s failed!\n", 431 __LINE__, i, __func__); 432 break; 433 } 434 435 /* reset rules and make sure that classify still works ok. */ 436 rte_acl_reset_rules(acx); 437 ret = test_classify_run(acx); 438 if (ret != 0) { 439 printf("Line %i, iter: %d: %s failed!\n", 440 __LINE__, i, __func__); 441 break; 442 } 443 } 444 445 rte_acl_free(acx); 446 return ret; 447 } 448 449 static int 450 test_build_ports_range(void) 451 { 452 static const struct rte_acl_ipv4vlan_rule test_rules[] = { 453 { 454 /* match all packets. */ 455 .data = { 456 .userdata = 1, 457 .category_mask = ACL_ALLOW_MASK, 458 .priority = 101, 459 }, 460 .src_port_low = 0, 461 .src_port_high = UINT16_MAX, 462 .dst_port_low = 0, 463 .dst_port_high = UINT16_MAX, 464 }, 465 { 466 /* match all packets with dst ports [54-65280]. */ 467 .data = { 468 .userdata = 2, 469 .category_mask = ACL_ALLOW_MASK, 470 .priority = 102, 471 }, 472 .src_port_low = 0, 473 .src_port_high = UINT16_MAX, 474 .dst_port_low = 54, 475 .dst_port_high = 65280, 476 }, 477 { 478 /* match all packets with dst ports [0-52]. */ 479 .data = { 480 .userdata = 3, 481 .category_mask = ACL_ALLOW_MASK, 482 .priority = 103, 483 }, 484 .src_port_low = 0, 485 .src_port_high = UINT16_MAX, 486 .dst_port_low = 0, 487 .dst_port_high = 52, 488 }, 489 { 490 /* match all packets with dst ports [53]. */ 491 .data = { 492 .userdata = 4, 493 .category_mask = ACL_ALLOW_MASK, 494 .priority = 99, 495 }, 496 .src_port_low = 0, 497 .src_port_high = UINT16_MAX, 498 .dst_port_low = 53, 499 .dst_port_high = 53, 500 }, 501 { 502 /* match all packets with dst ports [65279-65535]. */ 503 .data = { 504 .userdata = 5, 505 .category_mask = ACL_ALLOW_MASK, 506 .priority = 98, 507 }, 508 .src_port_low = 0, 509 .src_port_high = UINT16_MAX, 510 .dst_port_low = 65279, 511 .dst_port_high = UINT16_MAX, 512 }, 513 }; 514 515 static struct ipv4_7tuple test_data[] = { 516 { 517 .proto = 6, 518 .ip_src = RTE_IPv4(10, 1, 1, 1), 519 .ip_dst = RTE_IPv4(192, 168, 0, 33), 520 .port_dst = 53, 521 .allow = 1, 522 }, 523 { 524 .proto = 6, 525 .ip_src = RTE_IPv4(127, 84, 33, 1), 526 .ip_dst = RTE_IPv4(1, 2, 3, 4), 527 .port_dst = 65281, 528 .allow = 1, 529 }, 530 }; 531 532 struct rte_acl_ctx *acx; 533 int32_t ret, i, j; 534 uint32_t results[RTE_DIM(test_data)]; 535 const uint8_t *data[RTE_DIM(test_data)]; 536 537 acx = rte_acl_create(&acl_param); 538 if (acx == NULL) { 539 printf("Line %i: Error creating ACL context!\n", __LINE__); 540 return -1; 541 } 542 543 /* swap all bytes in the data to network order */ 544 bswap_test_data(test_data, RTE_DIM(test_data), 1); 545 546 /* store pointers to test data */ 547 for (i = 0; i != RTE_DIM(test_data); i++) 548 data[i] = (uint8_t *)&test_data[i]; 549 550 for (i = 0; i != RTE_DIM(test_rules); i++) { 551 rte_acl_reset(acx); 552 ret = test_classify_buid(acx, test_rules, i + 1); 553 if (ret != 0) { 554 printf("Line %i, iter: %d: " 555 "Adding rules to ACL context failed!\n", 556 __LINE__, i); 557 break; 558 } 559 ret = rte_acl_classify(acx, data, results, 560 RTE_DIM(data), 1); 561 if (ret != 0) { 562 printf("Line %i, iter: %d: classify failed!\n", 563 __LINE__, i); 564 break; 565 } 566 567 /* check results */ 568 for (j = 0; j != RTE_DIM(results); j++) { 569 if (results[j] != test_data[j].allow) { 570 printf("Line %i: Error in allow results at %i " 571 "(expected %"PRIu32" got %"PRIu32")!\n", 572 __LINE__, j, test_data[j].allow, 573 results[j]); 574 ret = -EINVAL; 575 } 576 } 577 } 578 579 bswap_test_data(test_data, RTE_DIM(test_data), 0); 580 581 rte_acl_free(acx); 582 return ret; 583 } 584 585 static void 586 convert_rule(const struct rte_acl_ipv4vlan_rule *ri, 587 struct acl_ipv4vlan_rule *ro) 588 { 589 ro->data = ri->data; 590 591 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto; 592 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan; 593 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain; 594 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr; 595 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr; 596 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low; 597 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low; 598 599 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask; 600 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask; 601 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 = 602 ri->domain_mask; 603 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = 604 ri->src_mask_len; 605 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len; 606 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 = 607 ri->src_port_high; 608 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 = 609 ri->dst_port_high; 610 } 611 612 /* 613 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to 614 * RTE_ACL_FIELD_TYPE_BITMASK. 615 */ 616 static void 617 convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri, 618 struct acl_ipv4vlan_rule *ro) 619 { 620 uint32_t v; 621 622 convert_rule(ri, ro); 623 v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32; 624 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = 625 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v)); 626 v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32; 627 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = 628 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v)); 629 } 630 631 /* 632 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to 633 * RTE_ACL_FIELD_TYPE_RANGE. 634 */ 635 static void 636 convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri, 637 struct acl_ipv4vlan_rule *ro) 638 { 639 uint32_t hi, lo, mask; 640 641 convert_rule(ri, ro); 642 643 mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32; 644 mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask)); 645 lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask; 646 hi = lo + ~mask; 647 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo; 648 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi; 649 650 mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32; 651 mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask)); 652 lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask; 653 hi = lo + ~mask; 654 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo; 655 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi; 656 } 657 658 /* 659 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields. 660 */ 661 static void 662 convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri, 663 struct acl_ipv4vlan_rule *ro) 664 { 665 struct rte_acl_field t1, t2; 666 667 convert_rule(ri, ro); 668 669 t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD]; 670 t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD]; 671 672 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] = 673 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD]; 674 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] = 675 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD]; 676 677 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1; 678 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2; 679 } 680 681 /* 682 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules. 683 */ 684 static void 685 convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri, 686 struct acl_ipv4vlan_rule *ro) 687 { 688 struct rte_acl_field t; 689 690 convert_rule(ri, ro); 691 692 t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD]; 693 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] = 694 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD]; 695 696 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t; 697 } 698 699 static void 700 ipv4vlan_config(struct rte_acl_config *cfg, 701 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], 702 uint32_t num_categories) 703 { 704 static const struct rte_acl_field_def 705 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = { 706 { 707 .type = RTE_ACL_FIELD_TYPE_BITMASK, 708 .size = sizeof(uint8_t), 709 .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD, 710 .input_index = RTE_ACL_IPV4VLAN_PROTO, 711 }, 712 { 713 .type = RTE_ACL_FIELD_TYPE_BITMASK, 714 .size = sizeof(uint16_t), 715 .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD, 716 .input_index = RTE_ACL_IPV4VLAN_VLAN, 717 }, 718 { 719 .type = RTE_ACL_FIELD_TYPE_BITMASK, 720 .size = sizeof(uint16_t), 721 .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD, 722 .input_index = RTE_ACL_IPV4VLAN_VLAN, 723 }, 724 { 725 .type = RTE_ACL_FIELD_TYPE_MASK, 726 .size = sizeof(uint32_t), 727 .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD, 728 .input_index = RTE_ACL_IPV4VLAN_SRC, 729 }, 730 { 731 .type = RTE_ACL_FIELD_TYPE_MASK, 732 .size = sizeof(uint32_t), 733 .field_index = RTE_ACL_IPV4VLAN_DST_FIELD, 734 .input_index = RTE_ACL_IPV4VLAN_DST, 735 }, 736 { 737 .type = RTE_ACL_FIELD_TYPE_RANGE, 738 .size = sizeof(uint16_t), 739 .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD, 740 .input_index = RTE_ACL_IPV4VLAN_PORTS, 741 }, 742 { 743 .type = RTE_ACL_FIELD_TYPE_RANGE, 744 .size = sizeof(uint16_t), 745 .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD, 746 .input_index = RTE_ACL_IPV4VLAN_PORTS, 747 }, 748 }; 749 750 memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs)); 751 cfg->num_fields = RTE_DIM(ipv4_defs); 752 753 cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset = 754 layout[RTE_ACL_IPV4VLAN_PROTO]; 755 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset = 756 layout[RTE_ACL_IPV4VLAN_VLAN]; 757 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset = 758 layout[RTE_ACL_IPV4VLAN_VLAN] + 759 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size; 760 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset = 761 layout[RTE_ACL_IPV4VLAN_SRC]; 762 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = 763 layout[RTE_ACL_IPV4VLAN_DST]; 764 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = 765 layout[RTE_ACL_IPV4VLAN_PORTS]; 766 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = 767 layout[RTE_ACL_IPV4VLAN_PORTS] + 768 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size; 769 770 cfg->num_categories = num_categories; 771 } 772 773 static int 774 convert_rules(struct rte_acl_ctx *acx, 775 void (*convert)(const struct rte_acl_ipv4vlan_rule *, 776 struct acl_ipv4vlan_rule *), 777 const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) 778 { 779 int32_t rc; 780 uint32_t i; 781 struct acl_ipv4vlan_rule r; 782 783 for (i = 0; i != num; i++) { 784 convert(rules + i, &r); 785 rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1); 786 if (rc != 0) { 787 printf("Line %i: Adding rule %u to ACL context " 788 "failed with error code: %d\n", 789 __LINE__, i, rc); 790 return rc; 791 } 792 } 793 794 return 0; 795 } 796 797 static void 798 convert_config(struct rte_acl_config *cfg) 799 { 800 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); 801 } 802 803 /* 804 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK. 805 */ 806 static void 807 convert_config_1(struct rte_acl_config *cfg) 808 { 809 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); 810 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK; 811 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK; 812 } 813 814 /* 815 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE. 816 */ 817 static void 818 convert_config_2(struct rte_acl_config *cfg) 819 { 820 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); 821 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE; 822 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE; 823 } 824 825 /* 826 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions. 827 */ 828 static void 829 convert_config_3(struct rte_acl_config *cfg) 830 { 831 struct rte_acl_field_def t1, t2; 832 833 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); 834 835 t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD]; 836 t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD]; 837 838 /* swap VLAN1 and SRCP rule definition. */ 839 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] = 840 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD]; 841 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index; 842 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index; 843 844 /* swap VLAN2 and DSTP rule definition. */ 845 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] = 846 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD]; 847 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index; 848 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index; 849 850 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type; 851 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size; 852 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset; 853 854 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type; 855 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size; 856 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset; 857 } 858 859 /* 860 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions. 861 */ 862 static void 863 convert_config_4(struct rte_acl_config *cfg) 864 { 865 struct rte_acl_field_def t; 866 867 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); 868 869 t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD]; 870 871 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] = 872 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD]; 873 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index; 874 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index; 875 876 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type; 877 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size; 878 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset; 879 } 880 881 882 static int 883 build_convert_rules(struct rte_acl_ctx *acx, 884 void (*config)(struct rte_acl_config *), 885 size_t max_size) 886 { 887 struct rte_acl_config cfg; 888 889 memset(&cfg, 0, sizeof(cfg)); 890 config(&cfg); 891 cfg.max_size = max_size; 892 return rte_acl_build(acx, &cfg); 893 } 894 895 static int 896 test_convert_rules(const char *desc, 897 void (*config)(struct rte_acl_config *), 898 void (*convert)(const struct rte_acl_ipv4vlan_rule *, 899 struct acl_ipv4vlan_rule *)) 900 { 901 struct rte_acl_ctx *acx; 902 int32_t rc; 903 uint32_t i; 904 static const size_t mem_sizes[] = {0, -1}; 905 906 printf("running %s(%s)\n", __func__, desc); 907 908 acx = rte_acl_create(&acl_param); 909 if (acx == NULL) { 910 printf("Line %i: Error creating ACL context!\n", __LINE__); 911 return -1; 912 } 913 914 rc = convert_rules(acx, convert, acl_test_rules, 915 RTE_DIM(acl_test_rules)); 916 if (rc != 0) 917 printf("Line %i: Error converting ACL rules!\n", __LINE__); 918 919 for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) { 920 921 rc = build_convert_rules(acx, config, mem_sizes[i]); 922 if (rc != 0) { 923 printf("Line %i: Error @ build_convert_rules(%zu)!\n", 924 __LINE__, mem_sizes[i]); 925 break; 926 } 927 928 rc = test_classify_run(acx); 929 if (rc != 0) 930 printf("%s failed at line %i, max_size=%zu\n", 931 __func__, __LINE__, mem_sizes[i]); 932 } 933 934 rte_acl_free(acx); 935 return rc; 936 } 937 938 static int 939 test_convert(void) 940 { 941 static const struct { 942 const char *desc; 943 void (*config)(struct rte_acl_config *); 944 void (*convert)(const struct rte_acl_ipv4vlan_rule *, 945 struct acl_ipv4vlan_rule *); 946 } convert_param[] = { 947 { 948 "acl_ipv4vlan_tuple", 949 convert_config, 950 convert_rule, 951 }, 952 { 953 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type " 954 "for IPv4", 955 convert_config_1, 956 convert_rule_1, 957 }, 958 { 959 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type " 960 "for IPv4", 961 convert_config_2, 962 convert_rule_2, 963 }, 964 { 965 "acl_ipv4vlan_tuple: swap VLAN and PORTs order", 966 convert_config_3, 967 convert_rule_3, 968 }, 969 { 970 "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order", 971 convert_config_4, 972 convert_rule_4, 973 }, 974 }; 975 976 uint32_t i; 977 int32_t rc; 978 979 for (i = 0; i != RTE_DIM(convert_param); i++) { 980 rc = test_convert_rules(convert_param[i].desc, 981 convert_param[i].config, 982 convert_param[i].convert); 983 if (rc != 0) { 984 printf("%s for test-case: %s failed, error code: %d;\n", 985 __func__, convert_param[i].desc, rc); 986 return rc; 987 } 988 } 989 990 return 0; 991 } 992 993 /* 994 * Test wrong layout behavior 995 * This test supplies the ACL context with invalid layout, which results in 996 * ACL matching the wrong stuff. However, it should match the wrong stuff 997 * the right way. We switch around source and destination addresses, 998 * source and destination ports, and protocol will point to first byte of 999 * destination port. 1000 */ 1001 static int 1002 test_invalid_layout(void) 1003 { 1004 struct rte_acl_ctx *acx; 1005 int ret, i; 1006 1007 uint32_t results[RTE_DIM(invalid_layout_data)]; 1008 const uint8_t *data[RTE_DIM(invalid_layout_data)]; 1009 1010 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = { 1011 /* proto points to destination port's first byte */ 1012 offsetof(struct ipv4_7tuple, port_dst), 1013 1014 0, /* VLAN not used */ 1015 1016 /* src and dst addresses are swapped */ 1017 offsetof(struct ipv4_7tuple, ip_dst), 1018 offsetof(struct ipv4_7tuple, ip_src), 1019 1020 /* 1021 * we can't swap ports here, so we will swap 1022 * them in the data 1023 */ 1024 offsetof(struct ipv4_7tuple, port_src), 1025 }; 1026 1027 acx = rte_acl_create(&acl_param); 1028 if (acx == NULL) { 1029 printf("Line %i: Error creating ACL context!\n", __LINE__); 1030 return -1; 1031 } 1032 1033 /* putting a lot of rules into the context results in greater 1034 * coverage numbers. it doesn't matter if they are identical */ 1035 for (i = 0; i < 1000; i++) { 1036 /* add rules to the context */ 1037 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules, 1038 RTE_DIM(invalid_layout_rules)); 1039 if (ret != 0) { 1040 printf("Line %i: Adding rules to ACL context failed!\n", 1041 __LINE__); 1042 rte_acl_free(acx); 1043 return -1; 1044 } 1045 } 1046 1047 /* try building the context */ 1048 ret = rte_acl_ipv4vlan_build(acx, layout, 1); 1049 if (ret != 0) { 1050 printf("Line %i: Building ACL context failed!\n", __LINE__); 1051 rte_acl_free(acx); 1052 return -1; 1053 } 1054 1055 /* swap all bytes in the data to network order */ 1056 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1); 1057 1058 /* prepare data */ 1059 for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) { 1060 data[i] = (uint8_t *)&invalid_layout_data[i]; 1061 } 1062 1063 /* classify tuples */ 1064 ret = rte_acl_classify_alg(acx, data, results, 1065 RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR); 1066 if (ret != 0) { 1067 printf("Line %i: SSE classify failed!\n", __LINE__); 1068 rte_acl_free(acx); 1069 return -1; 1070 } 1071 1072 for (i = 0; i < (int) RTE_DIM(results); i++) { 1073 if (results[i] != invalid_layout_data[i].allow) { 1074 printf("Line %i: Wrong results at %i " 1075 "(result=%u, should be %u)!\n", 1076 __LINE__, i, results[i], 1077 invalid_layout_data[i].allow); 1078 goto err; 1079 } 1080 } 1081 1082 /* classify tuples (scalar) */ 1083 ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1, 1084 RTE_ACL_CLASSIFY_SCALAR); 1085 1086 if (ret != 0) { 1087 printf("Line %i: Scalar classify failed!\n", __LINE__); 1088 rte_acl_free(acx); 1089 return -1; 1090 } 1091 1092 for (i = 0; i < (int) RTE_DIM(results); i++) { 1093 if (results[i] != invalid_layout_data[i].allow) { 1094 printf("Line %i: Wrong results at %i " 1095 "(result=%u, should be %u)!\n", 1096 __LINE__, i, results[i], 1097 invalid_layout_data[i].allow); 1098 goto err; 1099 } 1100 } 1101 1102 rte_acl_free(acx); 1103 1104 /* swap data back to cpu order so that next time tests don't fail */ 1105 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0); 1106 1107 return 0; 1108 err: 1109 1110 /* swap data back to cpu order so that next time tests don't fail */ 1111 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0); 1112 1113 rte_acl_free(acx); 1114 1115 return -1; 1116 } 1117 1118 /* 1119 * Test creating and finding ACL contexts, and adding rules 1120 */ 1121 static int 1122 test_create_find_add(void) 1123 { 1124 struct rte_acl_param param; 1125 struct rte_acl_ctx *acx, *acx2, *tmp; 1126 struct rte_acl_ipv4vlan_rule rules[LEN]; 1127 1128 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0}; 1129 1130 const char *acx_name = "acx"; 1131 const char *acx2_name = "acx2"; 1132 int i, ret; 1133 1134 /* create two contexts */ 1135 memcpy(¶m, &acl_param, sizeof(param)); 1136 param.max_rule_num = 2; 1137 1138 param.name = acx_name; 1139 acx = rte_acl_create(¶m); 1140 if (acx == NULL) { 1141 printf("Line %i: Error creating %s!\n", __LINE__, acx_name); 1142 return -1; 1143 } 1144 1145 param.name = acx2_name; 1146 acx2 = rte_acl_create(¶m); 1147 if (acx2 == NULL || acx2 == acx) { 1148 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name); 1149 rte_acl_free(acx); 1150 return -1; 1151 } 1152 1153 /* try to create third one, with an existing name */ 1154 param.name = acx_name; 1155 tmp = rte_acl_create(¶m); 1156 if (tmp != acx) { 1157 printf("Line %i: Creating context with existing name " 1158 "test failed!\n", 1159 __LINE__); 1160 if (tmp) 1161 rte_acl_free(tmp); 1162 goto err; 1163 } 1164 1165 param.name = acx2_name; 1166 tmp = rte_acl_create(¶m); 1167 if (tmp != acx2) { 1168 printf("Line %i: Creating context with existing " 1169 "name test 2 failed!\n", 1170 __LINE__); 1171 if (tmp) 1172 rte_acl_free(tmp); 1173 goto err; 1174 } 1175 1176 /* try to find existing ACL contexts */ 1177 tmp = rte_acl_find_existing(acx_name); 1178 if (tmp != acx) { 1179 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name); 1180 if (tmp) 1181 rte_acl_free(tmp); 1182 goto err; 1183 } 1184 1185 tmp = rte_acl_find_existing(acx2_name); 1186 if (tmp != acx2) { 1187 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name); 1188 if (tmp) 1189 rte_acl_free(tmp); 1190 goto err; 1191 } 1192 1193 /* try to find non-existing context */ 1194 tmp = rte_acl_find_existing("invalid"); 1195 if (tmp != NULL) { 1196 printf("Line %i: Non-existent ACL context found!\n", __LINE__); 1197 goto err; 1198 } 1199 1200 /* free context */ 1201 rte_acl_free(acx); 1202 1203 1204 /* create valid (but severely limited) acx */ 1205 memcpy(¶m, &acl_param, sizeof(param)); 1206 param.max_rule_num = LEN; 1207 1208 acx = rte_acl_create(¶m); 1209 if (acx == NULL) { 1210 printf("Line %i: Error creating %s!\n", __LINE__, param.name); 1211 goto err; 1212 } 1213 1214 /* create dummy acl */ 1215 for (i = 0; i < LEN; i++) { 1216 memcpy(&rules[i], &acl_rule, 1217 sizeof(struct rte_acl_ipv4vlan_rule)); 1218 /* skip zero */ 1219 rules[i].data.userdata = i + 1; 1220 /* one rule per category */ 1221 rules[i].data.category_mask = 1 << i; 1222 } 1223 1224 /* try filling up the context */ 1225 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN); 1226 if (ret != 0) { 1227 printf("Line %i: Adding %i rules to ACL context failed!\n", 1228 __LINE__, LEN); 1229 goto err; 1230 } 1231 1232 /* try adding to a (supposedly) full context */ 1233 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1); 1234 if (ret == 0) { 1235 printf("Line %i: Adding rules to full ACL context should" 1236 "have failed!\n", __LINE__); 1237 goto err; 1238 } 1239 1240 /* try building the context */ 1241 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES); 1242 if (ret != 0) { 1243 printf("Line %i: Building ACL context failed!\n", __LINE__); 1244 goto err; 1245 } 1246 1247 rte_acl_free(acx); 1248 rte_acl_free(acx2); 1249 1250 return 0; 1251 err: 1252 rte_acl_free(acx); 1253 rte_acl_free(acx2); 1254 return -1; 1255 } 1256 1257 /* 1258 * test various invalid rules 1259 */ 1260 static int 1261 test_invalid_rules(void) 1262 { 1263 struct rte_acl_ctx *acx; 1264 int ret; 1265 1266 struct rte_acl_ipv4vlan_rule rule; 1267 1268 acx = rte_acl_create(&acl_param); 1269 if (acx == NULL) { 1270 printf("Line %i: Error creating ACL context!\n", __LINE__); 1271 return -1; 1272 } 1273 1274 /* test inverted high/low source and destination ports. 1275 * originally, there was a problem with memory consumption when using 1276 * such rules. 1277 */ 1278 /* create dummy acl */ 1279 memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule)); 1280 rule.data.userdata = 1; 1281 rule.dst_port_low = 0xfff0; 1282 rule.dst_port_high = 0x0010; 1283 1284 /* add rules to context and try to build it */ 1285 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); 1286 if (ret == 0) { 1287 printf("Line %i: Adding rules to ACL context " 1288 "should have failed!\n", __LINE__); 1289 goto err; 1290 } 1291 1292 rule.dst_port_low = 0x0; 1293 rule.dst_port_high = 0xffff; 1294 rule.src_port_low = 0xfff0; 1295 rule.src_port_high = 0x0010; 1296 1297 /* add rules to context and try to build it */ 1298 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); 1299 if (ret == 0) { 1300 printf("Line %i: Adding rules to ACL context " 1301 "should have failed!\n", __LINE__); 1302 goto err; 1303 } 1304 1305 rule.dst_port_low = 0x0; 1306 rule.dst_port_high = 0xffff; 1307 rule.src_port_low = 0x0; 1308 rule.src_port_high = 0xffff; 1309 1310 rule.dst_mask_len = 33; 1311 1312 /* add rules to context and try to build it */ 1313 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); 1314 if (ret == 0) { 1315 printf("Line %i: Adding rules to ACL context " 1316 "should have failed!\n", __LINE__); 1317 goto err; 1318 } 1319 1320 rule.dst_mask_len = 0; 1321 rule.src_mask_len = 33; 1322 1323 /* add rules to context and try to build it */ 1324 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); 1325 if (ret == 0) { 1326 printf("Line %i: Adding rules to ACL context " 1327 "should have failed!\n", __LINE__); 1328 goto err; 1329 } 1330 1331 rte_acl_free(acx); 1332 1333 return 0; 1334 1335 err: 1336 rte_acl_free(acx); 1337 1338 return -1; 1339 } 1340 1341 /* 1342 * test functions by passing invalid or 1343 * non-workable parameters. 1344 * 1345 * we do very limited testing of classify functions here 1346 * because those are performance-critical and 1347 * thus don't do much parameter checking. 1348 */ 1349 static int 1350 test_invalid_parameters(void) 1351 { 1352 struct rte_acl_param param; 1353 struct rte_acl_ctx *acx; 1354 struct rte_acl_ipv4vlan_rule rule; 1355 int result; 1356 1357 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0}; 1358 1359 1360 /** 1361 * rte_ac_create() 1362 */ 1363 1364 /* NULL param */ 1365 acx = rte_acl_create(NULL); 1366 if (acx != NULL) { 1367 printf("Line %i: ACL context creation with NULL param " 1368 "should have failed!\n", __LINE__); 1369 rte_acl_free(acx); 1370 return -1; 1371 } 1372 1373 /* zero rule size */ 1374 memcpy(¶m, &acl_param, sizeof(param)); 1375 param.rule_size = 0; 1376 1377 acx = rte_acl_create(¶m); 1378 if (acx == NULL) { 1379 printf("Line %i: ACL context creation with zero rule len " 1380 "failed!\n", __LINE__); 1381 return -1; 1382 } else 1383 rte_acl_free(acx); 1384 1385 /* zero max rule num */ 1386 memcpy(¶m, &acl_param, sizeof(param)); 1387 param.max_rule_num = 0; 1388 1389 acx = rte_acl_create(¶m); 1390 if (acx == NULL) { 1391 printf("Line %i: ACL context creation with zero rule num " 1392 "failed!\n", __LINE__); 1393 return -1; 1394 } else 1395 rte_acl_free(acx); 1396 1397 /* invalid NUMA node */ 1398 memcpy(¶m, &acl_param, sizeof(param)); 1399 param.socket_id = RTE_MAX_NUMA_NODES + 1; 1400 1401 acx = rte_acl_create(¶m); 1402 if (acx != NULL) { 1403 printf("Line %i: ACL context creation with invalid NUMA " 1404 "should have failed!\n", __LINE__); 1405 rte_acl_free(acx); 1406 return -1; 1407 } 1408 1409 /* NULL name */ 1410 memcpy(¶m, &acl_param, sizeof(param)); 1411 param.name = NULL; 1412 1413 acx = rte_acl_create(¶m); 1414 if (acx != NULL) { 1415 printf("Line %i: ACL context creation with NULL name " 1416 "should have failed!\n", __LINE__); 1417 rte_acl_free(acx); 1418 return -1; 1419 } 1420 1421 /** 1422 * rte_acl_find_existing 1423 */ 1424 1425 acx = rte_acl_find_existing(NULL); 1426 if (acx != NULL) { 1427 printf("Line %i: NULL ACL context found!\n", __LINE__); 1428 rte_acl_free(acx); 1429 return -1; 1430 } 1431 1432 /** 1433 * rte_acl_ipv4vlan_add_rules 1434 */ 1435 1436 /* initialize everything */ 1437 memcpy(¶m, &acl_param, sizeof(param)); 1438 acx = rte_acl_create(¶m); 1439 if (acx == NULL) { 1440 printf("Line %i: ACL context creation failed!\n", __LINE__); 1441 return -1; 1442 } 1443 1444 memcpy(&rule, &acl_rule, sizeof(rule)); 1445 1446 /* NULL context */ 1447 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1); 1448 if (result == 0) { 1449 printf("Line %i: Adding rules with NULL ACL context " 1450 "should have failed!\n", __LINE__); 1451 rte_acl_free(acx); 1452 return -1; 1453 } 1454 1455 /* NULL rule */ 1456 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1); 1457 if (result == 0) { 1458 printf("Line %i: Adding NULL rule to ACL context " 1459 "should have failed!\n", __LINE__); 1460 rte_acl_free(acx); 1461 return -1; 1462 } 1463 1464 /* zero count (should succeed) */ 1465 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0); 1466 if (result != 0) { 1467 printf("Line %i: Adding 0 rules to ACL context failed!\n", 1468 __LINE__); 1469 rte_acl_free(acx); 1470 return -1; 1471 } 1472 1473 /* free ACL context */ 1474 rte_acl_free(acx); 1475 1476 1477 /** 1478 * rte_acl_ipv4vlan_build 1479 */ 1480 1481 /* reinitialize context */ 1482 memcpy(¶m, &acl_param, sizeof(param)); 1483 acx = rte_acl_create(¶m); 1484 if (acx == NULL) { 1485 printf("Line %i: ACL context creation failed!\n", __LINE__); 1486 return -1; 1487 } 1488 1489 /* NULL context */ 1490 result = rte_acl_ipv4vlan_build(NULL, layout, 1); 1491 if (result == 0) { 1492 printf("Line %i: Building with NULL context " 1493 "should have failed!\n", __LINE__); 1494 rte_acl_free(acx); 1495 return -1; 1496 } 1497 1498 /* NULL layout */ 1499 result = rte_acl_ipv4vlan_build(acx, NULL, 1); 1500 if (result == 0) { 1501 printf("Line %i: Building with NULL layout " 1502 "should have failed!\n", __LINE__); 1503 rte_acl_free(acx); 1504 return -1; 1505 } 1506 1507 /* zero categories (should not fail) */ 1508 result = rte_acl_ipv4vlan_build(acx, layout, 0); 1509 if (result == 0) { 1510 printf("Line %i: Building with 0 categories should fail!\n", 1511 __LINE__); 1512 rte_acl_free(acx); 1513 return -1; 1514 } 1515 1516 /* SSE classify test */ 1517 1518 /* cover zero categories in classify (should not fail) */ 1519 result = rte_acl_classify(acx, NULL, NULL, 0, 0); 1520 if (result != 0) { 1521 printf("Line %i: SSE classify with zero categories " 1522 "failed!\n", __LINE__); 1523 rte_acl_free(acx); 1524 return -1; 1525 } 1526 1527 /* cover invalid but positive categories in classify */ 1528 result = rte_acl_classify(acx, NULL, NULL, 0, 3); 1529 if (result == 0) { 1530 printf("Line %i: SSE classify with 3 categories " 1531 "should have failed!\n", __LINE__); 1532 rte_acl_free(acx); 1533 return -1; 1534 } 1535 1536 /* scalar classify test */ 1537 1538 /* cover zero categories in classify (should not fail) */ 1539 result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0, 1540 RTE_ACL_CLASSIFY_SCALAR); 1541 if (result != 0) { 1542 printf("Line %i: Scalar classify with zero categories " 1543 "failed!\n", __LINE__); 1544 rte_acl_free(acx); 1545 return -1; 1546 } 1547 1548 /* cover invalid but positive categories in classify */ 1549 result = rte_acl_classify(acx, NULL, NULL, 0, 3); 1550 if (result == 0) { 1551 printf("Line %i: Scalar classify with 3 categories " 1552 "should have failed!\n", __LINE__); 1553 rte_acl_free(acx); 1554 return -1; 1555 } 1556 1557 /* free ACL context */ 1558 rte_acl_free(acx); 1559 1560 1561 /** 1562 * make sure void functions don't crash with NULL parameters 1563 */ 1564 1565 rte_acl_free(NULL); 1566 1567 rte_acl_dump(NULL); 1568 1569 return 0; 1570 } 1571 1572 /** 1573 * Various tests that don't test much but improve coverage 1574 */ 1575 static int 1576 test_misc(void) 1577 { 1578 struct rte_acl_param param; 1579 struct rte_acl_ctx *acx; 1580 1581 /* create context */ 1582 memcpy(¶m, &acl_param, sizeof(param)); 1583 1584 acx = rte_acl_create(¶m); 1585 if (acx == NULL) { 1586 printf("Line %i: Error creating ACL context!\n", __LINE__); 1587 return -1; 1588 } 1589 1590 /* dump context with rules - useful for coverage */ 1591 rte_acl_list_dump(); 1592 1593 rte_acl_dump(acx); 1594 1595 rte_acl_free(acx); 1596 1597 return 0; 1598 } 1599 1600 static int 1601 test_acl(void) 1602 { 1603 if (test_invalid_parameters() < 0) 1604 return -1; 1605 if (test_invalid_rules() < 0) 1606 return -1; 1607 if (test_create_find_add() < 0) 1608 return -1; 1609 if (test_invalid_layout() < 0) 1610 return -1; 1611 if (test_misc() < 0) 1612 return -1; 1613 if (test_classify() < 0) 1614 return -1; 1615 if (test_build_ports_range() < 0) 1616 return -1; 1617 if (test_convert() < 0) 1618 return -1; 1619 1620 return 0; 1621 } 1622 1623 REGISTER_TEST_COMMAND(acl_autotest, test_acl); 1624