]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/app/test/test_acl.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / app / test / test_acl.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
7c673cae
FG
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
23RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS);
24
25struct 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
32struct 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
40const 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 */
50static void
51bswap_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
76static int
77acl_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
87static void
88acl_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 */
131static int
132rte_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
162static void
163acl_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 */
253static int
254rte_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 */
271static int
f67539c2
TL
272test_classify_run(struct rte_acl_ctx *acx, struct ipv4_7tuple test_data[],
273 size_t dim)
7c673cae
FG
274{
275 int ret, i;
276 uint32_t result, count;
f67539c2
TL
277 uint32_t results[dim * RTE_ACL_MAX_CATEGORIES];
278 const uint8_t *data[dim];
7c673cae 279 /* swap all bytes in the data to network order */
f67539c2 280 bswap_test_data(test_data, dim, 1);
7c673cae
FG
281
282 /* store pointers to test data */
f67539c2
TL
283 for (i = 0; i < (int) dim; i++)
284 data[i] = (uint8_t *)&test_data[i];
7c673cae
FG
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 */
f67539c2 290 for (count = 0; count <= dim; count++) {
7c673cae
FG
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];
f67539c2 302 if (result != test_data[i].allow) {
7c673cae
FG
303 printf("Line %i: Error in allow results at %i "
304 "(expected %"PRIu32" got %"PRIu32")!\n",
f67539c2 305 __LINE__, i, test_data[i].allow,
7c673cae
FG
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];
f67539c2 315 if (result != test_data[i].deny) {
7c673cae
FG
316 printf("Line %i: Error in deny results at %i "
317 "(expected %"PRIu32" got %"PRIu32")!\n",
f67539c2 318 __LINE__, i, test_data[i].deny,
7c673cae
FG
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,
f67539c2 328 dim, RTE_ACL_MAX_CATEGORIES,
7c673cae
FG
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 */
f67539c2 336 for (i = 0; i < (int) dim; i++) {
7c673cae 337 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
f67539c2 338 if (result != test_data[i].allow) {
7c673cae
FG
339 printf("Line %i: Error in allow results at %i "
340 "(expected %"PRIu32" got %"PRIu32")!\n",
f67539c2 341 __LINE__, i, test_data[i].allow,
7c673cae
FG
342 result);
343 ret = -EINVAL;
344 goto err;
345 }
346 }
347
348 /* check if we deny everything we should deny */
f67539c2 349 for (i = 0; i < (int) dim; i++) {
7c673cae 350 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
f67539c2 351 if (result != test_data[i].deny) {
7c673cae
FG
352 printf("Line %i: Error in deny results at %i "
353 "(expected %"PRIu32" got %"PRIu32")!\n",
f67539c2 354 __LINE__, i, test_data[i].deny,
7c673cae
FG
355 result);
356 ret = -EINVAL;
357 goto err;
358 }
359 }
360
361 ret = 0;
362
363err:
364 /* swap data back to cpu order so that next time tests don't fail */
f67539c2 365 bswap_test_data(test_data, dim, 0);
7c673cae
FG
366 return ret;
367}
368
369static int
370test_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 */
399static int
400test_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
f67539c2
TL
428 ret = test_classify_run(acx, acl_test_data,
429 RTE_DIM(acl_test_data));
7c673cae
FG
430 if (ret != 0) {
431 printf("Line %i, iter: %d: %s failed!\n",
432 __LINE__, i, __func__);
433 break;
434 }
435
436 /* reset rules and make sure that classify still works ok. */
437 rte_acl_reset_rules(acx);
f67539c2
TL
438 ret = test_classify_run(acx, acl_test_data,
439 RTE_DIM(acl_test_data));
7c673cae
FG
440 if (ret != 0) {
441 printf("Line %i, iter: %d: %s failed!\n",
442 __LINE__, i, __func__);
443 break;
444 }
445 }
446
447 rte_acl_free(acx);
448 return ret;
449}
450
451static int
452test_build_ports_range(void)
453{
454 static const struct rte_acl_ipv4vlan_rule test_rules[] = {
455 {
456 /* match all packets. */
457 .data = {
458 .userdata = 1,
459 .category_mask = ACL_ALLOW_MASK,
460 .priority = 101,
461 },
462 .src_port_low = 0,
463 .src_port_high = UINT16_MAX,
464 .dst_port_low = 0,
465 .dst_port_high = UINT16_MAX,
466 },
467 {
468 /* match all packets with dst ports [54-65280]. */
469 .data = {
470 .userdata = 2,
471 .category_mask = ACL_ALLOW_MASK,
472 .priority = 102,
473 },
474 .src_port_low = 0,
475 .src_port_high = UINT16_MAX,
476 .dst_port_low = 54,
477 .dst_port_high = 65280,
478 },
479 {
480 /* match all packets with dst ports [0-52]. */
481 .data = {
482 .userdata = 3,
483 .category_mask = ACL_ALLOW_MASK,
484 .priority = 103,
485 },
486 .src_port_low = 0,
487 .src_port_high = UINT16_MAX,
488 .dst_port_low = 0,
489 .dst_port_high = 52,
490 },
491 {
492 /* match all packets with dst ports [53]. */
493 .data = {
494 .userdata = 4,
495 .category_mask = ACL_ALLOW_MASK,
496 .priority = 99,
497 },
498 .src_port_low = 0,
499 .src_port_high = UINT16_MAX,
500 .dst_port_low = 53,
501 .dst_port_high = 53,
502 },
503 {
504 /* match all packets with dst ports [65279-65535]. */
505 .data = {
506 .userdata = 5,
507 .category_mask = ACL_ALLOW_MASK,
508 .priority = 98,
509 },
510 .src_port_low = 0,
511 .src_port_high = UINT16_MAX,
512 .dst_port_low = 65279,
513 .dst_port_high = UINT16_MAX,
514 },
515 };
516
517 static struct ipv4_7tuple test_data[] = {
518 {
519 .proto = 6,
f67539c2
TL
520 .ip_src = RTE_IPV4(10, 1, 1, 1),
521 .ip_dst = RTE_IPV4(192, 168, 0, 33),
7c673cae
FG
522 .port_dst = 53,
523 .allow = 1,
524 },
525 {
526 .proto = 6,
f67539c2
TL
527 .ip_src = RTE_IPV4(127, 84, 33, 1),
528 .ip_dst = RTE_IPV4(1, 2, 3, 4),
7c673cae
FG
529 .port_dst = 65281,
530 .allow = 1,
531 },
532 };
533
534 struct rte_acl_ctx *acx;
535 int32_t ret, i, j;
536 uint32_t results[RTE_DIM(test_data)];
537 const uint8_t *data[RTE_DIM(test_data)];
538
539 acx = rte_acl_create(&acl_param);
540 if (acx == NULL) {
541 printf("Line %i: Error creating ACL context!\n", __LINE__);
542 return -1;
543 }
544
545 /* swap all bytes in the data to network order */
546 bswap_test_data(test_data, RTE_DIM(test_data), 1);
547
548 /* store pointers to test data */
549 for (i = 0; i != RTE_DIM(test_data); i++)
550 data[i] = (uint8_t *)&test_data[i];
551
552 for (i = 0; i != RTE_DIM(test_rules); i++) {
553 rte_acl_reset(acx);
554 ret = test_classify_buid(acx, test_rules, i + 1);
555 if (ret != 0) {
556 printf("Line %i, iter: %d: "
557 "Adding rules to ACL context failed!\n",
558 __LINE__, i);
559 break;
560 }
561 ret = rte_acl_classify(acx, data, results,
562 RTE_DIM(data), 1);
563 if (ret != 0) {
564 printf("Line %i, iter: %d: classify failed!\n",
565 __LINE__, i);
566 break;
567 }
568
569 /* check results */
570 for (j = 0; j != RTE_DIM(results); j++) {
571 if (results[j] != test_data[j].allow) {
572 printf("Line %i: Error in allow results at %i "
573 "(expected %"PRIu32" got %"PRIu32")!\n",
574 __LINE__, j, test_data[j].allow,
575 results[j]);
576 ret = -EINVAL;
577 }
578 }
579 }
580
581 bswap_test_data(test_data, RTE_DIM(test_data), 0);
582
583 rte_acl_free(acx);
584 return ret;
585}
586
587static void
588convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
589 struct acl_ipv4vlan_rule *ro)
590{
591 ro->data = ri->data;
592
593 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
594 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
595 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
596 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
597 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
598 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
599 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
600
601 ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
602 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
603 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
604 ri->domain_mask;
605 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
606 ri->src_mask_len;
607 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
608 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
609 ri->src_port_high;
610 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
611 ri->dst_port_high;
612}
613
614/*
615 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
616 * RTE_ACL_FIELD_TYPE_BITMASK.
617 */
618static void
619convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
620 struct acl_ipv4vlan_rule *ro)
621{
622 uint32_t v;
623
624 convert_rule(ri, ro);
625 v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
626 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
627 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
628 v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
629 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 =
630 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
631}
632
633/*
634 * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
635 * RTE_ACL_FIELD_TYPE_RANGE.
636 */
637static void
638convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
639 struct acl_ipv4vlan_rule *ro)
640{
641 uint32_t hi, lo, mask;
642
643 convert_rule(ri, ro);
644
645 mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
646 mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
647 lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask;
648 hi = lo + ~mask;
649 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
650 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
651
652 mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
653 mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
654 lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask;
655 hi = lo + ~mask;
656 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
657 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
658}
659
660/*
661 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
662 */
663static void
664convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
665 struct acl_ipv4vlan_rule *ro)
666{
667 struct rte_acl_field t1, t2;
668
669 convert_rule(ri, ro);
670
671 t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
672 t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
673
674 ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
675 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD];
676 ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
677 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD];
678
679 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
680 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
681}
682
683/*
684 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
685 */
686static void
687convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
688 struct acl_ipv4vlan_rule *ro)
689{
690 struct rte_acl_field t;
691
692 convert_rule(ri, ro);
693
694 t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD];
695 ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] =
696 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD];
697
698 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
699}
700
701static void
702ipv4vlan_config(struct rte_acl_config *cfg,
703 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
704 uint32_t num_categories)
705{
706 static const struct rte_acl_field_def
707 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
708 {
709 .type = RTE_ACL_FIELD_TYPE_BITMASK,
710 .size = sizeof(uint8_t),
711 .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
712 .input_index = RTE_ACL_IPV4VLAN_PROTO,
713 },
714 {
715 .type = RTE_ACL_FIELD_TYPE_BITMASK,
716 .size = sizeof(uint16_t),
717 .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
718 .input_index = RTE_ACL_IPV4VLAN_VLAN,
719 },
720 {
721 .type = RTE_ACL_FIELD_TYPE_BITMASK,
722 .size = sizeof(uint16_t),
723 .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
724 .input_index = RTE_ACL_IPV4VLAN_VLAN,
725 },
726 {
727 .type = RTE_ACL_FIELD_TYPE_MASK,
728 .size = sizeof(uint32_t),
729 .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
730 .input_index = RTE_ACL_IPV4VLAN_SRC,
731 },
732 {
733 .type = RTE_ACL_FIELD_TYPE_MASK,
734 .size = sizeof(uint32_t),
735 .field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
736 .input_index = RTE_ACL_IPV4VLAN_DST,
737 },
738 {
739 .type = RTE_ACL_FIELD_TYPE_RANGE,
740 .size = sizeof(uint16_t),
741 .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
742 .input_index = RTE_ACL_IPV4VLAN_PORTS,
743 },
744 {
745 .type = RTE_ACL_FIELD_TYPE_RANGE,
746 .size = sizeof(uint16_t),
747 .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
748 .input_index = RTE_ACL_IPV4VLAN_PORTS,
749 },
750 };
751
752 memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
753 cfg->num_fields = RTE_DIM(ipv4_defs);
754
755 cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
756 layout[RTE_ACL_IPV4VLAN_PROTO];
757 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
758 layout[RTE_ACL_IPV4VLAN_VLAN];
759 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
760 layout[RTE_ACL_IPV4VLAN_VLAN] +
761 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
762 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
763 layout[RTE_ACL_IPV4VLAN_SRC];
764 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
765 layout[RTE_ACL_IPV4VLAN_DST];
766 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
767 layout[RTE_ACL_IPV4VLAN_PORTS];
768 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
769 layout[RTE_ACL_IPV4VLAN_PORTS] +
770 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
771
772 cfg->num_categories = num_categories;
773}
774
775static int
776convert_rules(struct rte_acl_ctx *acx,
777 void (*convert)(const struct rte_acl_ipv4vlan_rule *,
778 struct acl_ipv4vlan_rule *),
779 const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
780{
781 int32_t rc;
782 uint32_t i;
783 struct acl_ipv4vlan_rule r;
784
785 for (i = 0; i != num; i++) {
786 convert(rules + i, &r);
787 rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
788 if (rc != 0) {
789 printf("Line %i: Adding rule %u to ACL context "
790 "failed with error code: %d\n",
791 __LINE__, i, rc);
792 return rc;
793 }
794 }
795
796 return 0;
797}
798
799static void
800convert_config(struct rte_acl_config *cfg)
801{
802 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
803}
804
805/*
806 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
807 */
808static void
809convert_config_1(struct rte_acl_config *cfg)
810{
811 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
812 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
813 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
814}
815
816/*
817 * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
818 */
819static void
820convert_config_2(struct rte_acl_config *cfg)
821{
822 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
823 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
824 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
825}
826
827/*
828 * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
829 */
830static void
831convert_config_3(struct rte_acl_config *cfg)
832{
833 struct rte_acl_field_def t1, t2;
834
835 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
836
837 t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
838 t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
839
840 /* swap VLAN1 and SRCP rule definition. */
841 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
842 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD];
843 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index;
844 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index;
845
846 /* swap VLAN2 and DSTP rule definition. */
847 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
848 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD];
849 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index;
850 cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index;
851
852 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type;
853 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size;
854 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset;
855
856 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type;
857 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size;
858 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset;
859}
860
861/*
862 * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
863 */
864static void
865convert_config_4(struct rte_acl_config *cfg)
866{
867 struct rte_acl_field_def t;
868
869 ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
870
871 t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
872
873 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] =
874 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD];
875 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index;
876 cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index;
877
878 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type;
879 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size;
880 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset;
881}
882
883
884static int
885build_convert_rules(struct rte_acl_ctx *acx,
886 void (*config)(struct rte_acl_config *),
887 size_t max_size)
888{
889 struct rte_acl_config cfg;
890
891 memset(&cfg, 0, sizeof(cfg));
892 config(&cfg);
893 cfg.max_size = max_size;
894 return rte_acl_build(acx, &cfg);
895}
896
897static int
898test_convert_rules(const char *desc,
899 void (*config)(struct rte_acl_config *),
900 void (*convert)(const struct rte_acl_ipv4vlan_rule *,
901 struct acl_ipv4vlan_rule *))
902{
903 struct rte_acl_ctx *acx;
904 int32_t rc;
905 uint32_t i;
906 static const size_t mem_sizes[] = {0, -1};
907
908 printf("running %s(%s)\n", __func__, desc);
909
910 acx = rte_acl_create(&acl_param);
911 if (acx == NULL) {
912 printf("Line %i: Error creating ACL context!\n", __LINE__);
913 return -1;
914 }
915
916 rc = convert_rules(acx, convert, acl_test_rules,
917 RTE_DIM(acl_test_rules));
918 if (rc != 0)
919 printf("Line %i: Error converting ACL rules!\n", __LINE__);
920
921 for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
922
923 rc = build_convert_rules(acx, config, mem_sizes[i]);
924 if (rc != 0) {
925 printf("Line %i: Error @ build_convert_rules(%zu)!\n",
926 __LINE__, mem_sizes[i]);
927 break;
928 }
929
f67539c2
TL
930 rc = test_classify_run(acx, acl_test_data,
931 RTE_DIM(acl_test_data));
7c673cae
FG
932 if (rc != 0)
933 printf("%s failed at line %i, max_size=%zu\n",
934 __func__, __LINE__, mem_sizes[i]);
935 }
936
937 rte_acl_free(acx);
938 return rc;
939}
940
941static int
942test_convert(void)
943{
944 static const struct {
945 const char *desc;
946 void (*config)(struct rte_acl_config *);
947 void (*convert)(const struct rte_acl_ipv4vlan_rule *,
948 struct acl_ipv4vlan_rule *);
949 } convert_param[] = {
950 {
951 "acl_ipv4vlan_tuple",
952 convert_config,
953 convert_rule,
954 },
955 {
956 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
957 "for IPv4",
958 convert_config_1,
959 convert_rule_1,
960 },
961 {
962 "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
963 "for IPv4",
964 convert_config_2,
965 convert_rule_2,
966 },
967 {
968 "acl_ipv4vlan_tuple: swap VLAN and PORTs order",
969 convert_config_3,
970 convert_rule_3,
971 },
972 {
973 "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
974 convert_config_4,
975 convert_rule_4,
976 },
977 };
978
979 uint32_t i;
980 int32_t rc;
981
982 for (i = 0; i != RTE_DIM(convert_param); i++) {
983 rc = test_convert_rules(convert_param[i].desc,
984 convert_param[i].config,
985 convert_param[i].convert);
986 if (rc != 0) {
987 printf("%s for test-case: %s failed, error code: %d;\n",
988 __func__, convert_param[i].desc, rc);
989 return rc;
990 }
991 }
992
993 return 0;
994}
995
996/*
997 * Test wrong layout behavior
998 * This test supplies the ACL context with invalid layout, which results in
999 * ACL matching the wrong stuff. However, it should match the wrong stuff
1000 * the right way. We switch around source and destination addresses,
1001 * source and destination ports, and protocol will point to first byte of
1002 * destination port.
1003 */
1004static int
1005test_invalid_layout(void)
1006{
1007 struct rte_acl_ctx *acx;
1008 int ret, i;
1009
1010 uint32_t results[RTE_DIM(invalid_layout_data)];
1011 const uint8_t *data[RTE_DIM(invalid_layout_data)];
1012
1013 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
1014 /* proto points to destination port's first byte */
1015 offsetof(struct ipv4_7tuple, port_dst),
1016
1017 0, /* VLAN not used */
1018
1019 /* src and dst addresses are swapped */
1020 offsetof(struct ipv4_7tuple, ip_dst),
1021 offsetof(struct ipv4_7tuple, ip_src),
1022
1023 /*
1024 * we can't swap ports here, so we will swap
1025 * them in the data
1026 */
1027 offsetof(struct ipv4_7tuple, port_src),
1028 };
1029
1030 acx = rte_acl_create(&acl_param);
1031 if (acx == NULL) {
1032 printf("Line %i: Error creating ACL context!\n", __LINE__);
1033 return -1;
1034 }
1035
1036 /* putting a lot of rules into the context results in greater
1037 * coverage numbers. it doesn't matter if they are identical */
1038 for (i = 0; i < 1000; i++) {
1039 /* add rules to the context */
1040 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
1041 RTE_DIM(invalid_layout_rules));
1042 if (ret != 0) {
1043 printf("Line %i: Adding rules to ACL context failed!\n",
1044 __LINE__);
1045 rte_acl_free(acx);
1046 return -1;
1047 }
1048 }
1049
1050 /* try building the context */
1051 ret = rte_acl_ipv4vlan_build(acx, layout, 1);
1052 if (ret != 0) {
1053 printf("Line %i: Building ACL context failed!\n", __LINE__);
1054 rte_acl_free(acx);
1055 return -1;
1056 }
1057
1058 /* swap all bytes in the data to network order */
1059 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
1060
1061 /* prepare data */
1062 for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
1063 data[i] = (uint8_t *)&invalid_layout_data[i];
1064 }
1065
1066 /* classify tuples */
1067 ret = rte_acl_classify_alg(acx, data, results,
1068 RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
1069 if (ret != 0) {
1070 printf("Line %i: SSE classify failed!\n", __LINE__);
1071 rte_acl_free(acx);
1072 return -1;
1073 }
1074
1075 for (i = 0; i < (int) RTE_DIM(results); i++) {
1076 if (results[i] != invalid_layout_data[i].allow) {
1077 printf("Line %i: Wrong results at %i "
1078 "(result=%u, should be %u)!\n",
1079 __LINE__, i, results[i],
1080 invalid_layout_data[i].allow);
1081 goto err;
1082 }
1083 }
1084
1085 /* classify tuples (scalar) */
1086 ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
1087 RTE_ACL_CLASSIFY_SCALAR);
1088
1089 if (ret != 0) {
1090 printf("Line %i: Scalar classify failed!\n", __LINE__);
1091 rte_acl_free(acx);
1092 return -1;
1093 }
1094
1095 for (i = 0; i < (int) RTE_DIM(results); i++) {
1096 if (results[i] != invalid_layout_data[i].allow) {
1097 printf("Line %i: Wrong results at %i "
1098 "(result=%u, should be %u)!\n",
1099 __LINE__, i, results[i],
1100 invalid_layout_data[i].allow);
1101 goto err;
1102 }
1103 }
1104
1105 rte_acl_free(acx);
1106
1107 /* swap data back to cpu order so that next time tests don't fail */
1108 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
1109
1110 return 0;
1111err:
1112
1113 /* swap data back to cpu order so that next time tests don't fail */
1114 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
1115
1116 rte_acl_free(acx);
1117
1118 return -1;
1119}
1120
1121/*
1122 * Test creating and finding ACL contexts, and adding rules
1123 */
1124static int
1125test_create_find_add(void)
1126{
1127 struct rte_acl_param param;
1128 struct rte_acl_ctx *acx, *acx2, *tmp;
1129 struct rte_acl_ipv4vlan_rule rules[LEN];
1130
1131 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1132
1133 const char *acx_name = "acx";
1134 const char *acx2_name = "acx2";
1135 int i, ret;
1136
1137 /* create two contexts */
1138 memcpy(&param, &acl_param, sizeof(param));
1139 param.max_rule_num = 2;
1140
1141 param.name = acx_name;
1142 acx = rte_acl_create(&param);
1143 if (acx == NULL) {
1144 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
1145 return -1;
1146 }
1147
1148 param.name = acx2_name;
1149 acx2 = rte_acl_create(&param);
1150 if (acx2 == NULL || acx2 == acx) {
1151 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
1152 rte_acl_free(acx);
1153 return -1;
1154 }
1155
1156 /* try to create third one, with an existing name */
1157 param.name = acx_name;
1158 tmp = rte_acl_create(&param);
1159 if (tmp != acx) {
1160 printf("Line %i: Creating context with existing name "
1161 "test failed!\n",
1162 __LINE__);
1163 if (tmp)
1164 rte_acl_free(tmp);
1165 goto err;
1166 }
1167
1168 param.name = acx2_name;
1169 tmp = rte_acl_create(&param);
1170 if (tmp != acx2) {
1171 printf("Line %i: Creating context with existing "
1172 "name test 2 failed!\n",
1173 __LINE__);
1174 if (tmp)
1175 rte_acl_free(tmp);
1176 goto err;
1177 }
1178
1179 /* try to find existing ACL contexts */
1180 tmp = rte_acl_find_existing(acx_name);
1181 if (tmp != acx) {
1182 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
1183 if (tmp)
1184 rte_acl_free(tmp);
1185 goto err;
1186 }
1187
1188 tmp = rte_acl_find_existing(acx2_name);
1189 if (tmp != acx2) {
1190 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
1191 if (tmp)
1192 rte_acl_free(tmp);
1193 goto err;
1194 }
1195
1196 /* try to find non-existing context */
1197 tmp = rte_acl_find_existing("invalid");
1198 if (tmp != NULL) {
1199 printf("Line %i: Non-existent ACL context found!\n", __LINE__);
1200 goto err;
1201 }
1202
1203 /* free context */
1204 rte_acl_free(acx);
1205
1206
1207 /* create valid (but severely limited) acx */
1208 memcpy(&param, &acl_param, sizeof(param));
1209 param.max_rule_num = LEN;
1210
1211 acx = rte_acl_create(&param);
1212 if (acx == NULL) {
1213 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
1214 goto err;
1215 }
1216
1217 /* create dummy acl */
1218 for (i = 0; i < LEN; i++) {
1219 memcpy(&rules[i], &acl_rule,
1220 sizeof(struct rte_acl_ipv4vlan_rule));
1221 /* skip zero */
1222 rules[i].data.userdata = i + 1;
1223 /* one rule per category */
1224 rules[i].data.category_mask = 1 << i;
1225 }
1226
1227 /* try filling up the context */
1228 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
1229 if (ret != 0) {
1230 printf("Line %i: Adding %i rules to ACL context failed!\n",
1231 __LINE__, LEN);
1232 goto err;
1233 }
1234
1235 /* try adding to a (supposedly) full context */
1236 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
1237 if (ret == 0) {
1238 printf("Line %i: Adding rules to full ACL context should"
1239 "have failed!\n", __LINE__);
1240 goto err;
1241 }
1242
1243 /* try building the context */
1244 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
1245 if (ret != 0) {
1246 printf("Line %i: Building ACL context failed!\n", __LINE__);
1247 goto err;
1248 }
1249
1250 rte_acl_free(acx);
1251 rte_acl_free(acx2);
1252
1253 return 0;
1254err:
1255 rte_acl_free(acx);
1256 rte_acl_free(acx2);
1257 return -1;
1258}
1259
1260/*
1261 * test various invalid rules
1262 */
1263static int
1264test_invalid_rules(void)
1265{
1266 struct rte_acl_ctx *acx;
1267 int ret;
1268
1269 struct rte_acl_ipv4vlan_rule rule;
1270
1271 acx = rte_acl_create(&acl_param);
1272 if (acx == NULL) {
1273 printf("Line %i: Error creating ACL context!\n", __LINE__);
1274 return -1;
1275 }
1276
1277 /* test inverted high/low source and destination ports.
1278 * originally, there was a problem with memory consumption when using
1279 * such rules.
1280 */
1281 /* create dummy acl */
1282 memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
1283 rule.data.userdata = 1;
1284 rule.dst_port_low = 0xfff0;
1285 rule.dst_port_high = 0x0010;
1286
1287 /* add rules to context and try to build it */
1288 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1289 if (ret == 0) {
1290 printf("Line %i: Adding rules to ACL context "
1291 "should have failed!\n", __LINE__);
1292 goto err;
1293 }
1294
1295 rule.dst_port_low = 0x0;
1296 rule.dst_port_high = 0xffff;
1297 rule.src_port_low = 0xfff0;
1298 rule.src_port_high = 0x0010;
1299
1300 /* add rules to context and try to build it */
1301 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1302 if (ret == 0) {
1303 printf("Line %i: Adding rules to ACL context "
1304 "should have failed!\n", __LINE__);
1305 goto err;
1306 }
1307
1308 rule.dst_port_low = 0x0;
1309 rule.dst_port_high = 0xffff;
1310 rule.src_port_low = 0x0;
1311 rule.src_port_high = 0xffff;
1312
1313 rule.dst_mask_len = 33;
1314
1315 /* add rules to context and try to build it */
1316 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1317 if (ret == 0) {
1318 printf("Line %i: Adding rules to ACL context "
1319 "should have failed!\n", __LINE__);
1320 goto err;
1321 }
1322
1323 rule.dst_mask_len = 0;
1324 rule.src_mask_len = 33;
1325
1326 /* add rules to context and try to build it */
1327 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1328 if (ret == 0) {
1329 printf("Line %i: Adding rules to ACL context "
1330 "should have failed!\n", __LINE__);
1331 goto err;
1332 }
1333
7c673cae
FG
1334 rte_acl_free(acx);
1335
1336 return 0;
1337
1338err:
1339 rte_acl_free(acx);
1340
1341 return -1;
1342}
1343
1344/*
1345 * test functions by passing invalid or
1346 * non-workable parameters.
1347 *
1348 * we do very limited testing of classify functions here
1349 * because those are performance-critical and
1350 * thus don't do much parameter checking.
1351 */
1352static int
1353test_invalid_parameters(void)
1354{
1355 struct rte_acl_param param;
1356 struct rte_acl_ctx *acx;
1357 struct rte_acl_ipv4vlan_rule rule;
1358 int result;
1359
1360 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1361
1362
1363 /**
1364 * rte_ac_create()
1365 */
1366
1367 /* NULL param */
1368 acx = rte_acl_create(NULL);
1369 if (acx != NULL) {
1370 printf("Line %i: ACL context creation with NULL param "
1371 "should have failed!\n", __LINE__);
1372 rte_acl_free(acx);
1373 return -1;
1374 }
1375
1376 /* zero rule size */
1377 memcpy(&param, &acl_param, sizeof(param));
1378 param.rule_size = 0;
1379
1380 acx = rte_acl_create(&param);
1381 if (acx == NULL) {
1382 printf("Line %i: ACL context creation with zero rule len "
1383 "failed!\n", __LINE__);
1384 return -1;
1385 } else
1386 rte_acl_free(acx);
1387
1388 /* zero max rule num */
1389 memcpy(&param, &acl_param, sizeof(param));
1390 param.max_rule_num = 0;
1391
1392 acx = rte_acl_create(&param);
1393 if (acx == NULL) {
1394 printf("Line %i: ACL context creation with zero rule num "
1395 "failed!\n", __LINE__);
1396 return -1;
1397 } else
1398 rte_acl_free(acx);
1399
f67539c2
TL
1400 if (rte_eal_has_hugepages()) {
1401 /* invalid NUMA node */
1402 memcpy(&param, &acl_param, sizeof(param));
1403 param.socket_id = RTE_MAX_NUMA_NODES + 1;
7c673cae 1404
f67539c2
TL
1405 acx = rte_acl_create(&param);
1406 if (acx != NULL) {
1407 printf("Line %i: ACL context creation with invalid "
1408 "NUMA should have failed!\n", __LINE__);
1409 rte_acl_free(acx);
1410 return -1;
1411 }
7c673cae
FG
1412 }
1413
1414 /* NULL name */
1415 memcpy(&param, &acl_param, sizeof(param));
1416 param.name = NULL;
1417
1418 acx = rte_acl_create(&param);
1419 if (acx != NULL) {
1420 printf("Line %i: ACL context creation with NULL name "
1421 "should have failed!\n", __LINE__);
1422 rte_acl_free(acx);
1423 return -1;
1424 }
1425
1426 /**
1427 * rte_acl_find_existing
1428 */
1429
1430 acx = rte_acl_find_existing(NULL);
1431 if (acx != NULL) {
1432 printf("Line %i: NULL ACL context found!\n", __LINE__);
1433 rte_acl_free(acx);
1434 return -1;
1435 }
1436
1437 /**
1438 * rte_acl_ipv4vlan_add_rules
1439 */
1440
1441 /* initialize everything */
1442 memcpy(&param, &acl_param, sizeof(param));
1443 acx = rte_acl_create(&param);
1444 if (acx == NULL) {
1445 printf("Line %i: ACL context creation failed!\n", __LINE__);
1446 return -1;
1447 }
1448
1449 memcpy(&rule, &acl_rule, sizeof(rule));
1450
1451 /* NULL context */
1452 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
1453 if (result == 0) {
1454 printf("Line %i: Adding rules with NULL ACL context "
1455 "should have failed!\n", __LINE__);
1456 rte_acl_free(acx);
1457 return -1;
1458 }
1459
1460 /* NULL rule */
1461 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
1462 if (result == 0) {
1463 printf("Line %i: Adding NULL rule to ACL context "
1464 "should have failed!\n", __LINE__);
1465 rte_acl_free(acx);
1466 return -1;
1467 }
1468
1469 /* zero count (should succeed) */
1470 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
1471 if (result != 0) {
1472 printf("Line %i: Adding 0 rules to ACL context failed!\n",
1473 __LINE__);
1474 rte_acl_free(acx);
1475 return -1;
1476 }
1477
1478 /* free ACL context */
1479 rte_acl_free(acx);
1480
7c673cae
FG
1481
1482 /**
1483 * rte_acl_ipv4vlan_build
1484 */
1485
1486 /* reinitialize context */
1487 memcpy(&param, &acl_param, sizeof(param));
1488 acx = rte_acl_create(&param);
1489 if (acx == NULL) {
1490 printf("Line %i: ACL context creation failed!\n", __LINE__);
1491 return -1;
1492 }
1493
1494 /* NULL context */
1495 result = rte_acl_ipv4vlan_build(NULL, layout, 1);
1496 if (result == 0) {
1497 printf("Line %i: Building with NULL context "
1498 "should have failed!\n", __LINE__);
1499 rte_acl_free(acx);
1500 return -1;
1501 }
1502
1503 /* NULL layout */
1504 result = rte_acl_ipv4vlan_build(acx, NULL, 1);
1505 if (result == 0) {
1506 printf("Line %i: Building with NULL layout "
1507 "should have failed!\n", __LINE__);
1508 rte_acl_free(acx);
1509 return -1;
1510 }
1511
1512 /* zero categories (should not fail) */
1513 result = rte_acl_ipv4vlan_build(acx, layout, 0);
1514 if (result == 0) {
1515 printf("Line %i: Building with 0 categories should fail!\n",
1516 __LINE__);
1517 rte_acl_free(acx);
1518 return -1;
1519 }
1520
1521 /* SSE classify test */
1522
1523 /* cover zero categories in classify (should not fail) */
1524 result = rte_acl_classify(acx, NULL, NULL, 0, 0);
1525 if (result != 0) {
1526 printf("Line %i: SSE classify with zero categories "
1527 "failed!\n", __LINE__);
1528 rte_acl_free(acx);
1529 return -1;
1530 }
1531
1532 /* cover invalid but positive categories in classify */
1533 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1534 if (result == 0) {
1535 printf("Line %i: SSE classify with 3 categories "
1536 "should have failed!\n", __LINE__);
1537 rte_acl_free(acx);
1538 return -1;
1539 }
1540
1541 /* scalar classify test */
1542
1543 /* cover zero categories in classify (should not fail) */
1544 result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0,
1545 RTE_ACL_CLASSIFY_SCALAR);
1546 if (result != 0) {
1547 printf("Line %i: Scalar classify with zero categories "
1548 "failed!\n", __LINE__);
1549 rte_acl_free(acx);
1550 return -1;
1551 }
1552
1553 /* cover invalid but positive categories in classify */
1554 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1555 if (result == 0) {
1556 printf("Line %i: Scalar classify with 3 categories "
1557 "should have failed!\n", __LINE__);
1558 rte_acl_free(acx);
1559 return -1;
1560 }
1561
1562 /* free ACL context */
1563 rte_acl_free(acx);
1564
1565
1566 /**
1567 * make sure void functions don't crash with NULL parameters
1568 */
1569
1570 rte_acl_free(NULL);
1571
1572 rte_acl_dump(NULL);
1573
1574 return 0;
1575}
1576
1577/**
1578 * Various tests that don't test much but improve coverage
1579 */
1580static int
1581test_misc(void)
1582{
1583 struct rte_acl_param param;
1584 struct rte_acl_ctx *acx;
1585
1586 /* create context */
1587 memcpy(&param, &acl_param, sizeof(param));
1588
1589 acx = rte_acl_create(&param);
1590 if (acx == NULL) {
1591 printf("Line %i: Error creating ACL context!\n", __LINE__);
1592 return -1;
1593 }
1594
1595 /* dump context with rules - useful for coverage */
1596 rte_acl_list_dump();
1597
1598 rte_acl_dump(acx);
1599
1600 rte_acl_free(acx);
1601
1602 return 0;
1603}
1604
f67539c2
TL
1605static uint32_t
1606get_u32_range_max(void)
1607{
1608 uint32_t i, max;
1609
1610 max = 0;
1611 for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1612 max = RTE_MAX(max, acl_u32_range_test_rules[i].src_mask_len);
1613 return max;
1614}
1615
1616static uint32_t
1617get_u32_range_min(void)
1618{
1619 uint32_t i, min;
1620
1621 min = UINT32_MAX;
1622 for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1623 min = RTE_MIN(min, acl_u32_range_test_rules[i].src_addr);
1624 return min;
1625}
1626
1627static const struct rte_acl_ipv4vlan_rule *
1628find_u32_range_rule(uint32_t val)
1629{
1630 uint32_t i;
1631
1632 for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1633 if (val >= acl_u32_range_test_rules[i].src_addr &&
1634 val <= acl_u32_range_test_rules[i].src_mask_len)
1635 return acl_u32_range_test_rules + i;
1636 }
1637 return NULL;
1638}
1639
1640static void
1641fill_u32_range_data(struct ipv4_7tuple tdata[], uint32_t start, uint32_t num)
1642{
1643 uint32_t i;
1644 const struct rte_acl_ipv4vlan_rule *r;
1645
1646 for (i = 0; i != num; i++) {
1647 tdata[i].ip_src = start + i;
1648 r = find_u32_range_rule(start + i);
1649 if (r != NULL)
1650 tdata[i].allow = r->data.userdata;
1651 }
1652}
1653
1654static int
1655test_u32_range(void)
1656{
1657 int32_t rc;
1658 uint32_t i, k, max, min;
1659 struct rte_acl_ctx *acx;
1660 struct acl_ipv4vlan_rule r;
1661 struct ipv4_7tuple test_data[64];
1662
1663 acx = rte_acl_create(&acl_param);
1664 if (acx == NULL) {
1665 printf("%s#%i: Error creating ACL context!\n",
1666 __func__, __LINE__);
1667 return -1;
1668 }
1669
1670 for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1671 convert_rule(&acl_u32_range_test_rules[i], &r);
1672 rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
1673 if (rc != 0) {
1674 printf("%s#%i: Adding rule to ACL context "
1675 "failed with error code: %d\n",
1676 __func__, __LINE__, rc);
1677 rte_acl_free(acx);
1678 return rc;
1679 }
1680 }
1681
1682 rc = build_convert_rules(acx, convert_config_2, 0);
1683 if (rc != 0) {
1684 printf("%s#%i Error @ build_convert_rules!\n",
1685 __func__, __LINE__);
1686 rte_acl_free(acx);
1687 return rc;
1688 }
1689
1690 max = get_u32_range_max();
1691 min = get_u32_range_min();
1692
1693 max = RTE_MAX(max, max + 1);
1694 min = RTE_MIN(min, min - 1);
1695
1696 printf("%s#%d starting range test from %u to %u\n",
1697 __func__, __LINE__, min, max);
1698
1699 for (i = min; i <= max; i += k) {
1700
1701 k = RTE_MIN(max - i + 1, RTE_DIM(test_data));
1702
1703 memset(test_data, 0, sizeof(test_data));
1704 fill_u32_range_data(test_data, i, k);
1705
1706 rc = test_classify_run(acx, test_data, k);
1707 if (rc != 0) {
1708 printf("%s#%d failed at [%u, %u) interval\n",
1709 __func__, __LINE__, i, i + k);
1710 break;
1711 }
1712 }
1713
1714 rte_acl_free(acx);
1715 return rc;
1716}
1717
7c673cae
FG
1718static int
1719test_acl(void)
1720{
1721 if (test_invalid_parameters() < 0)
1722 return -1;
1723 if (test_invalid_rules() < 0)
1724 return -1;
1725 if (test_create_find_add() < 0)
1726 return -1;
1727 if (test_invalid_layout() < 0)
1728 return -1;
1729 if (test_misc() < 0)
1730 return -1;
1731 if (test_classify() < 0)
1732 return -1;
1733 if (test_build_ports_range() < 0)
1734 return -1;
1735 if (test_convert() < 0)
1736 return -1;
f67539c2
TL
1737 if (test_u32_range() < 0)
1738 return -1;
7c673cae
FG
1739
1740 return 0;
1741}
1742
1743REGISTER_TEST_COMMAND(acl_autotest, test_acl);