4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <rte_string_fns.h>
43 #include <rte_byteorder.h>
46 #include <rte_common.h>
50 #define LEN RTE_ACL_MAX_CATEGORIES
52 struct rte_acl_param acl_param = {
54 .socket_id = SOCKET_ID_ANY,
55 .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ,
56 .max_rule_num = 0x30000,
59 struct rte_acl_ipv4vlan_rule acl_rule = {
60 .data = { .priority = 1, .category_mask = 0xff },
62 .src_port_high = UINT16_MAX,
64 .dst_port_high = UINT16_MAX,
67 /* byteswap to cpu or network order */
69 bswap_test_data(struct ipv4_7tuple * data, int len, int to_be)
73 for (i = 0; i < len; i++) {
76 /* swap all bytes so that they are in network order */
77 data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
78 data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
79 data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
80 data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
81 data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
82 data[i].domain = rte_cpu_to_be_16(data[i].domain);
85 data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
86 data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
87 data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
88 data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
89 data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
90 data[i].domain = rte_be_to_cpu_16(data[i].domain);
96 * Test scalar and SSE ACL lookup.
101 struct rte_acl_ctx * acx;
103 uint32_t result, count;
105 uint32_t results[RTE_DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
107 const uint8_t * data[RTE_DIM(acl_test_data)];
109 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
110 offsetof(struct ipv4_7tuple, proto),
111 offsetof(struct ipv4_7tuple, vlan),
112 offsetof(struct ipv4_7tuple, ip_src),
113 offsetof(struct ipv4_7tuple, ip_dst),
114 offsetof(struct ipv4_7tuple, port_src),
117 acx = rte_acl_create(&acl_param);
119 printf("Line %i: Error creating ACL context!\n", __LINE__);
123 /* add rules to the context */
124 ret = rte_acl_ipv4vlan_add_rules(acx, acl_test_rules,
125 RTE_DIM(acl_test_rules));
127 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
132 /* try building the context */
133 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
135 printf("Line %i: Building ACL context failed!\n", __LINE__);
140 /* swap all bytes in the data to network order */
141 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1);
143 /* store pointers to test data */
144 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++)
145 data[i] = (uint8_t *)&acl_test_data[i];
148 * these will run quite a few times, it's necessary to test code paths
149 * from num=0 to num>8
151 for (count = 0; count < RTE_DIM(acl_test_data); count++) {
152 ret = rte_acl_classify(acx, data, results,
153 count, RTE_ACL_MAX_CATEGORIES);
155 printf("Line %i: SSE classify failed!\n", __LINE__);
159 /* check if we allow everything we should allow */
160 for (i = 0; i < (int) count; i++) {
161 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
162 if (result != acl_test_data[i].allow) {
163 printf("Line %i: Error in allow results at %i "
164 "(expected %"PRIu32" got %"PRIu32")!\n",
165 __LINE__, i, acl_test_data[i].allow,
171 /* check if we deny everything we should deny */
172 for (i = 0; i < (int) count; i++) {
173 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
174 if (result != acl_test_data[i].deny) {
175 printf("Line %i: Error in deny results at %i "
176 "(expected %"PRIu32" got %"PRIu32")!\n",
177 __LINE__, i, acl_test_data[i].deny,
184 /* make a quick check for scalar */
185 ret = rte_acl_classify_scalar(acx, data, results,
186 RTE_DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES);
188 printf("Line %i: SSE classify failed!\n", __LINE__);
192 /* check if we allow everything we should allow */
193 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
194 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
195 if (result != acl_test_data[i].allow) {
196 printf("Line %i: Error in allow results at %i "
197 "(expected %"PRIu32" got %"PRIu32")!\n",
198 __LINE__, i, acl_test_data[i].allow,
204 /* check if we deny everything we should deny */
205 for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
206 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
207 if (result != acl_test_data[i].deny) {
208 printf("Line %i: Error in deny results at %i "
209 "(expected %"PRIu32" got %"PRIu32")!\n",
210 __LINE__, i, acl_test_data[i].deny,
216 /* free ACL context */
219 /* swap data back to cpu order so that next time tests don't fail */
220 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0);
225 /* swap data back to cpu order so that next time tests don't fail */
226 bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0);
234 * Test wrong layout behavior
235 * This test supplies the ACL context with invalid layout, which results in
236 * ACL matching the wrong stuff. However, it should match the wrong stuff
237 * the right way. We switch around source and destination addresses,
238 * source and destination ports, and protocol will point to first byte of
242 test_invalid_layout(void)
244 struct rte_acl_ctx * acx;
247 uint32_t results[RTE_DIM(invalid_layout_data)];
248 const uint8_t * data[RTE_DIM(invalid_layout_data)];
250 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
251 /* proto points to destination port's first byte */
252 offsetof(struct ipv4_7tuple, port_dst),
254 0, /* VLAN not used */
256 /* src and dst addresses are swapped */
257 offsetof(struct ipv4_7tuple, ip_dst),
258 offsetof(struct ipv4_7tuple, ip_src),
260 /* we can't swap ports here, so we will swap them in the data */
261 offsetof(struct ipv4_7tuple, port_src),
264 acx = rte_acl_create(&acl_param);
266 printf("Line %i: Error creating ACL context!\n", __LINE__);
270 /* putting a lot of rules into the context results in greater
271 * coverage numbers. it doesn't matter if they are identical */
272 for (i = 0; i < 1000; i++) {
273 /* add rules to the context */
274 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
275 RTE_DIM(invalid_layout_rules));
277 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
283 /* try building the context */
284 ret = rte_acl_ipv4vlan_build(acx, layout, 1);
286 printf("Line %i: Building ACL context failed!\n", __LINE__);
291 /* swap all bytes in the data to network order */
292 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
295 for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
296 data[i] = (uint8_t *)&invalid_layout_data[i];
299 /* classify tuples */
300 ret = rte_acl_classify(acx, data, results,
301 RTE_DIM(results), 1);
303 printf("Line %i: SSE classify failed!\n", __LINE__);
308 for (i = 0; i < (int) RTE_DIM(results); i++) {
309 if (results[i] != invalid_layout_data[i].allow) {
310 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
311 __LINE__, i, results[i], invalid_layout_data[i].allow);
316 /* classify tuples (scalar) */
317 ret = rte_acl_classify_scalar(acx, data, results,
318 RTE_DIM(results), 1);
320 printf("Line %i: Scalar classify failed!\n", __LINE__);
325 for (i = 0; i < (int) RTE_DIM(results); i++) {
326 if (results[i] != invalid_layout_data[i].allow) {
327 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
328 __LINE__, i, results[i], invalid_layout_data[i].allow);
335 /* swap data back to cpu order so that next time tests don't fail */
336 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
341 /* swap data back to cpu order so that next time tests don't fail */
342 bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
350 * Test creating and finding ACL contexts, and adding rules
353 test_create_find_add(void)
355 struct rte_acl_param param;
356 struct rte_acl_ctx * acx, *acx2, *tmp;
357 struct rte_acl_ipv4vlan_rule rules[LEN];
359 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
361 const char * acx_name = "acx";
362 const char * acx2_name = "acx2";
365 /* create two contexts */
366 memcpy(¶m, &acl_param, sizeof(param));
367 param.max_rule_num = 2;
369 param.name = acx_name;
370 acx = rte_acl_create(¶m);
372 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
376 param.name = acx2_name;
377 acx2 = rte_acl_create(¶m);
378 if (acx2 == NULL || acx2 == acx) {
379 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
384 /* try to create third one, with an existing name */
385 param.name = acx_name;
386 tmp = rte_acl_create(¶m);
388 printf("Line %i: Creating context with existing name test failed!\n",
395 param.name = acx2_name;
396 tmp = rte_acl_create(¶m);
398 printf("Line %i: Creating context with existing name test 2 failed!\n",
405 /* try to find existing ACL contexts */
406 tmp = rte_acl_find_existing(acx_name);
408 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
414 tmp = rte_acl_find_existing(acx2_name);
416 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
422 /* try to find non-existing context */
423 tmp = rte_acl_find_existing("invalid");
425 printf("Line %i: Non-existent ACL context found!\n", __LINE__);
433 /* create valid (but severely limited) acx */
434 memcpy(¶m, &acl_param, sizeof(param));
435 param.max_rule_num = LEN;
437 acx = rte_acl_create(¶m);
439 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
443 /* create dummy acl */
444 for (i = 0; i < LEN; i++) {
445 memcpy(&rules[i], &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
446 rules[i].data.userdata = i + 1; /* skip zero */
447 rules[i].data.category_mask = 1 << i; /* one rule per category */
450 /* try filling up the context */
451 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
453 printf("Line %i: Adding %i rules to ACL context failed!\n",
458 /* try adding to a (supposedly) full context */
459 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
461 printf("Line %i: Adding rules to full ACL context should"
462 "have failed!\n", __LINE__);
466 /* try building the context */
467 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
469 printf("Line %i: Building ACL context failed!\n", __LINE__);
484 * test various invalid rules
487 test_invalid_rules(void)
489 struct rte_acl_ctx * acx;
492 struct rte_acl_ipv4vlan_rule rule;
494 acx = rte_acl_create(&acl_param);
496 printf("Line %i: Error creating ACL context!\n", __LINE__);
500 /* test inverted high/low source and destination ports.
501 * originally, there was a problem with memory consumption when using
504 /* create dummy acl */
505 memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
506 rule.data.userdata = 1;
507 rule.dst_port_low = 0xfff0;
508 rule.dst_port_high = 0x0010;
510 /* add rules to context and try to build it */
511 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
513 printf("Line %i: Adding rules to ACL context "
514 "should have failed!\n", __LINE__);
518 rule.dst_port_low = 0x0;
519 rule.dst_port_high = 0xffff;
520 rule.src_port_low = 0xfff0;
521 rule.src_port_high = 0x0010;
523 /* add rules to context and try to build it */
524 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
526 printf("Line %i: Adding rules to ACL context "
527 "should have failed!\n", __LINE__);
531 rule.dst_port_low = 0x0;
532 rule.dst_port_high = 0xffff;
533 rule.src_port_low = 0x0;
534 rule.src_port_high = 0xffff;
536 rule.dst_mask_len = 33;
538 /* add rules to context and try to build it */
539 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
541 printf("Line %i: Adding rules to ACL context "
542 "should have failed!\n", __LINE__);
546 rule.dst_mask_len = 0;
547 rule.src_mask_len = 33;
549 /* add rules to context and try to build it */
550 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
552 printf("Line %i: Adding rules to ACL context "
553 "should have failed!\n", __LINE__);
557 rule.dst_mask_len = 0;
558 rule.src_mask_len = 0;
559 rule.data.userdata = 0;
561 /* try adding this rule (it should fail because userdata is invalid) */
562 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
564 printf("Line %i: Adding a rule with invalid user data "
565 "should have failed!\n", __LINE__);
581 * test functions by passing invalid or
582 * non-workable parameters.
584 * we do very limited testing of classify functions here
585 * because those are performance-critical and
586 * thus don't do much parameter checking.
589 test_invalid_parameters(void)
591 struct rte_acl_param param;
592 struct rte_acl_ctx * acx;
593 struct rte_acl_ipv4vlan_rule rule;
596 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
604 acx = rte_acl_create(NULL);
606 printf("Line %i: ACL context creation with NULL param "
607 "should have failed!\n", __LINE__);
613 memcpy(¶m, &acl_param, sizeof(param));
616 acx = rte_acl_create(¶m);
618 printf("Line %i: ACL context creation with zero rule len "
619 "failed!\n", __LINE__);
625 /* zero max rule num */
626 memcpy(¶m, &acl_param, sizeof(param));
627 param.max_rule_num = 0;
629 acx = rte_acl_create(¶m);
631 printf("Line %i: ACL context creation with zero rule num "
632 "failed!\n", __LINE__);
638 /* invalid NUMA node */
639 memcpy(¶m, &acl_param, sizeof(param));
640 param.socket_id = RTE_MAX_NUMA_NODES + 1;
642 acx = rte_acl_create(¶m);
644 printf("Line %i: ACL context creation with invalid NUMA "
645 "should have failed!\n", __LINE__);
651 memcpy(¶m, &acl_param, sizeof(param));
654 acx = rte_acl_create(¶m);
656 printf("Line %i: ACL context creation with NULL name "
657 "should have failed!\n", __LINE__);
663 * rte_acl_find_existing
666 acx = rte_acl_find_existing(NULL);
668 printf("Line %i: NULL ACL context found!\n", __LINE__);
674 * rte_acl_ipv4vlan_add_rules
677 /* initialize everything */
678 memcpy(¶m, &acl_param, sizeof(param));
679 acx = rte_acl_create(¶m);
681 printf("Line %i: ACL context creation failed!\n", __LINE__);
685 memcpy(&rule, &acl_rule, sizeof(rule));
688 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
690 printf("Line %i: Adding rules with NULL ACL context "
691 "should have failed!\n", __LINE__);
697 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
699 printf("Line %i: Adding NULL rule to ACL context "
700 "should have failed!\n", __LINE__);
705 /* zero count (should succeed) */
706 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
708 printf("Line %i: Adding 0 rules to ACL context failed!\n", __LINE__);
713 /* free ACL context */
716 /* set wrong rule_size so that adding any rules would fail */
717 param.rule_size = RTE_ACL_IPV4VLAN_RULE_SZ + 4;
718 acx = rte_acl_create(¶m);
720 printf("Line %i: ACL context creation failed!\n", __LINE__);
724 /* try adding a rule with size different from context rule_size */
725 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
727 printf("Line %i: Adding an invalid sized rule "
728 "should have failed!\n", __LINE__);
733 /* free ACL context */
738 * rte_acl_ipv4vlan_build
741 /* reinitialize context */
742 memcpy(¶m, &acl_param, sizeof(param));
743 acx = rte_acl_create(¶m);
745 printf("Line %i: ACL context creation failed!\n", __LINE__);
750 result = rte_acl_ipv4vlan_build(NULL, layout, 1);
752 printf("Line %i: Building with NULL context "
753 "should have failed!\n", __LINE__);
759 result = rte_acl_ipv4vlan_build(acx, NULL, 1);
761 printf("Line %i: Building with NULL layout "
762 "should have failed!\n", __LINE__);
767 /* zero categories (should not fail) */
768 result = rte_acl_ipv4vlan_build(acx, layout, 0);
770 printf("Line %i: Building with 0 categories should fail!\n",
776 /* SSE classify test */
778 /* cover zero categories in classify (should not fail) */
779 result = rte_acl_classify(acx, NULL, NULL, 0, 0);
781 printf("Line %i: SSE classify with zero categories "
782 "failed!\n", __LINE__);
787 /* cover invalid but positive categories in classify */
788 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
790 printf("Line %i: SSE classify with 3 categories "
791 "should have failed!\n", __LINE__);
796 /* scalar classify test */
798 /* cover zero categories in classify (should not fail) */
799 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 0);
801 printf("Line %i: Scalar classify with zero categories "
802 "failed!\n", __LINE__);
807 /* cover invalid but positive categories in classify */
808 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 3);
810 printf("Line %i: Scalar classify with 3 categories "
811 "should have failed!\n", __LINE__);
816 /* free ACL context */
821 * make sure void functions don't crash with NULL parameters
832 * Various tests that don't test much but improve coverage
837 struct rte_acl_param param;
838 struct rte_acl_ctx * acx;
841 memcpy(¶m, &acl_param, sizeof(param));
843 acx = rte_acl_create(¶m);
845 printf("Line %i: Error creating ACL context!\n", __LINE__);
849 /* dump context with rules - useful for coverage */
862 if (test_invalid_parameters() < 0)
864 if (test_invalid_rules() < 0)
866 if (test_create_find_add() < 0)
868 if (test_invalid_layout() < 0)
872 if (test_classify() < 0)
882 printf("This binary was not compiled with ACL support!\n");
886 #endif /* RTE_LIBRTE_ACL */