4 * Copyright(c) 2010-2013 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.
38 #include <cmdline_parse.h>
40 #include <rte_string_fns.h>
45 #ifdef RTE_LIBRTE_PMAC
47 #include <rte_byteorder.h>
51 #include "test_pmac_acl.h"
53 #define LEN RTE_ACL_MAX_CATEGORIES
55 struct rte_acl_param acl_param = {
57 .socket_id = SOCKET_ID_ANY,
58 .rule_size = sizeof(struct rte_acl_ipv4vlan_rule),
59 .max_rule_num = 0x30000,
62 struct rte_acl_ipv4vlan_rule acl_rule = {
63 .data = { .priority = 1, .category_mask = 0xff },
65 .src_port_high = UINT16_MAX,
67 .dst_port_high = UINT16_MAX,
70 /* byteswap to cpu or network order */
72 bswap_test_data(struct ipv4_7tuple * data, int len, int to_be)
76 for (i = 0; i < len; i++) {
79 /* swap all bytes so that they are in network order */
80 data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
81 data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
82 data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
83 data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
84 data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
85 data[i].domain = rte_cpu_to_be_16(data[i].domain);
88 data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
89 data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
90 data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
91 data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
92 data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
93 data[i].domain = rte_be_to_cpu_16(data[i].domain);
99 * Test scalar and SSE ACL lookup.
104 struct rte_acl_ctx * acx;
106 uint32_t result, count;
108 uint32_t results[DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
110 const uint8_t * data[DIM(acl_test_data)];
112 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
113 offsetof(struct ipv4_7tuple, proto),
114 offsetof(struct ipv4_7tuple, vlan),
115 offsetof(struct ipv4_7tuple, ip_src),
116 offsetof(struct ipv4_7tuple, ip_dst),
117 offsetof(struct ipv4_7tuple, port_src),
120 acx = rte_acl_create(&acl_param);
122 printf("Line %i: Error creating ACL context!\n", __LINE__);
126 /* add rules to the context */
127 ret = rte_acl_ipv4vlan_add_rules(acx, acl_test_rules,
128 DIM(acl_test_rules));
130 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
135 /* try building the context */
136 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
138 printf("Line %i: Building ACL context failed!\n", __LINE__);
143 /* swap all bytes in the data to network order */
144 bswap_test_data(acl_test_data, DIM(acl_test_data), 1);
146 /* store pointers to test data */
147 for (i = 0; i < (int) DIM(acl_test_data); i++)
148 data[i] = (uint8_t *)&acl_test_data[i];
151 * these will run quite a few times, it's necessary to test code paths
152 * from num=0 to num>8
154 for (count = 0; count < DIM(acl_test_data); count++) {
155 ret = rte_acl_classify(acx, data, results,
156 count, RTE_ACL_MAX_CATEGORIES);
158 printf("Line %i: SSE classify failed!\n", __LINE__);
162 /* check if we allow everything we should allow */
163 for (i = 0; i < (int) count; i++) {
164 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
165 if (result != acl_test_data[i].allow) {
166 printf("Line %i: Error in allow results at %i "
167 "(expected %"PRIu32" got %"PRIu32")!\n",
168 __LINE__, i, acl_test_data[i].allow,
174 /* check if we deny everything we should deny */
175 for (i = 0; i < (int) count; i++) {
176 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
177 if (result != acl_test_data[i].deny) {
178 printf("Line %i: Error in deny results at %i "
179 "(expected %"PRIu32" got %"PRIu32")!\n",
180 __LINE__, i, acl_test_data[i].deny,
187 /* make a quick check for scalar */
188 ret = rte_acl_classify_scalar(acx, data, results,
189 DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES);
191 printf("Line %i: SSE classify failed!\n", __LINE__);
195 /* check if we allow everything we should allow */
196 for (i = 0; i < (int) DIM(acl_test_data); i++) {
197 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
198 if (result != acl_test_data[i].allow) {
199 printf("Line %i: Error in allow results at %i "
200 "(expected %"PRIu32" got %"PRIu32")!\n",
201 __LINE__, i, acl_test_data[i].allow,
207 /* check if we deny everything we should deny */
208 for (i = 0; i < (int) DIM(acl_test_data); i++) {
209 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
210 if (result != acl_test_data[i].deny) {
211 printf("Line %i: Error in deny results at %i "
212 "(expected %"PRIu32" got %"PRIu32")!\n",
213 __LINE__, i, acl_test_data[i].deny,
219 /* free ACL context */
222 /* swap data back to cpu order so that next time tests don't fail */
223 bswap_test_data(acl_test_data, DIM(acl_test_data), 0);
228 /* swap data back to cpu order so that next time tests don't fail */
229 bswap_test_data(acl_test_data, DIM(acl_test_data), 0);
237 * Test wrong layout behavior
238 * This test supplies the ACL context with invalid layout, which results in
239 * ACL matching the wrong stuff. However, it should match the wrong stuff
240 * the right way. We switch around source and destination addresses,
241 * source and destination ports, and protocol will point to first byte of
245 test_invalid_layout(void)
247 struct rte_acl_ctx * acx;
250 uint32_t results[DIM(invalid_layout_data)];
251 const uint8_t * data[DIM(invalid_layout_data)];
253 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
254 /* proto points to destination port's first byte */
255 offsetof(struct ipv4_7tuple, port_dst),
257 0, /* VLAN not used */
259 /* src and dst addresses are swapped */
260 offsetof(struct ipv4_7tuple, ip_dst),
261 offsetof(struct ipv4_7tuple, ip_src),
263 /* we can't swap ports here, so we will swap them in the data */
264 offsetof(struct ipv4_7tuple, port_src),
267 acx = rte_acl_create(&acl_param);
269 printf("Line %i: Error creating ACL context!\n", __LINE__);
273 /* putting a lot of rules into the context results in greater
274 * coverage numbers. it doesn't matter if they are identical */
275 for (i = 0; i < 1000; i++) {
276 /* add rules to the context */
277 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
278 DIM(invalid_layout_rules));
280 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
286 /* try building the context */
287 ret = rte_acl_ipv4vlan_build(acx, layout, 1);
289 printf("Line %i: Building ACL context failed!\n", __LINE__);
294 /* swap all bytes in the data to network order */
295 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 1);
298 for (i = 0; i < (int) DIM(invalid_layout_data); i++) {
299 data[i] = (uint8_t *)&invalid_layout_data[i];
302 /* classify tuples */
303 ret = rte_acl_classify(acx, data, results,
306 printf("Line %i: SSE classify failed!\n", __LINE__);
311 for (i = 0; i < (int) DIM(results); i++) {
312 if (results[i] != invalid_layout_data[i].allow) {
313 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
314 __LINE__, i, results[i], invalid_layout_data[i].allow);
319 /* classify tuples (scalar) */
320 ret = rte_acl_classify_scalar(acx, data, results,
323 printf("Line %i: Scalar classify failed!\n", __LINE__);
328 for (i = 0; i < (int) DIM(results); i++) {
329 if (results[i] != invalid_layout_data[i].allow) {
330 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
331 __LINE__, i, results[i], invalid_layout_data[i].allow);
338 /* swap data back to cpu order so that next time tests don't fail */
339 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 0);
344 /* swap data back to cpu order so that next time tests don't fail */
345 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 0);
353 * Test creating and finding ACL contexts, and adding rules
356 test_create_find_add(void)
358 struct rte_acl_param param;
359 struct rte_acl_ctx * acx, *acx2, *tmp;
360 struct rte_acl_ipv4vlan_rule rules[LEN];
362 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
364 const char * acx_name = "acx";
365 const char * acx2_name = "acx2";
368 /* create two contexts */
369 memcpy(¶m, &acl_param, sizeof(param));
370 param.max_rule_num = 2;
372 param.name = acx_name;
373 acx = rte_acl_create(¶m);
375 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
379 param.name = acx2_name;
380 acx2 = rte_acl_create(¶m);
381 if (acx2 == NULL || acx2 == acx) {
382 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
387 /* try to create third one, with an existing name */
388 param.name = acx_name;
389 tmp = rte_acl_create(¶m);
391 printf("Line %i: Creating context with existing name test failed!\n",
398 param.name = acx2_name;
399 tmp = rte_acl_create(¶m);
401 printf("Line %i: Creating context with existing name test 2 failed!\n",
408 /* try to find existing PM contexts */
409 tmp = rte_acl_find_existing(acx_name);
411 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
417 tmp = rte_acl_find_existing(acx2_name);
419 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
425 /* try to find non-existing context */
426 tmp = rte_acl_find_existing("invalid");
428 printf("Line %i: Non-existent PM context found!\n", __LINE__);
436 /* create valid (but severely limited) acx */
437 memcpy(¶m, &acl_param, sizeof(param));
438 param.max_rule_num = LEN;
440 acx = rte_acl_create(¶m);
442 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
446 /* create dummy acl */
447 for (i = 0; i < LEN; i++) {
448 memcpy(&rules[i], &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
449 rules[i].data.userdata = i + 1; /* skip zero */
450 rules[i].data.category_mask = 1 << i; /* one rule per category */
453 /* try filling up the context */
454 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
456 printf("Line %i: Adding %i rules to ACL context failed!\n",
461 /* try adding to a (supposedly) full context */
462 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
464 printf("Line %i: Adding rules to full ACL context should"
465 "have failed!\n", __LINE__);
469 /* try building the context */
470 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
472 printf("Line %i: Building ACL context failed!\n", __LINE__);
487 * test various invalid rules
490 test_invalid_rules(void)
492 struct rte_acl_ctx * acx;
495 struct rte_acl_ipv4vlan_rule rule;
497 acx = rte_acl_create(&acl_param);
499 printf("Line %i: Error creating ACL context!\n", __LINE__);
503 /* test inverted high/low source and destination ports.
504 * originally, there was a problem with memory consumption when using
507 /* create dummy acl */
508 memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
509 rule.data.userdata = 1;
510 rule.dst_port_low = 0xfff0;
511 rule.dst_port_high = 0x0010;
513 /* add rules to context and try to build it */
514 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
516 printf("Line %i: Adding rules to ACL context "
517 "should have failed!\n", __LINE__);
521 rule.dst_port_low = 0x0;
522 rule.dst_port_high = 0xffff;
523 rule.src_port_low = 0xfff0;
524 rule.src_port_high = 0x0010;
526 /* add rules to context and try to build it */
527 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
529 printf("Line %i: Adding rules to ACL context "
530 "should have failed!\n", __LINE__);
534 rule.dst_port_low = 0x0;
535 rule.dst_port_high = 0xffff;
536 rule.src_port_low = 0x0;
537 rule.src_port_high = 0xffff;
539 rule.dst_mask_len = 33;
541 /* add rules to context and try to build it */
542 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
544 printf("Line %i: Adding rules to ACL context "
545 "should have failed!\n", __LINE__);
549 rule.dst_mask_len = 0;
550 rule.src_mask_len = 33;
552 /* add rules to context and try to build it */
553 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
555 printf("Line %i: Adding rules to ACL context "
556 "should have failed!\n", __LINE__);
560 rule.dst_mask_len = 0;
561 rule.src_mask_len = 0;
562 rule.data.userdata = 0;
564 /* try adding this rule (it should fail because userdata is invalid) */
565 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
567 printf("Line %i: Adding a rule with invalid user data "
568 "should have failed!\n", __LINE__);
584 * test functions by passing invalid or
585 * non-workable parameters.
587 * we do very limited testing of classify functions here
588 * because those are performance-critical and
589 * thus don't do much parameter checking.
592 test_invalid_parameters(void)
594 struct rte_acl_param param;
595 struct rte_acl_ctx * acx;
596 struct rte_acl_ipv4vlan_rule rule;
599 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
607 acx = rte_acl_create(NULL);
609 printf("Line %i: ACL context creation with NULL param "
610 "should have failed!\n", __LINE__);
616 memcpy(¶m, &acl_param, sizeof(param));
619 acx = rte_acl_create(¶m);
621 printf("Line %i: ACL context creation with zero rule len "
622 "failed!\n", __LINE__);
628 /* zero max rule num */
629 memcpy(¶m, &acl_param, sizeof(param));
630 param.max_rule_num = 0;
632 acx = rte_acl_create(¶m);
634 printf("Line %i: ACL context creation with zero rule num "
635 "failed!\n", __LINE__);
641 /* invalid NUMA node */
642 memcpy(¶m, &acl_param, sizeof(param));
643 param.socket_id = RTE_MAX_NUMA_NODES + 1;
645 acx = rte_acl_create(¶m);
647 printf("Line %i: ACL context creation with invalid NUMA "
648 "should have failed!\n", __LINE__);
654 memcpy(¶m, &acl_param, sizeof(param));
657 acx = rte_acl_create(¶m);
659 printf("Line %i: ACL context creation with NULL name "
660 "should have failed!\n", __LINE__);
666 * rte_acl_find_existing
669 acx = rte_acl_find_existing(NULL);
671 printf("Line %i: NULL ACL context found!\n", __LINE__);
677 * rte_acl_ipv4vlan_add_rules
680 /* initialize everything */
681 memcpy(¶m, &acl_param, sizeof(param));
682 acx = rte_acl_create(¶m);
684 printf("Line %i: ACL context creation failed!\n", __LINE__);
688 memcpy(&rule, &acl_rule, sizeof(rule));
691 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
693 printf("Line %i: Adding rules with NULL ACL context "
694 "should have failed!\n", __LINE__);
700 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
702 printf("Line %i: Adding NULL rule to ACL context "
703 "should have failed!\n", __LINE__);
708 /* zero count (should succeed) */
709 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
711 printf("Line %i: Adding 0 rules to ACL context failed!\n", __LINE__);
716 /* free ACL context */
719 /* set wrong rule_size so that adding any rules would fail */
720 param.rule_size = sizeof(struct rte_acl_ipv4vlan_rule) + 4;
721 acx = rte_acl_create(¶m);
723 printf("Line %i: ACL context creation failed!\n", __LINE__);
727 /* try adding a rule with size different from context rule_size */
728 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
730 printf("Line %i: Adding an invalid sized rule "
731 "should have failed!\n", __LINE__);
736 /* free ACL context */
741 * rte_acl_ipv4vlan_build
744 /* reinitialize context */
745 memcpy(¶m, &acl_param, sizeof(param));
746 acx = rte_acl_create(¶m);
748 printf("Line %i: ACL context creation failed!\n", __LINE__);
753 result = rte_acl_ipv4vlan_build(NULL, layout, 1);
755 printf("Line %i: Building with NULL context "
756 "should have failed!\n", __LINE__);
762 result = rte_acl_ipv4vlan_build(acx, NULL, 1);
764 printf("Line %i: Building with NULL layout "
765 "should have failed!\n", __LINE__);
770 /* zero categories (should not fail) */
771 result = rte_acl_ipv4vlan_build(acx, layout, 0);
773 printf("Line %i: Building with 0 categories failed!\n", __LINE__);
778 /* SSE classify test */
780 /* cover zero categories in classify (should not fail) */
781 result = rte_acl_classify(acx, NULL, NULL, 0, 0);
783 printf("Line %i: SSE classify with zero categories "
784 "failed!\n", __LINE__);
789 /* cover invalid but positive categories in classify */
790 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
792 printf("Line %i: SSE classify with 3 categories "
793 "should have failed!\n", __LINE__);
798 /* scalar classify test */
800 /* cover zero categories in classify (should not fail) */
801 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 0);
803 printf("Line %i: Scalar classify with zero categories "
804 "failed!\n", __LINE__);
809 /* cover invalid but positive categories in classify */
810 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 3);
812 printf("Line %i: Scalar classify with 3 categories "
813 "should have failed!\n", __LINE__);
818 /* free ACL context */
823 * make sure void functions don't crash with NULL parameters
834 * Various tests that don't test much but improve coverage
839 struct rte_acl_param param;
840 struct rte_acl_ctx * acx;
843 memcpy(¶m, &acl_param, sizeof(param));
845 acx = rte_acl_create(¶m);
847 printf("Line %i: Error creating ACL context!\n", __LINE__);
851 /* dump context with rules - useful for coverage */
864 if (test_invalid_parameters() < 0)
866 if (test_invalid_rules() < 0)
868 if (test_create_find_add() < 0)
870 if (test_invalid_layout() < 0)
874 if (test_classify() < 0)
884 printf("This binary was not compiled with PMAC support!\n");
888 #endif /* RTE_LIBRTE_PMAC */