]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/test/test/test_acl.c
update download target update for octopus release
[ceph.git] / ceph / src / spdk / dpdk / test / test / test_acl.c
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 = IPv4(10, 1, 1, 1),
519 .ip_dst = IPv4(192, 168, 0, 33),
520 .port_dst = 53,
521 .allow = 1,
522 },
523 {
524 .proto = 6,
525 .ip_src = IPv4(127, 84, 33, 1),
526 .ip_dst = 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(&param, &acl_param, sizeof(param));
1136 param.max_rule_num = 2;
1137
1138 param.name = acx_name;
1139 acx = rte_acl_create(&param);
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(&param);
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(&param);
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(&param);
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(&param, &acl_param, sizeof(param));
1206 param.max_rule_num = LEN;
1207
1208 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1375 param.rule_size = 0;
1376
1377 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1387 param.max_rule_num = 0;
1388
1389 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1399 param.socket_id = RTE_MAX_NUMA_NODES + 1;
1400
1401 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1411 param.name = NULL;
1412
1413 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1438 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1483 acx = rte_acl_create(&param);
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(&param, &acl_param, sizeof(param));
1583
1584 acx = rte_acl_create(&param);
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);