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