1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
10 #include <rte_string_fns.h>
12 #include <rte_byteorder.h>
15 #include <rte_common.h>
19 #define BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT)
21 #define LEN RTE_ACL_MAX_CATEGORIES
23 RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS);
25 struct rte_acl_param acl_param = {
27 .socket_id = SOCKET_ID_ANY,
28 .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ,
29 .max_rule_num = 0x30000,
32 struct rte_acl_ipv4vlan_rule acl_rule = {
33 .data = { .priority = 1, .category_mask = 0xff },
35 .src_port_high = UINT16_MAX,
37 .dst_port_high = UINT16_MAX,
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),
49 /* byteswap to cpu or network order */
51 bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
55 for (i = 0; i < len; i++) {
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);
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);
77 acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule)
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))
88 acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
89 struct acl_ipv4vlan_rule *ro)
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;
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 =
105 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
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 =
110 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
115 * Add ipv4vlan rules to an existing ACL context.
116 * This function is not multi-thread safe.
119 * ACL context to add patterns to.
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.
125 * Number of elements in the input array of rules.
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.
132 rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx,
133 const struct rte_acl_ipv4vlan_rule *rules,
138 struct acl_ipv4vlan_rule rv;
140 if (ctx == NULL || rules == NULL)
143 /* check input rules. */
144 for (i = 0; i != num; i++) {
145 rc = acl_ipv4vlan_check_rule(rules + i);
147 RTE_LOG(ERR, ACL, "%s: rule #%u is invalid\n",
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);
163 acl_ipv4vlan_config(struct rte_acl_config *cfg,
164 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
165 uint32_t num_categories)
167 static const struct rte_acl_field_def
168 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
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,
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,
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,
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,
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,
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,
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,
213 memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
214 cfg->num_fields = RTE_DIM(ipv4_defs);
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;
233 cfg->num_categories = num_categories;
237 * Analyze set of ipv4vlan rules and build required internal
238 * run-time structures.
239 * This function is not multi-thread safe.
242 * ACL context to build.
244 * Layout of input data to search through.
245 * @param num_categories
246 * Maximum number of categories to use in that build.
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.
254 rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx,
255 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
256 uint32_t num_categories)
258 struct rte_acl_config cfg;
260 if (ctx == NULL || layout == NULL)
263 memset(&cfg, 0, sizeof(cfg));
264 acl_ipv4vlan_config(&cfg, layout, num_categories);
265 return rte_acl_build(ctx, &cfg);
269 * Test scalar and SSE ACL lookup.
272 test_classify_run(struct rte_acl_ctx *acx)
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)];
279 /* swap all bytes in the data to network order */
280 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1);
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];
287 * these will run quite a few times, it's necessary to test code paths
288 * from num=0 to num>8
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);
294 printf("Line %i: SSE classify failed!\n", __LINE__);
298 /* check if we allow everything we should allow */
299 for (i = 0; i < (int) count; i++) {
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,
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,
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);
331 printf("Line %i: scalar classify failed!\n", __LINE__);
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,
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,
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);
370 test_classify_buid(struct rte_acl_ctx *acx,
371 const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
375 /* add rules to the context */
376 ret = rte_acl_ipv4vlan_add_rules(acx, rules, num);
378 printf("Line %i: Adding rules to ACL context failed!\n",
383 /* try building the context */
384 ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout,
385 RTE_ACL_MAX_CATEGORIES);
387 printf("Line %i: Building ACL context failed!\n", __LINE__);
394 #define TEST_CLASSIFY_ITER 4
397 * Test scalar and SSE ACL lookup.
402 struct rte_acl_ctx *acx;
405 acx = rte_acl_create(&acl_param);
407 printf("Line %i: Error creating ACL context!\n", __LINE__);
412 for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
417 rte_acl_reset_rules(acx);
419 ret = test_classify_buid(acx, acl_test_rules,
420 RTE_DIM(acl_test_rules));
422 printf("Line %i, iter: %d: "
423 "Adding rules to ACL context failed!\n",
428 ret = test_classify_run(acx);
430 printf("Line %i, iter: %d: %s failed!\n",
431 __LINE__, i, __func__);
435 /* reset rules and make sure that classify still works ok. */
436 rte_acl_reset_rules(acx);
437 ret = test_classify_run(acx);
439 printf("Line %i, iter: %d: %s failed!\n",
440 __LINE__, i, __func__);
450 test_build_ports_range(void)
452 static const struct rte_acl_ipv4vlan_rule test_rules[] = {
454 /* match all packets. */
457 .category_mask = ACL_ALLOW_MASK,
461 .src_port_high = UINT16_MAX,
463 .dst_port_high = UINT16_MAX,
466 /* match all packets with dst ports [54-65280]. */
469 .category_mask = ACL_ALLOW_MASK,
473 .src_port_high = UINT16_MAX,
475 .dst_port_high = 65280,
478 /* match all packets with dst ports [0-52]. */
481 .category_mask = ACL_ALLOW_MASK,
485 .src_port_high = UINT16_MAX,
490 /* match all packets with dst ports [53]. */
493 .category_mask = ACL_ALLOW_MASK,
497 .src_port_high = UINT16_MAX,
502 /* match all packets with dst ports [65279-65535]. */
505 .category_mask = ACL_ALLOW_MASK,
509 .src_port_high = UINT16_MAX,
510 .dst_port_low = 65279,
511 .dst_port_high = UINT16_MAX,
515 static struct ipv4_7tuple test_data[] = {
518 .ip_src = RTE_IPV4(10, 1, 1, 1),
519 .ip_dst = RTE_IPV4(192, 168, 0, 33),
525 .ip_src = RTE_IPV4(127, 84, 33, 1),
526 .ip_dst = RTE_IPV4(1, 2, 3, 4),
532 struct rte_acl_ctx *acx;
534 uint32_t results[RTE_DIM(test_data)];
535 const uint8_t *data[RTE_DIM(test_data)];
537 acx = rte_acl_create(&acl_param);
539 printf("Line %i: Error creating ACL context!\n", __LINE__);
543 /* swap all bytes in the data to network order */
544 bswap_test_data(test_data, RTE_DIM(test_data), 1);
546 /* store pointers to test data */
547 for (i = 0; i != RTE_DIM(test_data); i++)
548 data[i] = (uint8_t *)&test_data[i];
550 for (i = 0; i != RTE_DIM(test_rules); i++) {
552 ret = test_classify_buid(acx, test_rules, i + 1);
554 printf("Line %i, iter: %d: "
555 "Adding rules to ACL context failed!\n",
559 ret = rte_acl_classify(acx, data, results,
562 printf("Line %i, iter: %d: classify failed!\n",
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,
579 bswap_test_data(test_data, RTE_DIM(test_data), 0);
586 convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
587 struct acl_ipv4vlan_rule *ro)
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;
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 =
603 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
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 =
608 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
613 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
614 * RTE_ACL_FIELD_TYPE_BITMASK.
617 convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
618 struct acl_ipv4vlan_rule *ro)
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));
632 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
633 * RTE_ACL_FIELD_TYPE_RANGE.
636 convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
637 struct acl_ipv4vlan_rule *ro)
639 uint32_t hi, lo, mask;
641 convert_rule(ri, ro);
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;
647 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
648 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
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;
654 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
655 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
659 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
662 convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
663 struct acl_ipv4vlan_rule *ro)
665 struct rte_acl_field t1, t2;
667 convert_rule(ri, ro);
669 t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
670 t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
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];
677 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
678 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
682 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
685 convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
686 struct acl_ipv4vlan_rule *ro)
688 struct rte_acl_field t;
690 convert_rule(ri, ro);
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];
696 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
700 ipv4vlan_config(struct rte_acl_config *cfg,
701 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
702 uint32_t num_categories)
704 static const struct rte_acl_field_def
705 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
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,
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,
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,
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,
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,
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,
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,
750 memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
751 cfg->num_fields = RTE_DIM(ipv4_defs);
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;
770 cfg->num_categories = num_categories;
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)
781 struct acl_ipv4vlan_rule r;
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);
787 printf("Line %i: Adding rule %u to ACL context "
788 "failed with error code: %d\n",
798 convert_config(struct rte_acl_config *cfg)
800 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
804 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
807 convert_config_1(struct rte_acl_config *cfg)
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;
815 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
818 convert_config_2(struct rte_acl_config *cfg)
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;
826 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
829 convert_config_3(struct rte_acl_config *cfg)
831 struct rte_acl_field_def t1, t2;
833 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
835 t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
836 t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
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;
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;
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;
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;
860 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
863 convert_config_4(struct rte_acl_config *cfg)
865 struct rte_acl_field_def t;
867 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
869 t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
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;
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;
883 build_convert_rules(struct rte_acl_ctx *acx,
884 void (*config)(struct rte_acl_config *),
887 struct rte_acl_config cfg;
889 memset(&cfg, 0, sizeof(cfg));
891 cfg.max_size = max_size;
892 return rte_acl_build(acx, &cfg);
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 *))
901 struct rte_acl_ctx *acx;
904 static const size_t mem_sizes[] = {0, -1};
906 printf("running %s(%s)\n", __func__, desc);
908 acx = rte_acl_create(&acl_param);
910 printf("Line %i: Error creating ACL context!\n", __LINE__);
914 rc = convert_rules(acx, convert, acl_test_rules,
915 RTE_DIM(acl_test_rules));
917 printf("Line %i: Error converting ACL rules!\n", __LINE__);
919 for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
921 rc = build_convert_rules(acx, config, mem_sizes[i]);
923 printf("Line %i: Error @ build_convert_rules(%zu)!\n",
924 __LINE__, mem_sizes[i]);
928 rc = test_classify_run(acx);
930 printf("%s failed at line %i, max_size=%zu\n",
931 __func__, __LINE__, mem_sizes[i]);
941 static const struct {
943 void (*config)(struct rte_acl_config *);
944 void (*convert)(const struct rte_acl_ipv4vlan_rule *,
945 struct acl_ipv4vlan_rule *);
946 } convert_param[] = {
948 "acl_ipv4vlan_tuple",
953 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
959 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
965 "acl_ipv4vlan_tuple: swap VLAN and PORTs order",
970 "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
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);
984 printf("%s for test-case: %s failed, error code: %d;\n",
985 __func__, convert_param[i].desc, rc);
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
1002 test_invalid_layout(void)
1004 struct rte_acl_ctx *acx;
1007 uint32_t results[RTE_DIM(invalid_layout_data)];
1008 const uint8_t *data[RTE_DIM(invalid_layout_data)];
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),
1014 0, /* VLAN not used */
1016 /* src and dst addresses are swapped */
1017 offsetof(struct ipv4_7tuple, ip_dst),
1018 offsetof(struct ipv4_7tuple, ip_src),
1021 * we can't swap ports here, so we will swap
1024 offsetof(struct ipv4_7tuple, port_src),
1027 acx = rte_acl_create(&acl_param);
1029 printf("Line %i: Error creating ACL context!\n", __LINE__);
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));
1040 printf("Line %i: Adding rules to ACL context failed!\n",
1047 /* try building the context */
1048 ret = rte_acl_ipv4vlan_build(acx, layout, 1);
1050 printf("Line %i: Building ACL context failed!\n", __LINE__);
1055 /* swap all bytes in the data to network order */
1056 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
1059 for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
1060 data[i] = (uint8_t *)&invalid_layout_data[i];
1063 /* classify tuples */
1064 ret = rte_acl_classify_alg(acx, data, results,
1065 RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
1067 printf("Line %i: SSE classify failed!\n", __LINE__);
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);
1082 /* classify tuples (scalar) */
1083 ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
1084 RTE_ACL_CLASSIFY_SCALAR);
1087 printf("Line %i: Scalar classify failed!\n", __LINE__);
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);
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);
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);
1119 * Test creating and finding ACL contexts, and adding rules
1122 test_create_find_add(void)
1124 struct rte_acl_param param;
1125 struct rte_acl_ctx *acx, *acx2, *tmp;
1126 struct rte_acl_ipv4vlan_rule rules[LEN];
1128 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1130 const char *acx_name = "acx";
1131 const char *acx2_name = "acx2";
1134 /* create two contexts */
1135 memcpy(¶m, &acl_param, sizeof(param));
1136 param.max_rule_num = 2;
1138 param.name = acx_name;
1139 acx = rte_acl_create(¶m);
1141 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
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);
1153 /* try to create third one, with an existing name */
1154 param.name = acx_name;
1155 tmp = rte_acl_create(¶m);
1157 printf("Line %i: Creating context with existing name "
1165 param.name = acx2_name;
1166 tmp = rte_acl_create(¶m);
1168 printf("Line %i: Creating context with existing "
1169 "name test 2 failed!\n",
1176 /* try to find existing ACL contexts */
1177 tmp = rte_acl_find_existing(acx_name);
1179 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
1185 tmp = rte_acl_find_existing(acx2_name);
1187 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
1193 /* try to find non-existing context */
1194 tmp = rte_acl_find_existing("invalid");
1196 printf("Line %i: Non-existent ACL context found!\n", __LINE__);
1204 /* create valid (but severely limited) acx */
1205 memcpy(¶m, &acl_param, sizeof(param));
1206 param.max_rule_num = LEN;
1208 acx = rte_acl_create(¶m);
1210 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
1214 /* create dummy acl */
1215 for (i = 0; i < LEN; i++) {
1216 memcpy(&rules[i], &acl_rule,
1217 sizeof(struct rte_acl_ipv4vlan_rule));
1219 rules[i].data.userdata = i + 1;
1220 /* one rule per category */
1221 rules[i].data.category_mask = 1 << i;
1224 /* try filling up the context */
1225 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
1227 printf("Line %i: Adding %i rules to ACL context failed!\n",
1232 /* try adding to a (supposedly) full context */
1233 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
1235 printf("Line %i: Adding rules to full ACL context should"
1236 "have failed!\n", __LINE__);
1240 /* try building the context */
1241 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
1243 printf("Line %i: Building ACL context failed!\n", __LINE__);
1258 * test various invalid rules
1261 test_invalid_rules(void)
1263 struct rte_acl_ctx *acx;
1266 struct rte_acl_ipv4vlan_rule rule;
1268 acx = rte_acl_create(&acl_param);
1270 printf("Line %i: Error creating ACL context!\n", __LINE__);
1274 /* test inverted high/low source and destination ports.
1275 * originally, there was a problem with memory consumption when using
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;
1284 /* add rules to context and try to build it */
1285 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1287 printf("Line %i: Adding rules to ACL context "
1288 "should have failed!\n", __LINE__);
1292 rule.dst_port_low = 0x0;
1293 rule.dst_port_high = 0xffff;
1294 rule.src_port_low = 0xfff0;
1295 rule.src_port_high = 0x0010;
1297 /* add rules to context and try to build it */
1298 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1300 printf("Line %i: Adding rules to ACL context "
1301 "should have failed!\n", __LINE__);
1305 rule.dst_port_low = 0x0;
1306 rule.dst_port_high = 0xffff;
1307 rule.src_port_low = 0x0;
1308 rule.src_port_high = 0xffff;
1310 rule.dst_mask_len = 33;
1312 /* add rules to context and try to build it */
1313 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1315 printf("Line %i: Adding rules to ACL context "
1316 "should have failed!\n", __LINE__);
1320 rule.dst_mask_len = 0;
1321 rule.src_mask_len = 33;
1323 /* add rules to context and try to build it */
1324 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1326 printf("Line %i: Adding rules to ACL context "
1327 "should have failed!\n", __LINE__);
1342 * test functions by passing invalid or
1343 * non-workable parameters.
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.
1350 test_invalid_parameters(void)
1352 struct rte_acl_param param;
1353 struct rte_acl_ctx *acx;
1354 struct rte_acl_ipv4vlan_rule rule;
1357 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1365 acx = rte_acl_create(NULL);
1367 printf("Line %i: ACL context creation with NULL param "
1368 "should have failed!\n", __LINE__);
1373 /* zero rule size */
1374 memcpy(¶m, &acl_param, sizeof(param));
1375 param.rule_size = 0;
1377 acx = rte_acl_create(¶m);
1379 printf("Line %i: ACL context creation with zero rule len "
1380 "failed!\n", __LINE__);
1385 /* zero max rule num */
1386 memcpy(¶m, &acl_param, sizeof(param));
1387 param.max_rule_num = 0;
1389 acx = rte_acl_create(¶m);
1391 printf("Line %i: ACL context creation with zero rule num "
1392 "failed!\n", __LINE__);
1397 /* invalid NUMA node */
1398 memcpy(¶m, &acl_param, sizeof(param));
1399 param.socket_id = RTE_MAX_NUMA_NODES + 1;
1401 acx = rte_acl_create(¶m);
1403 printf("Line %i: ACL context creation with invalid NUMA "
1404 "should have failed!\n", __LINE__);
1410 memcpy(¶m, &acl_param, sizeof(param));
1413 acx = rte_acl_create(¶m);
1415 printf("Line %i: ACL context creation with NULL name "
1416 "should have failed!\n", __LINE__);
1422 * rte_acl_find_existing
1425 acx = rte_acl_find_existing(NULL);
1427 printf("Line %i: NULL ACL context found!\n", __LINE__);
1433 * rte_acl_ipv4vlan_add_rules
1436 /* initialize everything */
1437 memcpy(¶m, &acl_param, sizeof(param));
1438 acx = rte_acl_create(¶m);
1440 printf("Line %i: ACL context creation failed!\n", __LINE__);
1444 memcpy(&rule, &acl_rule, sizeof(rule));
1447 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
1449 printf("Line %i: Adding rules with NULL ACL context "
1450 "should have failed!\n", __LINE__);
1456 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
1458 printf("Line %i: Adding NULL rule to ACL context "
1459 "should have failed!\n", __LINE__);
1464 /* zero count (should succeed) */
1465 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
1467 printf("Line %i: Adding 0 rules to ACL context failed!\n",
1473 /* free ACL context */
1478 * rte_acl_ipv4vlan_build
1481 /* reinitialize context */
1482 memcpy(¶m, &acl_param, sizeof(param));
1483 acx = rte_acl_create(¶m);
1485 printf("Line %i: ACL context creation failed!\n", __LINE__);
1490 result = rte_acl_ipv4vlan_build(NULL, layout, 1);
1492 printf("Line %i: Building with NULL context "
1493 "should have failed!\n", __LINE__);
1499 result = rte_acl_ipv4vlan_build(acx, NULL, 1);
1501 printf("Line %i: Building with NULL layout "
1502 "should have failed!\n", __LINE__);
1507 /* zero categories (should not fail) */
1508 result = rte_acl_ipv4vlan_build(acx, layout, 0);
1510 printf("Line %i: Building with 0 categories should fail!\n",
1516 /* SSE classify test */
1518 /* cover zero categories in classify (should not fail) */
1519 result = rte_acl_classify(acx, NULL, NULL, 0, 0);
1521 printf("Line %i: SSE classify with zero categories "
1522 "failed!\n", __LINE__);
1527 /* cover invalid but positive categories in classify */
1528 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1530 printf("Line %i: SSE classify with 3 categories "
1531 "should have failed!\n", __LINE__);
1536 /* scalar classify test */
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);
1542 printf("Line %i: Scalar classify with zero categories "
1543 "failed!\n", __LINE__);
1548 /* cover invalid but positive categories in classify */
1549 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1551 printf("Line %i: Scalar classify with 3 categories "
1552 "should have failed!\n", __LINE__);
1557 /* free ACL context */
1562 * make sure void functions don't crash with NULL parameters
1573 * Various tests that don't test much but improve coverage
1578 struct rte_acl_param param;
1579 struct rte_acl_ctx *acx;
1581 /* create context */
1582 memcpy(¶m, &acl_param, sizeof(param));
1584 acx = rte_acl_create(¶m);
1586 printf("Line %i: Error creating ACL context!\n", __LINE__);
1590 /* dump context with rules - useful for coverage */
1591 rte_acl_list_dump();
1603 if (test_invalid_parameters() < 0)
1605 if (test_invalid_rules() < 0)
1607 if (test_create_find_add() < 0)
1609 if (test_invalid_layout() < 0)
1611 if (test_misc() < 0)
1613 if (test_classify() < 0)
1615 if (test_build_ports_range() < 0)
1617 if (test_convert() < 0)
1623 REGISTER_TEST_COMMAND(acl_autotest, test_acl);