c6b3f860d219079f3ba4f2a1b451fc2d9255069a
[dpdk.git] / app / test / test_acl.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
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
16  *       distribution.
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.
20  *
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.
32  */
33
34 #include <string.h>
35 #include <errno.h>
36
37 #include "test.h"
38
39 #include <rte_string_fns.h>
40 #include <rte_mbuf.h>
41 #include <rte_byteorder.h>
42 #include <rte_ip.h>
43 #include <rte_acl.h>
44 #include <rte_common.h>
45
46 #include "test_acl.h"
47
48 #define LEN RTE_ACL_MAX_CATEGORIES
49
50 struct rte_acl_param acl_param = {
51         .name = "acl_ctx",
52         .socket_id = SOCKET_ID_ANY,
53         .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ,
54         .max_rule_num = 0x30000,
55 };
56
57 struct rte_acl_ipv4vlan_rule acl_rule = {
58                 .data = { .priority = 1, .category_mask = 0xff },
59                 .src_port_low = 0,
60                 .src_port_high = UINT16_MAX,
61                 .dst_port_low = 0,
62                 .dst_port_high = UINT16_MAX,
63 };
64
65 /* byteswap to cpu or network order */
66 static void
67 bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
68 {
69         int i;
70
71         for (i = 0; i < len; i++) {
72
73                 if (to_be) {
74                         /* swap all bytes so that they are in network order */
75                         data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
76                         data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
77                         data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
78                         data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
79                         data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
80                         data[i].domain = rte_cpu_to_be_16(data[i].domain);
81                 } else {
82                         data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
83                         data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
84                         data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
85                         data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
86                         data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
87                         data[i].domain = rte_be_to_cpu_16(data[i].domain);
88                 }
89         }
90 }
91
92 /*
93  * Test scalar and SSE ACL lookup.
94  */
95 static int
96 test_classify_run(struct rte_acl_ctx *acx)
97 {
98         int ret, i;
99         uint32_t result, count;
100         uint32_t results[RTE_DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
101         const uint8_t *data[RTE_DIM(acl_test_data)];
102
103         /* swap all bytes in the data to network order */
104         bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1);
105
106         /* store pointers to test data */
107         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++)
108                 data[i] = (uint8_t *)&acl_test_data[i];
109
110         /**
111          * these will run quite a few times, it's necessary to test code paths
112          * from num=0 to num>8
113          */
114         for (count = 0; count < RTE_DIM(acl_test_data); count++) {
115                 ret = rte_acl_classify(acx, data, results,
116                                 count, RTE_ACL_MAX_CATEGORIES);
117                 if (ret != 0) {
118                         printf("Line %i: SSE classify failed!\n", __LINE__);
119                         goto err;
120                 }
121
122                 /* check if we allow everything we should allow */
123                 for (i = 0; i < (int) count; i++) {
124                         result =
125                                 results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
126                         if (result != acl_test_data[i].allow) {
127                                 printf("Line %i: Error in allow results at %i "
128                                         "(expected %"PRIu32" got %"PRIu32")!\n",
129                                         __LINE__, i, acl_test_data[i].allow,
130                                         result);
131                                 goto err;
132                         }
133                 }
134
135                 /* check if we deny everything we should deny */
136                 for (i = 0; i < (int) count; i++) {
137                         result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
138                         if (result != acl_test_data[i].deny) {
139                                 printf("Line %i: Error in deny results at %i "
140                                         "(expected %"PRIu32" got %"PRIu32")!\n",
141                                         __LINE__, i, acl_test_data[i].deny,
142                                         result);
143                                 goto err;
144                         }
145                 }
146         }
147
148         /* make a quick check for scalar */
149         ret = rte_acl_classify_scalar(acx, data, results,
150                         RTE_DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES);
151         if (ret != 0) {
152                 printf("Line %i: SSE classify failed!\n", __LINE__);
153                 goto err;
154         }
155
156         /* check if we allow everything we should allow */
157         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
158                 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
159                 if (result != acl_test_data[i].allow) {
160                         printf("Line %i: Error in allow results at %i "
161                                         "(expected %"PRIu32" got %"PRIu32")!\n",
162                                         __LINE__, i, acl_test_data[i].allow,
163                                         result);
164                         goto err;
165                 }
166         }
167
168         /* check if we deny everything we should deny */
169         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
170                 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
171                 if (result != acl_test_data[i].deny) {
172                         printf("Line %i: Error in deny results at %i "
173                                         "(expected %"PRIu32" got %"PRIu32")!\n",
174                                         __LINE__, i, acl_test_data[i].deny,
175                                         result);
176                         goto err;
177                 }
178         }
179
180         ret = 0;
181
182 err:
183         /* swap data back to cpu order so that next time tests don't fail */
184         bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0);
185         return ret;
186 }
187
188 static int
189 test_classify_buid(struct rte_acl_ctx *acx)
190 {
191         int ret;
192         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
193                         offsetof(struct ipv4_7tuple, proto),
194                         offsetof(struct ipv4_7tuple, vlan),
195                         offsetof(struct ipv4_7tuple, ip_src),
196                         offsetof(struct ipv4_7tuple, ip_dst),
197                         offsetof(struct ipv4_7tuple, port_src),
198         };
199
200         /* add rules to the context */
201         ret = rte_acl_ipv4vlan_add_rules(acx, acl_test_rules,
202                         RTE_DIM(acl_test_rules));
203         if (ret != 0) {
204                 printf("Line %i: Adding rules to ACL context failed!\n",
205                         __LINE__);
206                 return ret;
207         }
208
209         /* try building the context */
210         ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
211         if (ret != 0) {
212                 printf("Line %i: Building ACL context failed!\n", __LINE__);
213                 return ret;
214         }
215
216         return 0;
217 }
218
219 #define TEST_CLASSIFY_ITER      4
220
221 /*
222  * Test scalar and SSE ACL lookup.
223  */
224 static int
225 test_classify(void)
226 {
227         struct rte_acl_ctx *acx;
228         int i, ret;
229
230         acx = rte_acl_create(&acl_param);
231         if (acx == NULL) {
232                 printf("Line %i: Error creating ACL context!\n", __LINE__);
233                 return -1;
234         }
235
236         ret = 0;
237         for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
238
239                 if ((i & 1) == 0)
240                         rte_acl_reset(acx);
241                 else
242                         rte_acl_reset_rules(acx);
243
244                 ret = test_classify_buid(acx);
245                 if (ret != 0) {
246                         printf("Line %i, iter: %d: "
247                                 "Adding rules to ACL context failed!\n",
248                                 __LINE__, i);
249                         break;
250                 }
251
252                 ret = test_classify_run(acx);
253                 if (ret != 0) {
254                         printf("Line %i, iter: %d: %s failed!\n",
255                                 __LINE__, i, __func__);
256                         break;
257                 }
258
259                 /* reset rules and make sure that classify still works ok. */
260                 rte_acl_reset_rules(acx);
261                 ret = test_classify_run(acx);
262                 if (ret != 0) {
263                         printf("Line %i, iter: %d: %s failed!\n",
264                                 __LINE__, i, __func__);
265                         break;
266                 }
267         }
268
269         rte_acl_free(acx);
270         return ret;
271 }
272
273 /*
274  * Test wrong layout behavior
275  * This test supplies the ACL context with invalid layout, which results in
276  * ACL matching the wrong stuff. However, it should match the wrong stuff
277  * the right way. We switch around source and destination addresses,
278  * source and destination ports, and protocol will point to first byte of
279  * destination port.
280  */
281 static int
282 test_invalid_layout(void)
283 {
284         struct rte_acl_ctx *acx;
285         int ret, i;
286
287         uint32_t results[RTE_DIM(invalid_layout_data)];
288         const uint8_t *data[RTE_DIM(invalid_layout_data)];
289
290         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
291                         /* proto points to destination port's first byte */
292                         offsetof(struct ipv4_7tuple, port_dst),
293
294                         0, /* VLAN not used */
295
296                         /* src and dst addresses are swapped */
297                         offsetof(struct ipv4_7tuple, ip_dst),
298                         offsetof(struct ipv4_7tuple, ip_src),
299
300                         /*
301                          * we can't swap ports here, so we will swap
302                          * them in the data
303                          */
304                         offsetof(struct ipv4_7tuple, port_src),
305         };
306
307         acx = rte_acl_create(&acl_param);
308         if (acx == NULL) {
309                 printf("Line %i: Error creating ACL context!\n", __LINE__);
310                 return -1;
311         }
312
313         /* putting a lot of rules into the context results in greater
314          * coverage numbers. it doesn't matter if they are identical */
315         for (i = 0; i < 1000; i++) {
316                 /* add rules to the context */
317                 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
318                                 RTE_DIM(invalid_layout_rules));
319                 if (ret != 0) {
320                         printf("Line %i: Adding rules to ACL context failed!\n",
321                                 __LINE__);
322                         rte_acl_free(acx);
323                         return -1;
324                 }
325         }
326
327         /* try building the context */
328         ret = rte_acl_ipv4vlan_build(acx, layout, 1);
329         if (ret != 0) {
330                 printf("Line %i: Building ACL context failed!\n", __LINE__);
331                 rte_acl_free(acx);
332                 return -1;
333         }
334
335         /* swap all bytes in the data to network order */
336         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
337
338         /* prepare data */
339         for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
340                 data[i] = (uint8_t *)&invalid_layout_data[i];
341         }
342
343         /* classify tuples */
344         ret = rte_acl_classify(acx, data, results,
345                         RTE_DIM(results), 1);
346         if (ret != 0) {
347                 printf("Line %i: SSE classify failed!\n", __LINE__);
348                 rte_acl_free(acx);
349                 return -1;
350         }
351
352         for (i = 0; i < (int) RTE_DIM(results); i++) {
353                 if (results[i] != invalid_layout_data[i].allow) {
354                         printf("Line %i: Wrong results at %i "
355                                 "(result=%u, should be %u)!\n",
356                                 __LINE__, i, results[i],
357                                 invalid_layout_data[i].allow);
358                         goto err;
359                 }
360         }
361
362         /* classify tuples (scalar) */
363         ret = rte_acl_classify_scalar(acx, data, results,
364                         RTE_DIM(results), 1);
365         if (ret != 0) {
366                 printf("Line %i: Scalar classify failed!\n", __LINE__);
367                 rte_acl_free(acx);
368                 return -1;
369         }
370
371         for (i = 0; i < (int) RTE_DIM(results); i++) {
372                 if (results[i] != invalid_layout_data[i].allow) {
373                         printf("Line %i: Wrong results at %i "
374                                 "(result=%u, should be %u)!\n",
375                                 __LINE__, i, results[i],
376                                 invalid_layout_data[i].allow);
377                         goto err;
378                 }
379         }
380
381         rte_acl_free(acx);
382
383         /* swap data back to cpu order so that next time tests don't fail */
384         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
385
386         return 0;
387 err:
388
389         /* swap data back to cpu order so that next time tests don't fail */
390         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
391
392         rte_acl_free(acx);
393
394         return -1;
395 }
396
397 /*
398  * Test creating and finding ACL contexts, and adding rules
399  */
400 static int
401 test_create_find_add(void)
402 {
403         struct rte_acl_param param;
404         struct rte_acl_ctx *acx, *acx2, *tmp;
405         struct rte_acl_ipv4vlan_rule rules[LEN];
406
407         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
408
409         const char *acx_name = "acx";
410         const char *acx2_name = "acx2";
411         int i, ret;
412
413         /* create two contexts */
414         memcpy(&param, &acl_param, sizeof(param));
415         param.max_rule_num = 2;
416
417         param.name = acx_name;
418         acx = rte_acl_create(&param);
419         if (acx == NULL) {
420                 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
421                 return -1;
422         }
423
424         param.name = acx2_name;
425         acx2 = rte_acl_create(&param);
426         if (acx2 == NULL || acx2 == acx) {
427                 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
428                 rte_acl_free(acx);
429                 return -1;
430         }
431
432         /* try to create third one, with an existing name */
433         param.name = acx_name;
434         tmp = rte_acl_create(&param);
435         if (tmp != acx) {
436                 printf("Line %i: Creating context with existing name "
437                         "test failed!\n",
438                         __LINE__);
439                 if (tmp)
440                         rte_acl_free(tmp);
441                 goto err;
442         }
443
444         param.name = acx2_name;
445         tmp = rte_acl_create(&param);
446         if (tmp != acx2) {
447                 printf("Line %i: Creating context with existing "
448                         "name test 2 failed!\n",
449                         __LINE__);
450                 if (tmp)
451                         rte_acl_free(tmp);
452                 goto err;
453         }
454
455         /* try to find existing ACL contexts */
456         tmp = rte_acl_find_existing(acx_name);
457         if (tmp != acx) {
458                 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
459                 if (tmp)
460                         rte_acl_free(tmp);
461                 goto err;
462         }
463
464         tmp = rte_acl_find_existing(acx2_name);
465         if (tmp != acx2) {
466                 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
467                 if (tmp)
468                         rte_acl_free(tmp);
469                 goto err;
470         }
471
472         /* try to find non-existing context */
473         tmp = rte_acl_find_existing("invalid");
474         if (tmp != NULL) {
475                 printf("Line %i: Non-existent ACL context found!\n", __LINE__);
476                 goto err;
477         }
478
479         /* free context */
480         rte_acl_free(acx);
481
482
483         /* create valid (but severely limited) acx */
484         memcpy(&param, &acl_param, sizeof(param));
485         param.max_rule_num = LEN;
486
487         acx = rte_acl_create(&param);
488         if (acx == NULL) {
489                 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
490                 goto err;
491         }
492
493         /* create dummy acl */
494         for (i = 0; i < LEN; i++) {
495                 memcpy(&rules[i], &acl_rule,
496                         sizeof(struct rte_acl_ipv4vlan_rule));
497                 /* skip zero */
498                 rules[i].data.userdata = i + 1;
499                 /* one rule per category */
500                 rules[i].data.category_mask = 1 << i;
501         }
502
503         /* try filling up the context */
504         ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
505         if (ret != 0) {
506                 printf("Line %i: Adding %i rules to ACL context failed!\n",
507                                 __LINE__, LEN);
508                 goto err;
509         }
510
511         /* try adding to a (supposedly) full context */
512         ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
513         if (ret == 0) {
514                 printf("Line %i: Adding rules to full ACL context should"
515                                 "have failed!\n", __LINE__);
516                 goto err;
517         }
518
519         /* try building the context */
520         ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
521         if (ret != 0) {
522                 printf("Line %i: Building ACL context failed!\n", __LINE__);
523                 goto err;
524         }
525
526         rte_acl_free(acx);
527         rte_acl_free(acx2);
528
529         return 0;
530 err:
531         rte_acl_free(acx);
532         rte_acl_free(acx2);
533         return -1;
534 }
535
536 /*
537  * test various invalid rules
538  */
539 static int
540 test_invalid_rules(void)
541 {
542         struct rte_acl_ctx *acx;
543         int ret;
544
545         struct rte_acl_ipv4vlan_rule rule;
546
547         acx = rte_acl_create(&acl_param);
548         if (acx == NULL) {
549                 printf("Line %i: Error creating ACL context!\n", __LINE__);
550                 return -1;
551         }
552
553         /* test inverted high/low source and destination ports.
554          * originally, there was a problem with memory consumption when using
555          * such rules.
556          */
557         /* create dummy acl */
558         memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
559         rule.data.userdata = 1;
560         rule.dst_port_low = 0xfff0;
561         rule.dst_port_high = 0x0010;
562
563         /* add rules to context and try to build it */
564         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
565         if (ret == 0) {
566                 printf("Line %i: Adding rules to ACL context "
567                                 "should have failed!\n", __LINE__);
568                 goto err;
569         }
570
571         rule.dst_port_low = 0x0;
572         rule.dst_port_high = 0xffff;
573         rule.src_port_low = 0xfff0;
574         rule.src_port_high = 0x0010;
575
576         /* add rules to context and try to build it */
577         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
578         if (ret == 0) {
579                 printf("Line %i: Adding rules to ACL context "
580                                 "should have failed!\n", __LINE__);
581                 goto err;
582         }
583
584         rule.dst_port_low = 0x0;
585         rule.dst_port_high = 0xffff;
586         rule.src_port_low = 0x0;
587         rule.src_port_high = 0xffff;
588
589         rule.dst_mask_len = 33;
590
591         /* add rules to context and try to build it */
592         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
593         if (ret == 0) {
594                 printf("Line %i: Adding rules to ACL context "
595                                 "should have failed!\n", __LINE__);
596                 goto err;
597         }
598
599         rule.dst_mask_len = 0;
600         rule.src_mask_len = 33;
601
602         /* add rules to context and try to build it */
603         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
604         if (ret == 0) {
605                 printf("Line %i: Adding rules to ACL context "
606                                 "should have failed!\n", __LINE__);
607                 goto err;
608         }
609
610         rule.dst_mask_len = 0;
611         rule.src_mask_len = 0;
612         rule.data.userdata = 0;
613
614         /* try adding this rule (it should fail because userdata is invalid) */
615         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
616         if (ret == 0) {
617                 printf("Line %i: Adding a rule with invalid user data "
618                                 "should have failed!\n", __LINE__);
619                 rte_acl_free(acx);
620                 return -1;
621         }
622
623         rte_acl_free(acx);
624
625         return 0;
626
627 err:
628         rte_acl_free(acx);
629
630         return -1;
631 }
632
633 /*
634  * test functions by passing invalid or
635  * non-workable parameters.
636  *
637  * we do very limited testing of classify functions here
638  * because those are performance-critical and
639  * thus don't do much parameter checking.
640  */
641 static int
642 test_invalid_parameters(void)
643 {
644         struct rte_acl_param param;
645         struct rte_acl_ctx *acx;
646         struct rte_acl_ipv4vlan_rule rule;
647         int result;
648
649         uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
650
651
652         /**
653          * rte_ac_create()
654          */
655
656         /* NULL param */
657         acx = rte_acl_create(NULL);
658         if (acx != NULL) {
659                 printf("Line %i: ACL context creation with NULL param "
660                                 "should have failed!\n", __LINE__);
661                 rte_acl_free(acx);
662                 return -1;
663         }
664
665         /* zero rule size */
666         memcpy(&param, &acl_param, sizeof(param));
667         param.rule_size = 0;
668
669         acx = rte_acl_create(&param);
670         if (acx == NULL) {
671                 printf("Line %i: ACL context creation with zero rule len "
672                                 "failed!\n", __LINE__);
673                 return -1;
674         } else
675                 rte_acl_free(acx);
676
677         /* zero max rule num */
678         memcpy(&param, &acl_param, sizeof(param));
679         param.max_rule_num = 0;
680
681         acx = rte_acl_create(&param);
682         if (acx == NULL) {
683                 printf("Line %i: ACL context creation with zero rule num "
684                                 "failed!\n", __LINE__);
685                 return -1;
686         } else
687                 rte_acl_free(acx);
688
689         /* invalid NUMA node */
690         memcpy(&param, &acl_param, sizeof(param));
691         param.socket_id = RTE_MAX_NUMA_NODES + 1;
692
693         acx = rte_acl_create(&param);
694         if (acx != NULL) {
695                 printf("Line %i: ACL context creation with invalid NUMA "
696                                 "should have failed!\n", __LINE__);
697                 rte_acl_free(acx);
698                 return -1;
699         }
700
701         /* NULL name */
702         memcpy(&param, &acl_param, sizeof(param));
703         param.name = NULL;
704
705         acx = rte_acl_create(&param);
706         if (acx != NULL) {
707                 printf("Line %i: ACL context creation with NULL name "
708                                 "should have failed!\n", __LINE__);
709                 rte_acl_free(acx);
710                 return -1;
711         }
712
713         /**
714          * rte_acl_find_existing
715          */
716
717         acx = rte_acl_find_existing(NULL);
718         if (acx != NULL) {
719                 printf("Line %i: NULL ACL context found!\n", __LINE__);
720                 rte_acl_free(acx);
721                 return -1;
722         }
723
724         /**
725          * rte_acl_ipv4vlan_add_rules
726          */
727
728         /* initialize everything */
729         memcpy(&param, &acl_param, sizeof(param));
730         acx = rte_acl_create(&param);
731         if (acx == NULL) {
732                 printf("Line %i: ACL context creation failed!\n", __LINE__);
733                 return -1;
734         }
735
736         memcpy(&rule, &acl_rule, sizeof(rule));
737
738         /* NULL context */
739         result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
740         if (result == 0) {
741                 printf("Line %i: Adding rules with NULL ACL context "
742                                 "should have failed!\n", __LINE__);
743                 rte_acl_free(acx);
744                 return -1;
745         }
746
747         /* NULL rule */
748         result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
749         if (result == 0) {
750                 printf("Line %i: Adding NULL rule to ACL context "
751                                 "should have failed!\n", __LINE__);
752                 rte_acl_free(acx);
753                 return -1;
754         }
755
756         /* zero count (should succeed) */
757         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
758         if (result != 0) {
759                 printf("Line %i: Adding 0 rules to ACL context failed!\n",
760                         __LINE__);
761                 rte_acl_free(acx);
762                 return -1;
763         }
764
765         /* free ACL context */
766         rte_acl_free(acx);
767
768         /* set wrong rule_size so that adding any rules would fail */
769         param.rule_size = RTE_ACL_IPV4VLAN_RULE_SZ + 4;
770         acx = rte_acl_create(&param);
771         if (acx == NULL) {
772                 printf("Line %i: ACL context creation failed!\n", __LINE__);
773                 return -1;
774         }
775
776         /* try adding a rule with size different from context rule_size */
777         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
778         if (result == 0) {
779                 printf("Line %i: Adding an invalid sized rule "
780                                 "should have failed!\n", __LINE__);
781                 rte_acl_free(acx);
782                 return -1;
783         }
784
785         /* free ACL context */
786         rte_acl_free(acx);
787
788
789         /**
790          * rte_acl_ipv4vlan_build
791          */
792
793         /* reinitialize context */
794         memcpy(&param, &acl_param, sizeof(param));
795         acx = rte_acl_create(&param);
796         if (acx == NULL) {
797                 printf("Line %i: ACL context creation failed!\n", __LINE__);
798                 return -1;
799         }
800
801         /* NULL context */
802         result = rte_acl_ipv4vlan_build(NULL, layout, 1);
803         if (result == 0) {
804                 printf("Line %i: Building with NULL context "
805                                 "should have failed!\n", __LINE__);
806                 rte_acl_free(acx);
807                 return -1;
808         }
809
810         /* NULL layout */
811         result = rte_acl_ipv4vlan_build(acx, NULL, 1);
812         if (result == 0) {
813                 printf("Line %i: Building with NULL layout "
814                                 "should have failed!\n", __LINE__);
815                 rte_acl_free(acx);
816                 return -1;
817         }
818
819         /* zero categories (should not fail) */
820         result = rte_acl_ipv4vlan_build(acx, layout, 0);
821         if (result == 0) {
822                 printf("Line %i: Building with 0 categories should fail!\n",
823                         __LINE__);
824                 rte_acl_free(acx);
825                 return -1;
826         }
827
828         /* SSE classify test */
829
830         /* cover zero categories in classify (should not fail) */
831         result = rte_acl_classify(acx, NULL, NULL, 0, 0);
832         if (result != 0) {
833                 printf("Line %i: SSE classify with zero categories "
834                                 "failed!\n", __LINE__);
835                 rte_acl_free(acx);
836                 return -1;
837         }
838
839         /* cover invalid but positive categories in classify */
840         result = rte_acl_classify(acx, NULL, NULL, 0, 3);
841         if (result == 0) {
842                 printf("Line %i: SSE classify with 3 categories "
843                                 "should have failed!\n", __LINE__);
844                 rte_acl_free(acx);
845                 return -1;
846         }
847
848         /* scalar classify test */
849
850         /* cover zero categories in classify (should not fail) */
851         result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 0);
852         if (result != 0) {
853                 printf("Line %i: Scalar classify with zero categories "
854                                 "failed!\n", __LINE__);
855                 rte_acl_free(acx);
856                 return -1;
857         }
858
859         /* cover invalid but positive categories in classify */
860         result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 3);
861         if (result == 0) {
862                 printf("Line %i: Scalar classify with 3 categories "
863                                 "should have failed!\n", __LINE__);
864                 rte_acl_free(acx);
865                 return -1;
866         }
867
868         /* free ACL context */
869         rte_acl_free(acx);
870
871
872         /**
873          * make sure void functions don't crash with NULL parameters
874          */
875
876         rte_acl_free(NULL);
877
878         rte_acl_dump(NULL);
879
880         return 0;
881 }
882
883 /**
884  * Various tests that don't test much but improve coverage
885  */
886 static int
887 test_misc(void)
888 {
889         struct rte_acl_param param;
890         struct rte_acl_ctx *acx;
891
892         /* create context */
893         memcpy(&param, &acl_param, sizeof(param));
894
895         acx = rte_acl_create(&param);
896         if (acx == NULL) {
897                 printf("Line %i: Error creating ACL context!\n", __LINE__);
898                 return -1;
899         }
900
901         /* dump context with rules - useful for coverage */
902         rte_acl_list_dump();
903
904         rte_acl_dump(acx);
905
906         rte_acl_free(acx);
907
908         return 0;
909 }
910
911 static int
912 test_acl(void)
913 {
914         if (test_invalid_parameters() < 0)
915                 return -1;
916         if (test_invalid_rules() < 0)
917                 return -1;
918         if (test_create_find_add() < 0)
919                 return -1;
920         if (test_invalid_layout() < 0)
921                 return -1;
922         if (test_misc() < 0)
923                 return -1;
924         if (test_classify() < 0)
925                 return -1;
926
927         return 0;
928 }
929
930 static struct test_command acl_cmd = {
931         .command = "acl_autotest",
932         .callback = test_acl,
933 };
934 REGISTER_TEST_COMMAND(acl_cmd);