doc: whitespace changes in licenses
[dpdk.git] / app / test / test_pmac_acl.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 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 <cmdline_parse.h>
38
39 #include <rte_string_fns.h>
40 #include <rte_mbuf.h>
41
42 #include "test.h"
43
44 #ifdef RTE_LIBRTE_PMAC
45
46 #include <rte_byteorder.h>
47 #include <rte_ip.h>
48 #include <rte_acl.h>
49
50 #include "test_pmac_acl.h"
51
52 #define LEN RTE_ACL_MAX_CATEGORIES
53
54 struct rte_acl_param acl_param = {
55         .name = "acl_ctx",
56         .socket_id = SOCKET_ID_ANY,
57         .rule_size = sizeof(struct rte_acl_ipv4vlan_rule),
58         .max_rule_num = 0x30000,
59 };
60
61 struct rte_acl_ipv4vlan_rule acl_rule = {
62                 .data = { .priority = 1, .category_mask = 0xff },
63                 .src_port_low = 0,
64                 .src_port_high = UINT16_MAX,
65                 .dst_port_low = 0,
66                 .dst_port_high = UINT16_MAX,
67 };
68
69 /* byteswap to cpu or network order */
70 static void
71 bswap_test_data(struct ipv4_7tuple * data, int len, int to_be)
72 {
73         int i;
74
75         for (i = 0; i < len; i++) {
76
77                 if (to_be) {
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);
85                 }
86                 else {
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);
93                 }
94         }
95 }
96
97 /*
98  * Test scalar and SSE ACL lookup.
99  */
100 static int
101 test_classify(void)
102 {
103         struct rte_acl_ctx * acx;
104         int ret, i;
105         uint32_t result, count;
106
107         uint32_t results[DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
108
109         const uint8_t * data[DIM(acl_test_data)];
110
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),
117         };
118
119         acx = rte_acl_create(&acl_param);
120         if (acx == NULL) {
121                 printf("Line %i: Error creating ACL context!\n", __LINE__);
122                 return -1;
123         }
124
125         /* add rules to the context */
126         ret = rte_acl_ipv4vlan_add_rules(acx, acl_test_rules,
127                         DIM(acl_test_rules));
128         if (ret != 0) {
129                 printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
130                 rte_acl_free(acx);
131                 return -1;
132         }
133
134         /* try building the context */
135         ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
136         if (ret != 0) {
137                 printf("Line %i: Building ACL context failed!\n", __LINE__);
138                 rte_acl_free(acx);
139                 return -1;
140         }
141
142         /* swap all bytes in the data to network order */
143         bswap_test_data(acl_test_data, DIM(acl_test_data), 1);
144
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];
148
149         /**
150          * these will run quite a few times, it's necessary to test code paths
151          * from num=0 to num>8
152          */
153         for (count = 0; count < DIM(acl_test_data); count++) {
154                 ret = rte_acl_classify(acx, data, results,
155                                 count, RTE_ACL_MAX_CATEGORIES);
156                 if (ret != 0) {
157                         printf("Line %i: SSE classify failed!\n", __LINE__);
158                         goto err;
159                 }
160
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,
168                                                 result);
169                                 goto err;
170                         }
171                 }
172
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,
180                                                 result);
181                                 goto err;
182                         }
183                 }
184         }
185
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);
189         if (ret != 0) {
190                 printf("Line %i: SSE classify failed!\n", __LINE__);
191                 goto err;
192         }
193
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,
201                                         result);
202                         goto err;
203                 }
204         }
205
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,
213                                         result);
214                         goto err;
215                 }
216         }
217
218         /* free ACL context */
219         rte_acl_free(acx);
220
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);
223
224         return 0;
225 err:
226
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);
229
230         rte_acl_free(acx);
231
232         return -1;
233 }
234
235 /*
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
241  * destination port.
242  */
243 static int
244 test_invalid_layout(void)
245 {
246         struct rte_acl_ctx * acx;
247         int ret, i;
248
249         uint32_t results[DIM(invalid_layout_data)];
250         const uint8_t * data[DIM(invalid_layout_data)];
251
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),
255
256                         0, /* VLAN not used */
257
258                         /* src and dst addresses are swapped */
259                         offsetof(struct ipv4_7tuple, ip_dst),
260                         offsetof(struct ipv4_7tuple, ip_src),
261
262                         /* we can't swap ports here, so we will swap them in the data */
263                         offsetof(struct ipv4_7tuple, port_src),
264         };
265
266         acx = rte_acl_create(&acl_param);
267         if (acx == NULL) {
268                 printf("Line %i: Error creating ACL context!\n", __LINE__);
269                 return -1;
270         }
271
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));
278                 if (ret != 0) {
279                         printf("Line %i: Adding rules to ACL context failed!\n", __LINE__);
280                         rte_acl_free(acx);
281                         return -1;
282                 }
283         }
284
285         /* try building the context */
286         ret = rte_acl_ipv4vlan_build(acx, layout, 1);
287         if (ret != 0) {
288                 printf("Line %i: Building ACL context failed!\n", __LINE__);
289                 rte_acl_free(acx);
290                 return -1;
291         }
292
293         /* swap all bytes in the data to network order */
294         bswap_test_data(invalid_layout_data, DIM(invalid_layout_data), 1);
295
296         /* prepare data */
297         for (i = 0; i < (int) DIM(invalid_layout_data); i++) {
298                 data[i] = (uint8_t *)&invalid_layout_data[i];
299         }
300
301         /* classify tuples */
302         ret = rte_acl_classify(acx, data, results,
303                         DIM(results), 1);
304         if (ret != 0) {
305                 printf("Line %i: SSE classify failed!\n", __LINE__);
306                 rte_acl_free(acx);
307                 return -1;
308         }
309
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);
314                         goto err;
315                 }
316         }
317
318         /* classify tuples (scalar) */
319         ret = rte_acl_classify_scalar(acx, data, results,
320                         DIM(results), 1);
321         if (ret != 0) {
322                 printf("Line %i: Scalar classify failed!\n", __LINE__);
323                 rte_acl_free(acx);
324                 return -1;
325         }
326
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);
331                         goto err;
332                 }
333         }
334
335         rte_acl_free(acx);
336
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);
339
340         return 0;
341 err:
342
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);
345
346         rte_acl_free(acx);
347
348         return -1;
349 }
350
351 /*
352  * Test creating and finding ACL contexts, and adding rules
353  */
354 static int
355 test_create_find_add(void)
356 {
357         struct rte_acl_param param;
358         struct rte_acl_ctx * acx, *acx2, *tmp;
359         struct rte_acl_ipv4vlan_rule rules[LEN];
360
361         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
362
363         const char * acx_name = "acx";
364         const char * acx2_name = "acx2";
365         int i, ret;
366
367         /* create two contexts */
368         memcpy(&param, &acl_param, sizeof(param));
369         param.max_rule_num = 2;
370
371         param.name = acx_name;
372         acx = rte_acl_create(&param);
373         if (acx == NULL) {
374                 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
375                 return -1;
376         }
377
378         param.name = acx2_name;
379         acx2 = rte_acl_create(&param);
380         if (acx2 == NULL || acx2 == acx) {
381                 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
382                 rte_acl_free(acx);
383                 return -1;
384         }
385
386         /* try to create third one, with an existing name */
387         param.name = acx_name;
388         tmp = rte_acl_create(&param);
389         if (tmp != acx) {
390                 printf("Line %i: Creating context with existing name test failed!\n",
391                                 __LINE__);
392                 if (tmp)
393                         rte_acl_free(tmp);
394                 goto err;
395         }
396
397         param.name = acx2_name;
398         tmp = rte_acl_create(&param);
399         if (tmp != acx2) {
400                 printf("Line %i: Creating context with existing name test 2 failed!\n",
401                                 __LINE__);
402                 if (tmp)
403                         rte_acl_free(tmp);
404                 goto err;
405         }
406
407         /* try to find existing PM contexts */
408         tmp = rte_acl_find_existing(acx_name);
409         if (tmp != acx) {
410                 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
411                 if (tmp)
412                         rte_acl_free(tmp);
413                 goto err;
414         }
415
416         tmp = rte_acl_find_existing(acx2_name);
417         if (tmp != acx2) {
418                 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
419                 if (tmp)
420                         rte_acl_free(tmp);
421                 goto err;
422         }
423
424         /* try to find non-existing context */
425         tmp = rte_acl_find_existing("invalid");
426         if (tmp != NULL) {
427                 printf("Line %i: Non-existent PM context found!\n", __LINE__);
428                 goto err;
429         }
430
431         /* free context */
432         rte_acl_free(acx);
433
434
435         /* create valid (but severely limited) acx */
436         memcpy(&param, &acl_param, sizeof(param));
437         param.max_rule_num = LEN;
438
439         acx = rte_acl_create(&param);
440         if (acx == NULL) {
441                 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
442                 goto err;
443         }
444
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 */
450         }
451
452         /* try filling up the context */
453         ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
454         if (ret != 0) {
455                 printf("Line %i: Adding %i rules to ACL context failed!\n",
456                                 __LINE__, LEN);
457                 goto err;
458         }
459
460         /* try adding to a (supposedly) full context */
461         ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
462         if (ret == 0) {
463                 printf("Line %i: Adding rules to full ACL context should"
464                                 "have failed!\n", __LINE__);
465                 goto err;
466         }
467
468         /* try building the context */
469         ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
470         if (ret != 0) {
471                 printf("Line %i: Building ACL context failed!\n", __LINE__);
472                 goto err;
473         }
474
475         rte_acl_free(acx);
476         rte_acl_free(acx2);
477
478         return 0;
479 err:
480         rte_acl_free(acx);
481         rte_acl_free(acx2);
482         return -1;
483 }
484
485 /*
486  * test various invalid rules
487  */
488 static int
489 test_invalid_rules(void)
490 {
491         struct rte_acl_ctx * acx;
492         int ret;
493
494         struct rte_acl_ipv4vlan_rule rule;
495
496         acx = rte_acl_create(&acl_param);
497         if (acx == NULL) {
498                 printf("Line %i: Error creating ACL context!\n", __LINE__);
499                 return -1;
500         }
501
502         /* test inverted high/low source and destination ports.
503          * originally, there was a problem with memory consumption when using
504          * such rules.
505          */
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;
511
512         /* add rules to context and try to build it */
513         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
514         if (ret == 0) {
515                 printf("Line %i: Adding rules to ACL context "
516                                 "should have failed!\n", __LINE__);
517                 goto err;
518         }
519
520         rule.dst_port_low = 0x0;
521         rule.dst_port_high = 0xffff;
522         rule.src_port_low = 0xfff0;
523         rule.src_port_high = 0x0010;
524
525         /* add rules to context and try to build it */
526         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
527         if (ret == 0) {
528                 printf("Line %i: Adding rules to ACL context "
529                                 "should have failed!\n", __LINE__);
530                 goto err;
531         }
532
533         rule.dst_port_low = 0x0;
534         rule.dst_port_high = 0xffff;
535         rule.src_port_low = 0x0;
536         rule.src_port_high = 0xffff;
537
538         rule.dst_mask_len = 33;
539
540         /* add rules to context and try to build it */
541         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
542         if (ret == 0) {
543                 printf("Line %i: Adding rules to ACL context "
544                                 "should have failed!\n", __LINE__);
545                 goto err;
546         }
547
548         rule.dst_mask_len = 0;
549         rule.src_mask_len = 33;
550
551         /* add rules to context and try to build it */
552         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
553         if (ret == 0) {
554                 printf("Line %i: Adding rules to ACL context "
555                                 "should have failed!\n", __LINE__);
556                 goto err;
557         }
558
559         rule.dst_mask_len = 0;
560         rule.src_mask_len = 0;
561         rule.data.userdata = 0;
562
563         /* try adding this rule (it should fail because userdata is invalid) */
564         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
565         if (ret == 0) {
566                 printf("Line %i: Adding a rule with invalid user data "
567                                 "should have failed!\n", __LINE__);
568                 rte_acl_free(acx);
569                 return -1;
570         }
571
572         rte_acl_free(acx);
573
574         return 0;
575
576 err:
577         rte_acl_free(acx);
578
579         return -1;
580 }
581
582 /*
583  * test functions by passing invalid or
584  * non-workable parameters.
585  *
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.
589  */
590 static int
591 test_invalid_parameters(void)
592 {
593         struct rte_acl_param param;
594         struct rte_acl_ctx * acx;
595         struct rte_acl_ipv4vlan_rule rule;
596         int result;
597
598         uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
599
600
601         /**
602          * rte_ac_create()
603          */
604
605         /* NULL param */
606         acx = rte_acl_create(NULL);
607         if (acx != NULL) {
608                 printf("Line %i: ACL context creation with NULL param "
609                                 "should have failed!\n", __LINE__);
610                 rte_acl_free(acx);
611                 return -1;
612         }
613
614         /* zero rule size */
615         memcpy(&param, &acl_param, sizeof(param));
616         param.rule_size = 0;
617
618         acx = rte_acl_create(&param);
619         if (acx == NULL) {
620                 printf("Line %i: ACL context creation with zero rule len "
621                                 "failed!\n", __LINE__);
622                 return -1;
623         }
624         else
625                 rte_acl_free(acx);
626
627         /* zero max rule num */
628         memcpy(&param, &acl_param, sizeof(param));
629         param.max_rule_num = 0;
630
631         acx = rte_acl_create(&param);
632         if (acx == NULL) {
633                 printf("Line %i: ACL context creation with zero rule num "
634                                 "failed!\n", __LINE__);
635                 return -1;
636         }
637         else
638                 rte_acl_free(acx);
639
640         /* invalid NUMA node */
641         memcpy(&param, &acl_param, sizeof(param));
642         param.socket_id = RTE_MAX_NUMA_NODES + 1;
643
644         acx = rte_acl_create(&param);
645         if (acx != NULL) {
646                 printf("Line %i: ACL context creation with invalid NUMA "
647                                 "should have failed!\n", __LINE__);
648                 rte_acl_free(acx);
649                 return -1;
650         }
651
652         /* NULL name */
653         memcpy(&param, &acl_param, sizeof(param));
654         param.name = NULL;
655
656         acx = rte_acl_create(&param);
657         if (acx != NULL) {
658                 printf("Line %i: ACL context creation with NULL name "
659                                 "should have failed!\n", __LINE__);
660                 rte_acl_free(acx);
661                 return -1;
662         }
663
664         /**
665          * rte_acl_find_existing
666          */
667
668         acx = rte_acl_find_existing(NULL);
669         if (acx != NULL) {
670                 printf("Line %i: NULL ACL context found!\n", __LINE__);
671                 rte_acl_free(acx);
672                 return -1;
673         }
674
675         /**
676          * rte_acl_ipv4vlan_add_rules
677          */
678
679         /* initialize everything */
680         memcpy(&param, &acl_param, sizeof(param));
681         acx = rte_acl_create(&param);
682         if (acx == NULL) {
683                 printf("Line %i: ACL context creation failed!\n", __LINE__);
684                 return -1;
685         }
686
687         memcpy(&rule, &acl_rule, sizeof(rule));
688
689         /* NULL context */
690         result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
691         if (result == 0) {
692                 printf("Line %i: Adding rules with NULL ACL context "
693                                 "should have failed!\n", __LINE__);
694                 rte_acl_free(acx);
695                 return -1;
696         }
697
698         /* NULL rule */
699         result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
700         if (result == 0) {
701                 printf("Line %i: Adding NULL rule to ACL context "
702                                 "should have failed!\n", __LINE__);
703                 rte_acl_free(acx);
704                 return -1;
705         }
706
707         /* zero count (should succeed) */
708         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
709         if (result != 0) {
710                 printf("Line %i: Adding 0 rules to ACL context failed!\n", __LINE__);
711                 rte_acl_free(acx);
712                 return -1;
713         }
714
715         /* free ACL context */
716         rte_acl_free(acx);
717
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(&param);
721         if (acx == NULL) {
722                 printf("Line %i: ACL context creation failed!\n", __LINE__);
723                 return -1;
724         }
725
726         /* try adding a rule with size different from context rule_size */
727         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
728         if (result == 0) {
729                 printf("Line %i: Adding an invalid sized rule "
730                                 "should have failed!\n", __LINE__);
731                 rte_acl_free(acx);
732                 return -1;
733         }
734
735         /* free ACL context */
736         rte_acl_free(acx);
737
738
739         /**
740          * rte_acl_ipv4vlan_build
741          */
742
743         /* reinitialize context */
744         memcpy(&param, &acl_param, sizeof(param));
745         acx = rte_acl_create(&param);
746         if (acx == NULL) {
747                 printf("Line %i: ACL context creation failed!\n", __LINE__);
748                 return -1;
749         }
750
751         /* NULL context */
752         result = rte_acl_ipv4vlan_build(NULL, layout, 1);
753         if (result == 0) {
754                 printf("Line %i: Building with NULL context "
755                                 "should have failed!\n", __LINE__);
756                 rte_acl_free(acx);
757                 return -1;
758         }
759
760         /* NULL layout */
761         result = rte_acl_ipv4vlan_build(acx, NULL, 1);
762         if (result == 0) {
763                 printf("Line %i: Building with NULL layout "
764                                 "should have failed!\n", __LINE__);
765                 rte_acl_free(acx);
766                 return -1;
767         }
768
769         /* zero categories (should not fail) */
770         result = rte_acl_ipv4vlan_build(acx, layout, 0);
771         if (result != 0) {
772                 printf("Line %i: Building with 0 categories failed!\n", __LINE__);
773                 rte_acl_free(acx);
774                 return -1;
775         }
776
777         /* SSE classify test */
778
779         /* cover zero categories in classify (should not fail) */
780         result = rte_acl_classify(acx, NULL, NULL, 0, 0);
781         if (result != 0) {
782                 printf("Line %i: SSE classify with zero categories "
783                                 "failed!\n", __LINE__);
784                 rte_acl_free(acx);
785                 return -1;
786         }
787
788         /* cover invalid but positive categories in classify */
789         result = rte_acl_classify(acx, NULL, NULL, 0, 3);
790         if (result == 0) {
791                 printf("Line %i: SSE classify with 3 categories "
792                                 "should have failed!\n", __LINE__);
793                 rte_acl_free(acx);
794                 return -1;
795         }
796
797         /* scalar classify test */
798
799         /* cover zero categories in classify (should not fail) */
800         result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 0);
801         if (result != 0) {
802                 printf("Line %i: Scalar classify with zero categories "
803                                 "failed!\n", __LINE__);
804                 rte_acl_free(acx);
805                 return -1;
806         }
807
808         /* cover invalid but positive categories in classify */
809         result = rte_acl_classify_scalar(acx, NULL, NULL, 0, 3);
810         if (result == 0) {
811                 printf("Line %i: Scalar classify with 3 categories "
812                                 "should have failed!\n", __LINE__);
813                 rte_acl_free(acx);
814                 return -1;
815         }
816
817         /* free ACL context */
818         rte_acl_free(acx);
819
820
821         /**
822          * make sure void functions don't crash with NULL parameters
823          */
824
825         rte_acl_free(NULL);
826
827         rte_acl_dump(NULL);
828
829         return 0;
830 }
831
832 /**
833  * Various tests that don't test much but improve coverage
834  */
835 static int
836 test_misc(void)
837 {
838         struct rte_acl_param param;
839         struct rte_acl_ctx * acx;
840
841         /* create context */
842         memcpy(&param, &acl_param, sizeof(param));
843
844         acx = rte_acl_create(&param);
845         if (acx == NULL) {
846                 printf("Line %i: Error creating ACL context!\n", __LINE__);
847                 return -1;
848         }
849
850         /* dump context with rules - useful for coverage */
851         rte_acl_list_dump();
852
853         rte_acl_dump(acx);
854
855         rte_acl_free(acx);
856
857         return 0;
858 }
859
860 int
861 test_pmac_acl(void)
862 {
863         if (test_invalid_parameters() < 0)
864                 return -1;
865         if (test_invalid_rules() < 0)
866                 return -1;
867         if (test_create_find_add() < 0)
868                 return -1;
869         if (test_invalid_layout() < 0)
870                 return -1;
871         if (test_misc() < 0)
872                 return -1;
873         if (test_classify() < 0)
874                 return -1;
875
876         return 0;
877 }
878 #else
879
880 int
881 test_pmac_acl(void)
882 {
883         printf("This binary was not compiled with PMAC support!\n");
884         return 0;
885 }
886
887 #endif /* RTE_LIBRTE_PMAC */