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