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.
37 #include <cmdline_parse.h>
39 #include <rte_string_fns.h>
44 #ifdef RTE_LIBRTE_PMAC
46 #include <rte_byteorder.h>
50 #include "test_pmac_acl.h"
52 #define LEN RTE_ACL_MAX_CATEGORIES
54 struct rte_acl_param acl_param = {
56 .socket_id = SOCKET_ID_ANY,
57 .rule_size = sizeof(struct rte_acl_ipv4vlan_rule),
58 .max_rule_num = 0x30000,
61 struct rte_acl_ipv4vlan_rule acl_rule = {
62 .data = { .priority = 1, .category_mask = 0xff },
64 .src_port_high = UINT16_MAX,
66 .dst_port_high = UINT16_MAX,
69 /* byteswap to cpu or network order */
71 bswap_test_data(struct ipv4_7tuple * data, int len, int to_be)
75 for (i = 0; i < len; i++) {
78 /* swap all bytes so that they are in network order */
79 data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
80 data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
81 data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
82 data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
83 data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
84 data[i].domain = rte_cpu_to_be_16(data[i].domain);
87 data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
88 data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
89 data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
90 data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
91 data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
92 data[i].domain = rte_be_to_cpu_16(data[i].domain);
98 * Test scalar and SSE ACL lookup.
103 struct rte_acl_ctx * acx;
105 uint32_t result, count;
107 uint32_t results[DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
109 const uint8_t * data[DIM(acl_test_data)];
111 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
112 offsetof(struct ipv4_7tuple, proto),
113 offsetof(struct ipv4_7tuple, vlan),
114 offsetof(struct ipv4_7tuple, ip_src),
115 offsetof(struct ipv4_7tuple, ip_dst),
116 offsetof(struct ipv4_7tuple, port_src),
119 acx = rte_acl_create(&acl_param);
121 printf("Line %i: Error creating ACL context!\n", __LINE__);
125 /* add rules to the context */
126 ret = rte_acl_ipv4vlan_add_rules(acx, acl_test_rules,
127 DIM(acl_test_rules));
129 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
134 /* try building the context */
135 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
137 printf("Line %i: Building ACL context failed!\n", __LINE__);
142 /* swap all bytes in the data to network order */
143 bswap_test_data(acl_test_data, DIM(acl_test_data), 1);
145 /* store pointers to test data */
146 for (i = 0; i < (int) DIM(acl_test_data); i++)
147 data[i] = (uint8_t *)&acl_test_data[i];
150 * these will run quite a few times, it's necessary to test code paths
151 * from num=0 to num>8
153 for (count = 0; count < DIM(acl_test_data); count++) {
154 ret = rte_acl_classify(acx, data, results,
155 count, RTE_ACL_MAX_CATEGORIES);
157 printf("Line %i: SSE classify failed!\n", __LINE__);
161 /* check if we allow everything we should allow */
162 for (i = 0; i < (int) count; i++) {
163 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
164 if (result != acl_test_data[i].allow) {
165 printf("Line %i: Error in allow results at %i "
166 "(expected %"PRIu32" got %"PRIu32")!\n",
167 __LINE__, i, acl_test_data[i].allow,
173 /* check if we deny everything we should deny */
174 for (i = 0; i < (int) count; i++) {
175 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
176 if (result != acl_test_data[i].deny) {
177 printf("Line %i: Error in deny results at %i "
178 "(expected %"PRIu32" got %"PRIu32")!\n",
179 __LINE__, i, acl_test_data[i].deny,
186 /* make a quick check for scalar */
187 ret = rte_acl_classify_scalar(acx, data, results,
188 DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES);
190 printf("Line %i: SSE classify failed!\n", __LINE__);
194 /* check if we allow everything we should allow */
195 for (i = 0; i < (int) DIM(acl_test_data); i++) {
196 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
197 if (result != acl_test_data[i].allow) {
198 printf("Line %i: Error in allow results at %i "
199 "(expected %"PRIu32" got %"PRIu32")!\n",
200 __LINE__, i, acl_test_data[i].allow,
206 /* check if we deny everything we should deny */
207 for (i = 0; i < (int) DIM(acl_test_data); i++) {
208 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
209 if (result != acl_test_data[i].deny) {
210 printf("Line %i: Error in deny results at %i "
211 "(expected %"PRIu32" got %"PRIu32")!\n",
212 __LINE__, i, acl_test_data[i].deny,
218 /* free ACL context */
221 /* swap data back to cpu order so that next time tests don't fail */
222 bswap_test_data(acl_test_data, DIM(acl_test_data), 0);
227 /* swap data back to cpu order so that next time tests don't fail */
228 bswap_test_data(acl_test_data, DIM(acl_test_data), 0);
236 * Test wrong layout behavior
237 * This test supplies the ACL context with invalid layout, which results in
238 * ACL matching the wrong stuff. However, it should match the wrong stuff
239 * the right way. We switch around source and destination addresses,
240 * source and destination ports, and protocol will point to first byte of
244 test_invalid_layout(void)
246 struct rte_acl_ctx * acx;
249 uint32_t results[DIM(invalid_layout_data)];
250 const uint8_t * data[DIM(invalid_layout_data)];
252 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
253 /* proto points to destination port's first byte */
254 offsetof(struct ipv4_7tuple, port_dst),
256 0, /* VLAN not used */
258 /* src and dst addresses are swapped */
259 offsetof(struct ipv4_7tuple, ip_dst),
260 offsetof(struct ipv4_7tuple, ip_src),
262 /* we can't swap ports here, so we will swap them in the data */
263 offsetof(struct ipv4_7tuple, port_src),
266 acx = rte_acl_create(&acl_param);
268 printf("Line %i: Error creating ACL context!\n", __LINE__);
272 /* putting a lot of rules into the context results in greater
273 * coverage numbers. it doesn't matter if they are identical */
274 for (i = 0; i < 1000; i++) {
275 /* add rules to the context */
276 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
277 DIM(invalid_layout_rules));
279 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
285 /* try building the context */
286 ret = rte_acl_ipv4vlan_build(acx, layout, 1);
288 printf("Line %i: Building ACL context failed!\n", __LINE__);
293 /* swap all bytes in the data to network order */
294 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 1);
297 for (i = 0; i < (int) DIM(invalid_layout_data); i++) {
298 data[i] = (uint8_t *)&invalid_layout_data[i];
301 /* classify tuples */
302 ret = rte_acl_classify(acx, data, results,
305 printf("Line %i: SSE classify failed!\n", __LINE__);
310 for (i = 0; i < (int) DIM(results); i++) {
311 if (results[i] != invalid_layout_data[i].allow) {
312 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
313 __LINE__, i, results[i], invalid_layout_data[i].allow);
318 /* classify tuples (scalar) */
319 ret = rte_acl_classify_scalar(acx, data, results,
322 printf("Line %i: Scalar classify failed!\n", __LINE__);
327 for (i = 0; i < (int) DIM(results); i++) {
328 if (results[i] != invalid_layout_data[i].allow) {
329 printf("Line %i: Wrong results at %i (result=%u, should be %u)!\n",
330 __LINE__, i, results[i], invalid_layout_data[i].allow);
337 /* swap data back to cpu order so that next time tests don't fail */
338 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 0);
343 /* swap data back to cpu order so that next time tests don't fail */
344 bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 0);
352 * Test creating and finding ACL contexts, and adding rules
355 test_create_find_add(void)
357 struct rte_acl_param param;
358 struct rte_acl_ctx * acx, *acx2, *tmp;
359 struct rte_acl_ipv4vlan_rule rules[LEN];
361 const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
363 const char * acx_name = "acx";
364 const char * acx2_name = "acx2";
367 /* create two contexts */
368 memcpy(¶m, &acl_param, sizeof(param));
369 param.max_rule_num = 2;
371 param.name = acx_name;
372 acx = rte_acl_create(¶m);
374 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
378 param.name = acx2_name;
379 acx2 = rte_acl_create(¶m);
380 if (acx2 == NULL || acx2 == acx) {
381 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
386 /* try to create third one, with an existing name */
387 param.name = acx_name;
388 tmp = rte_acl_create(¶m);
390 printf("Line %i: Creating context with existing name test failed!\n",
397 param.name = acx2_name;
398 tmp = rte_acl_create(¶m);
400 printf("Line %i: Creating context with existing name test 2 failed!\n",
407 /* try to find existing PM contexts */
408 tmp = rte_acl_find_existing(acx_name);
410 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
416 tmp = rte_acl_find_existing(acx2_name);
418 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
424 /* try to find non-existing context */
425 tmp = rte_acl_find_existing("invalid");
427 printf("Line %i: Non-existent PM context found!\n", __LINE__);
435 /* create valid (but severely limited) acx */
436 memcpy(¶m, &acl_param, sizeof(param));
437 param.max_rule_num = LEN;
439 acx = rte_acl_create(¶m);
441 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
445 /* create dummy acl */
446 for (i = 0; i < LEN; i++) {
447 memcpy(&rules[i], &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
448 rules[i].data.userdata = i + 1; /* skip zero */
449 rules[i].data.category_mask = 1 << i; /* one rule per category */
452 /* try filling up the context */
453 ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
455 printf("Line %i: Adding %i rules to ACL context failed!\n",
460 /* try adding to a (supposedly) full context */
461 ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
463 printf("Line %i: Adding rules to full ACL context should"
464 "have failed!\n", __LINE__);
468 /* try building the context */
469 ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
471 printf("Line %i: Building ACL context failed!\n", __LINE__);
486 * test various invalid rules
489 test_invalid_rules(void)
491 struct rte_acl_ctx * acx;
494 struct rte_acl_ipv4vlan_rule rule;
496 acx = rte_acl_create(&acl_param);
498 printf("Line %i: Error creating ACL context!\n", __LINE__);
502 /* test inverted high/low source and destination ports.
503 * originally, there was a problem with memory consumption when using
506 /* create dummy acl */
507 memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
508 rule.data.userdata = 1;
509 rule.dst_port_low = 0xfff0;
510 rule.dst_port_high = 0x0010;
512 /* add rules to context and try to build it */
513 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
515 printf("Line %i: Adding rules to ACL context "
516 "should have failed!\n", __LINE__);
520 rule.dst_port_low = 0x0;
521 rule.dst_port_high = 0xffff;
522 rule.src_port_low = 0xfff0;
523 rule.src_port_high = 0x0010;
525 /* add rules to context and try to build it */
526 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
528 printf("Line %i: Adding rules to ACL context "
529 "should have failed!\n", __LINE__);
533 rule.dst_port_low = 0x0;
534 rule.dst_port_high = 0xffff;
535 rule.src_port_low = 0x0;
536 rule.src_port_high = 0xffff;
538 rule.dst_mask_len = 33;
540 /* add rules to context and try to build it */
541 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
543 printf("Line %i: Adding rules to ACL context "
544 "should have failed!\n", __LINE__);
548 rule.dst_mask_len = 0;
549 rule.src_mask_len = 33;
551 /* add rules to context and try to build it */
552 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
554 printf("Line %i: Adding rules to ACL context "
555 "should have failed!\n", __LINE__);
559 rule.dst_mask_len = 0;
560 rule.src_mask_len = 0;
561 rule.data.userdata = 0;
563 /* try adding this rule (it should fail because userdata is invalid) */
564 ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
566 printf("Line %i: Adding a rule with invalid user data "
567 "should have failed!\n", __LINE__);
583 * test functions by passing invalid or
584 * non-workable parameters.
586 * we do very limited testing of classify functions here
587 * because those are performance-critical and
588 * thus don't do much parameter checking.
591 test_invalid_parameters(void)
593 struct rte_acl_param param;
594 struct rte_acl_ctx * acx;
595 struct rte_acl_ipv4vlan_rule rule;
598 uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
606 acx = rte_acl_create(NULL);
608 printf("Line %i: ACL context creation with NULL param "
609 "should have failed!\n", __LINE__);
615 memcpy(¶m, &acl_param, sizeof(param));
618 acx = rte_acl_create(¶m);
620 printf("Line %i: ACL context creation with zero rule len "
621 "failed!\n", __LINE__);
627 /* zero max rule num */
628 memcpy(¶m, &acl_param, sizeof(param));
629 param.max_rule_num = 0;
631 acx = rte_acl_create(¶m);
633 printf("Line %i: ACL context creation with zero rule num "
634 "failed!\n", __LINE__);
640 /* invalid NUMA node */
641 memcpy(¶m, &acl_param, sizeof(param));
642 param.socket_id = RTE_MAX_NUMA_NODES + 1;
644 acx = rte_acl_create(¶m);
646 printf("Line %i: ACL context creation with invalid NUMA "
647 "should have failed!\n", __LINE__);
653 memcpy(¶m, &acl_param, sizeof(param));
656 acx = rte_acl_create(¶m);
658 printf("Line %i: ACL context creation with NULL name "
659 "should have failed!\n", __LINE__);
665 * rte_acl_find_existing
668 acx = rte_acl_find_existing(NULL);
670 printf("Line %i: NULL ACL context found!\n", __LINE__);
676 * rte_acl_ipv4vlan_add_rules
679 /* initialize everything */
680 memcpy(¶m, &acl_param, sizeof(param));
681 acx = rte_acl_create(¶m);
683 printf("Line %i: ACL context creation failed!\n", __LINE__);
687 memcpy(&rule, &acl_rule, sizeof(rule));
690 result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
692 printf("Line %i: Adding rules with NULL ACL context "
693 "should have failed!\n", __LINE__);
699 result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
701 printf("Line %i: Adding NULL rule to ACL context "
702 "should have failed!\n", __LINE__);
707 /* zero count (should succeed) */
708 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
710 printf("Line %i: Adding 0 rules to ACL context failed!\n", __LINE__);
715 /* free ACL context */
718 /* set wrong rule_size so that adding any rules would fail */
719 param.rule_size = sizeof(struct rte_acl_ipv4vlan_rule) + 4;
720 acx = rte_acl_create(¶m);
722 printf("Line %i: ACL context creation failed!\n", __LINE__);
726 /* try adding a rule with size different from context rule_size */
727 result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
729 printf("Line %i: Adding an invalid sized rule "
730 "should have failed!\n", __LINE__);
735 /* free ACL context */
740 * rte_acl_ipv4vlan_build
743 /* reinitialize context */
744 memcpy(¶m, &acl_param, sizeof(param));
745 acx = rte_acl_create(¶m);
747 printf("Line %i: ACL context creation failed!\n", __LINE__);
752 result = rte_acl_ipv4vlan_build(NULL, layout, 1);
754 printf("Line %i: Building with NULL context "
755 "should have failed!\n", __LINE__);
761 result = rte_acl_ipv4vlan_build(acx, NULL, 1);
763 printf("Line %i: Building with NULL layout "
764 "should have failed!\n", __LINE__);
769 /* zero categories (should not fail) */
770 result = rte_acl_ipv4vlan_build(acx, layout, 0);
772 printf("Line %i: Building with 0 categories failed!\n", __LINE__);
777 /* SSE classify test */
779 /* cover zero categories in classify (should not fail) */
780 result = rte_acl_classify(acx, NULL, NULL, 0, 0);
782 printf("Line %i: SSE classify with zero categories "
783 "failed!\n", __LINE__);
788 /* cover invalid but positive categories in classify */
789 result = rte_acl_classify(acx, NULL, NULL, 0, 3);
791 printf("Line %i: SSE classify with 3 categories "
792 "should have failed!\n", __LINE__);
797 /* scalar classify test */
799 /* cover zero categories in classify (should not fail) */
800 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 0);
802 printf("Line %i: Scalar classify with zero categories "
803 "failed!\n", __LINE__);
808 /* cover invalid but positive categories in classify */
809 result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 3);
811 printf("Line %i: Scalar classify with 3 categories "
812 "should have failed!\n", __LINE__);
817 /* free ACL context */
822 * make sure void functions don't crash with NULL parameters
833 * Various tests that don't test much but improve coverage
838 struct rte_acl_param param;
839 struct rte_acl_ctx * acx;
842 memcpy(¶m, &acl_param, sizeof(param));
844 acx = rte_acl_create(¶m);
846 printf("Line %i: Error creating ACL context!\n", __LINE__);
850 /* dump context with rules - useful for coverage */
863 if (test_invalid_parameters() < 0)
865 if (test_invalid_rules() < 0)
867 if (test_create_find_add() < 0)
869 if (test_invalid_layout() < 0)
873 if (test_classify() < 0)
883 printf("This binary was not compiled with PMAC support!\n");
887 #endif /* RTE_LIBRTE_PMAC */