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