acl: add new test cases
[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 RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS);
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 const uint32_t ipv4_7tuple_layout[RTE_ACL_IPV4VLAN_NUM] = {
68         offsetof(struct ipv4_7tuple, proto),
69         offsetof(struct ipv4_7tuple, vlan),
70         offsetof(struct ipv4_7tuple, ip_src),
71         offsetof(struct ipv4_7tuple, ip_dst),
72         offsetof(struct ipv4_7tuple, port_src),
73 };
74
75
76 /* byteswap to cpu or network order */
77 static void
78 bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
79 {
80         int i;
81
82         for (i = 0; i < len; i++) {
83
84                 if (to_be) {
85                         /* swap all bytes so that they are in network order */
86                         data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
87                         data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
88                         data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
89                         data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
90                         data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
91                         data[i].domain = rte_cpu_to_be_16(data[i].domain);
92                 } else {
93                         data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
94                         data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
95                         data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
96                         data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
97                         data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
98                         data[i].domain = rte_be_to_cpu_16(data[i].domain);
99                 }
100         }
101 }
102
103 /*
104  * Test scalar and SSE ACL lookup.
105  */
106 static int
107 test_classify_run(struct rte_acl_ctx *acx)
108 {
109         int ret, i;
110         uint32_t result, count;
111         uint32_t results[RTE_DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES];
112         const uint8_t *data[RTE_DIM(acl_test_data)];
113
114         /* swap all bytes in the data to network order */
115         bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1);
116
117         /* store pointers to test data */
118         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++)
119                 data[i] = (uint8_t *)&acl_test_data[i];
120
121         /**
122          * these will run quite a few times, it's necessary to test code paths
123          * from num=0 to num>8
124          */
125         for (count = 0; count <= RTE_DIM(acl_test_data); count++) {
126                 ret = rte_acl_classify(acx, data, results,
127                                 count, RTE_ACL_MAX_CATEGORIES);
128                 if (ret != 0) {
129                         printf("Line %i: SSE classify failed!\n", __LINE__);
130                         goto err;
131                 }
132
133                 /* check if we allow everything we should allow */
134                 for (i = 0; i < (int) count; i++) {
135                         result =
136                                 results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
137                         if (result != acl_test_data[i].allow) {
138                                 printf("Line %i: Error in allow results at %i "
139                                         "(expected %"PRIu32" got %"PRIu32")!\n",
140                                         __LINE__, i, acl_test_data[i].allow,
141                                         result);
142                                 ret = -EINVAL;
143                                 goto err;
144                         }
145                 }
146
147                 /* check if we deny everything we should deny */
148                 for (i = 0; i < (int) count; i++) {
149                         result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
150                         if (result != acl_test_data[i].deny) {
151                                 printf("Line %i: Error in deny results at %i "
152                                         "(expected %"PRIu32" got %"PRIu32")!\n",
153                                         __LINE__, i, acl_test_data[i].deny,
154                                         result);
155                                 ret = -EINVAL;
156                                 goto err;
157                         }
158                 }
159         }
160
161         /* make a quick check for scalar */
162         ret = rte_acl_classify_alg(acx, data, results,
163                         RTE_DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES,
164                         RTE_ACL_CLASSIFY_SCALAR);
165         if (ret != 0) {
166                 printf("Line %i: scalar classify failed!\n", __LINE__);
167                 goto err;
168         }
169
170         /* check if we allow everything we should allow */
171         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
172                 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
173                 if (result != acl_test_data[i].allow) {
174                         printf("Line %i: Error in allow results at %i "
175                                         "(expected %"PRIu32" got %"PRIu32")!\n",
176                                         __LINE__, i, acl_test_data[i].allow,
177                                         result);
178                         ret = -EINVAL;
179                         goto err;
180                 }
181         }
182
183         /* check if we deny everything we should deny */
184         for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) {
185                 result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
186                 if (result != acl_test_data[i].deny) {
187                         printf("Line %i: Error in deny results at %i "
188                                         "(expected %"PRIu32" got %"PRIu32")!\n",
189                                         __LINE__, i, acl_test_data[i].deny,
190                                         result);
191                         ret = -EINVAL;
192                         goto err;
193                 }
194         }
195
196         ret = 0;
197
198 err:
199         /* swap data back to cpu order so that next time tests don't fail */
200         bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0);
201         return ret;
202 }
203
204 static int
205 test_classify_buid(struct rte_acl_ctx *acx,
206         const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
207 {
208         int ret;
209
210         /* add rules to the context */
211         ret = rte_acl_ipv4vlan_add_rules(acx, rules, num);
212         if (ret != 0) {
213                 printf("Line %i: Adding rules to ACL context failed!\n",
214                         __LINE__);
215                 return ret;
216         }
217
218         /* try building the context */
219         ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout,
220                 RTE_ACL_MAX_CATEGORIES);
221         if (ret != 0) {
222                 printf("Line %i: Building ACL context failed!\n", __LINE__);
223                 return ret;
224         }
225
226         return 0;
227 }
228
229 #define TEST_CLASSIFY_ITER      4
230
231 /*
232  * Test scalar and SSE ACL lookup.
233  */
234 static int
235 test_classify(void)
236 {
237         struct rte_acl_ctx *acx;
238         int i, ret;
239
240         acx = rte_acl_create(&acl_param);
241         if (acx == NULL) {
242                 printf("Line %i: Error creating ACL context!\n", __LINE__);
243                 return -1;
244         }
245
246         ret = 0;
247         for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
248
249                 if ((i & 1) == 0)
250                         rte_acl_reset(acx);
251                 else
252                         rte_acl_reset_rules(acx);
253
254                 ret = test_classify_buid(acx, acl_test_rules,
255                         RTE_DIM(acl_test_rules));
256                 if (ret != 0) {
257                         printf("Line %i, iter: %d: "
258                                 "Adding rules to ACL context failed!\n",
259                                 __LINE__, i);
260                         break;
261                 }
262
263                 ret = test_classify_run(acx);
264                 if (ret != 0) {
265                         printf("Line %i, iter: %d: %s failed!\n",
266                                 __LINE__, i, __func__);
267                         break;
268                 }
269
270                 /* reset rules and make sure that classify still works ok. */
271                 rte_acl_reset_rules(acx);
272                 ret = test_classify_run(acx);
273                 if (ret != 0) {
274                         printf("Line %i, iter: %d: %s failed!\n",
275                                 __LINE__, i, __func__);
276                         break;
277                 }
278         }
279
280         rte_acl_free(acx);
281         return ret;
282 }
283
284 static int
285 test_build_ports_range(void)
286 {
287         static const struct rte_acl_ipv4vlan_rule test_rules[] = {
288                 {
289                         /* match all packets. */
290                         .data = {
291                                 .userdata = 1,
292                                 .category_mask = ACL_ALLOW_MASK,
293                                 .priority = 101,
294                         },
295                         .src_port_low = 0,
296                         .src_port_high = UINT16_MAX,
297                         .dst_port_low = 0,
298                         .dst_port_high = UINT16_MAX,
299                 },
300                 {
301                         /* match all packets with dst ports [54-65280]. */
302                         .data = {
303                                 .userdata = 2,
304                                 .category_mask = ACL_ALLOW_MASK,
305                                 .priority = 102,
306                         },
307                         .src_port_low = 0,
308                         .src_port_high = UINT16_MAX,
309                         .dst_port_low = 54,
310                         .dst_port_high = 65280,
311                 },
312                 {
313                         /* match all packets with dst ports [0-52]. */
314                         .data = {
315                                 .userdata = 3,
316                                 .category_mask = ACL_ALLOW_MASK,
317                                 .priority = 103,
318                         },
319                         .src_port_low = 0,
320                         .src_port_high = UINT16_MAX,
321                         .dst_port_low = 0,
322                         .dst_port_high = 52,
323                 },
324                 {
325                         /* match all packets with dst ports [53]. */
326                         .data = {
327                                 .userdata = 4,
328                                 .category_mask = ACL_ALLOW_MASK,
329                                 .priority = 99,
330                         },
331                         .src_port_low = 0,
332                         .src_port_high = UINT16_MAX,
333                         .dst_port_low = 53,
334                         .dst_port_high = 53,
335                 },
336                 {
337                         /* match all packets with dst ports [65279-65535]. */
338                         .data = {
339                                 .userdata = 5,
340                                 .category_mask = ACL_ALLOW_MASK,
341                                 .priority = 98,
342                         },
343                         .src_port_low = 0,
344                         .src_port_high = UINT16_MAX,
345                         .dst_port_low = 65279,
346                         .dst_port_high = UINT16_MAX,
347                 },
348         };
349
350         static struct ipv4_7tuple test_data[] = {
351                 {
352                         .proto = 6,
353                         .ip_src = IPv4(10, 1, 1, 1),
354                         .ip_dst = IPv4(192, 168, 0, 33),
355                         .port_dst = 53,
356                         .allow = 1,
357                 },
358                 {
359                         .proto = 6,
360                         .ip_src = IPv4(127, 84, 33, 1),
361                         .ip_dst = IPv4(1, 2, 3, 4),
362                         .port_dst = 65281,
363                         .allow = 1,
364                 },
365         };
366
367         struct rte_acl_ctx *acx;
368         int32_t ret, i, j;
369         uint32_t results[RTE_DIM(test_data)];
370         const uint8_t *data[RTE_DIM(test_data)];
371
372         acx = rte_acl_create(&acl_param);
373         if (acx == NULL) {
374                 printf("Line %i: Error creating ACL context!\n", __LINE__);
375                 return -1;
376         }
377
378         /* swap all bytes in the data to network order */
379         bswap_test_data(test_data, RTE_DIM(test_data), 1);
380
381         /* store pointers to test data */
382         for (i = 0; i != RTE_DIM(test_data); i++)
383                 data[i] = (uint8_t *)&test_data[i];
384
385         for (i = 0; i != RTE_DIM(test_rules); i++) {
386                 rte_acl_reset(acx);
387                 ret = test_classify_buid(acx, test_rules, i + 1);
388                 if (ret != 0) {
389                         printf("Line %i, iter: %d: "
390                                 "Adding rules to ACL context failed!\n",
391                                 __LINE__, i);
392                         break;
393                 }
394                 ret = rte_acl_classify(acx, data, results,
395                         RTE_DIM(data), 1);
396                 if (ret != 0) {
397                         printf("Line %i, iter: %d: classify failed!\n",
398                                 __LINE__, i);
399                         break;
400                 }
401
402                 /* check results */
403                 for (j = 0; j != RTE_DIM(results); j++) {
404                         if (results[j] != test_data[j].allow) {
405                                 printf("Line %i: Error in allow results at %i "
406                                         "(expected %"PRIu32" got %"PRIu32")!\n",
407                                         __LINE__, j, test_data[j].allow,
408                                         results[j]);
409                                 ret = -EINVAL;
410                         }
411                 }
412         }
413
414         bswap_test_data(test_data, RTE_DIM(test_data), 0);
415
416         rte_acl_free(acx);
417         return ret;
418 }
419
420 static void
421 convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
422         struct acl_ipv4vlan_rule *ro)
423 {
424         ro->data = ri->data;
425
426         ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
427         ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
428         ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
429         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
430         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
431         ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
432         ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
433
434         ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
435         ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
436         ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
437                 ri->domain_mask;
438         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
439                 ri->src_mask_len;
440         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
441         ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
442                 ri->src_port_high;
443         ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
444                 ri->dst_port_high;
445 }
446
447 /*
448  * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
449  * RTE_ACL_FIELD_TYPE_BITMASK.
450  */
451 static void
452 convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
453         struct acl_ipv4vlan_rule *ro)
454 {
455         uint32_t v;
456
457         convert_rule(ri, ro);
458         v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
459         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
460                 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
461         v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
462         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 =
463                 RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
464 }
465
466 /*
467  * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
468  * RTE_ACL_FIELD_TYPE_RANGE.
469  */
470 static void
471 convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
472         struct acl_ipv4vlan_rule *ro)
473 {
474         uint32_t hi, lo, mask;
475
476         convert_rule(ri, ro);
477
478         mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
479         mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
480         lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask;
481         hi = lo + ~mask;
482         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
483         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
484
485         mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
486         mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
487         lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask;
488         hi = lo + ~mask;
489         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
490         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
491 }
492
493 /*
494  * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
495  */
496 static void
497 convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
498         struct acl_ipv4vlan_rule *ro)
499 {
500         struct rte_acl_field t1, t2;
501
502         convert_rule(ri, ro);
503
504         t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
505         t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
506
507         ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
508                 ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD];
509         ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
510                 ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD];
511
512         ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
513         ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
514 }
515
516 /*
517  * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
518  */
519 static void
520 convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
521         struct acl_ipv4vlan_rule *ro)
522 {
523         struct rte_acl_field t;
524
525         convert_rule(ri, ro);
526
527         t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD];
528         ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] =
529                 ro->field[RTE_ACL_IPV4VLAN_DST_FIELD];
530
531         ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
532 }
533
534 static void
535 ipv4vlan_config(struct rte_acl_config *cfg,
536         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
537         uint32_t num_categories)
538 {
539         static const struct rte_acl_field_def
540                 ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
541                 {
542                         .type = RTE_ACL_FIELD_TYPE_BITMASK,
543                         .size = sizeof(uint8_t),
544                         .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
545                         .input_index = RTE_ACL_IPV4VLAN_PROTO,
546                 },
547                 {
548                         .type = RTE_ACL_FIELD_TYPE_BITMASK,
549                         .size = sizeof(uint16_t),
550                         .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
551                         .input_index = RTE_ACL_IPV4VLAN_VLAN,
552                 },
553                 {
554                         .type = RTE_ACL_FIELD_TYPE_BITMASK,
555                         .size = sizeof(uint16_t),
556                         .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
557                         .input_index = RTE_ACL_IPV4VLAN_VLAN,
558                 },
559                 {
560                         .type = RTE_ACL_FIELD_TYPE_MASK,
561                         .size = sizeof(uint32_t),
562                         .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
563                         .input_index = RTE_ACL_IPV4VLAN_SRC,
564                 },
565                 {
566                         .type = RTE_ACL_FIELD_TYPE_MASK,
567                         .size = sizeof(uint32_t),
568                         .field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
569                         .input_index = RTE_ACL_IPV4VLAN_DST,
570                 },
571                 {
572                         .type = RTE_ACL_FIELD_TYPE_RANGE,
573                         .size = sizeof(uint16_t),
574                         .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
575                         .input_index = RTE_ACL_IPV4VLAN_PORTS,
576                 },
577                 {
578                         .type = RTE_ACL_FIELD_TYPE_RANGE,
579                         .size = sizeof(uint16_t),
580                         .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
581                         .input_index = RTE_ACL_IPV4VLAN_PORTS,
582                 },
583         };
584
585         memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
586         cfg->num_fields = RTE_DIM(ipv4_defs);
587
588         cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
589                 layout[RTE_ACL_IPV4VLAN_PROTO];
590         cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
591                 layout[RTE_ACL_IPV4VLAN_VLAN];
592         cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
593                 layout[RTE_ACL_IPV4VLAN_VLAN] +
594                 cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
595         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
596                 layout[RTE_ACL_IPV4VLAN_SRC];
597         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
598                 layout[RTE_ACL_IPV4VLAN_DST];
599         cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
600                 layout[RTE_ACL_IPV4VLAN_PORTS];
601         cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
602                 layout[RTE_ACL_IPV4VLAN_PORTS] +
603                 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
604
605         cfg->num_categories = num_categories;
606 }
607
608 static int
609 convert_rules(struct rte_acl_ctx *acx,
610         void (*convert)(const struct rte_acl_ipv4vlan_rule *,
611         struct acl_ipv4vlan_rule *),
612         const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
613 {
614         int32_t rc;
615         uint32_t i;
616         struct acl_ipv4vlan_rule r;
617
618         for (i = 0; i != num; i++) {
619                 convert(rules + i, &r);
620                 rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
621                 if (rc != 0) {
622                         printf("Line %i: Adding rule %u to ACL context "
623                                 "failed with error code: %d\n",
624                         __LINE__, i, rc);
625                         return rc;
626                 }
627         }
628
629         return 0;
630 }
631
632 static void
633 convert_config(struct rte_acl_config *cfg)
634 {
635         ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
636 }
637
638 /*
639  * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
640  */
641 static void
642 convert_config_1(struct rte_acl_config *cfg)
643 {
644         ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
645         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
646         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
647 }
648
649 /*
650  * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
651  */
652 static void
653 convert_config_2(struct rte_acl_config *cfg)
654 {
655         ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
656         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
657         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
658 }
659
660 /*
661  * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
662  */
663 static void
664 convert_config_3(struct rte_acl_config *cfg)
665 {
666         struct rte_acl_field_def t1, t2;
667
668         ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
669
670         t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
671         t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
672
673         /* swap VLAN1 and SRCP rule definition. */
674         cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
675                 cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD];
676         cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index;
677         cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index;
678
679         /* swap VLAN2 and DSTP rule definition. */
680         cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
681                 cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD];
682         cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index;
683         cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index;
684
685         cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type;
686         cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size;
687         cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset;
688
689         cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type;
690         cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size;
691         cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset;
692 }
693
694 /*
695  * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
696  */
697 static void
698 convert_config_4(struct rte_acl_config *cfg)
699 {
700         struct rte_acl_field_def t;
701
702         ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
703
704         t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
705
706         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] =
707                 cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD];
708         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index;
709         cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index;
710
711         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type;
712         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size;
713         cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset;
714 }
715
716
717 static int
718 build_convert_rules(struct rte_acl_ctx *acx,
719         void (*config)(struct rte_acl_config *),
720         size_t max_size)
721 {
722         struct rte_acl_config cfg;
723
724         memset(&cfg, 0, sizeof(cfg));
725         config(&cfg);
726         cfg.max_size = max_size;
727         return rte_acl_build(acx, &cfg);
728 }
729
730 static int
731 test_convert_rules(const char *desc,
732         void (*config)(struct rte_acl_config *),
733         void (*convert)(const struct rte_acl_ipv4vlan_rule *,
734         struct acl_ipv4vlan_rule *))
735 {
736         struct rte_acl_ctx *acx;
737         int32_t rc;
738         uint32_t i;
739         static const size_t mem_sizes[] = {0, -1};
740
741         printf("running %s(%s)\n", __func__, desc);
742
743         acx = rte_acl_create(&acl_param);
744         if (acx == NULL) {
745                 printf("Line %i: Error creating ACL context!\n", __LINE__);
746                 return -1;
747         }
748
749         rc = convert_rules(acx, convert, acl_test_rules,
750                 RTE_DIM(acl_test_rules));
751         if (rc != 0)
752                 printf("Line %i: Error converting ACL rules!\n", __LINE__);
753
754         for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
755
756                 rc = build_convert_rules(acx, config, mem_sizes[i]);
757                 if (rc != 0) {
758                         printf("Line %i: Error @ build_convert_rules(%zu)!\n",
759                                 __LINE__, mem_sizes[i]);
760                         break;
761                 }
762
763                 rc = test_classify_run(acx);
764                 if (rc != 0)
765                         printf("%s failed at line %i, max_size=%zu\n",
766                                 __func__, __LINE__, mem_sizes[i]);
767         }
768
769         rte_acl_free(acx);
770         return rc;
771 }
772
773 static int
774 test_convert(void)
775 {
776         static const struct {
777                 const char *desc;
778                 void (*config)(struct rte_acl_config *);
779                 void (*convert)(const struct rte_acl_ipv4vlan_rule *,
780                         struct acl_ipv4vlan_rule *);
781         } convert_param[] = {
782                 {
783                         "acl_ipv4vlan_tuple",
784                         convert_config,
785                         convert_rule,
786                 },
787                 {
788                         "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
789                         "for IPv4",
790                         convert_config_1,
791                         convert_rule_1,
792                 },
793                 {
794                         "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
795                         "for IPv4",
796                         convert_config_2,
797                         convert_rule_2,
798                 },
799                 {
800                         "acl_ipv4vlan_tuple: swap VLAN and PORTs order",
801                         convert_config_3,
802                         convert_rule_3,
803                 },
804                 {
805                         "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
806                         convert_config_4,
807                         convert_rule_4,
808                 },
809         };
810
811         uint32_t i;
812         int32_t rc;
813
814         for (i = 0; i != RTE_DIM(convert_param); i++) {
815                 rc = test_convert_rules(convert_param[i].desc,
816                         convert_param[i].config,
817                         convert_param[i].convert);
818                 if (rc != 0) {
819                         printf("%s for test-case: %s failed, error code: %d;\n",
820                                 __func__, convert_param[i].desc, rc);
821                         return rc;
822                 }
823         }
824
825         return 0;
826 }
827
828 /*
829  * Test wrong layout behavior
830  * This test supplies the ACL context with invalid layout, which results in
831  * ACL matching the wrong stuff. However, it should match the wrong stuff
832  * the right way. We switch around source and destination addresses,
833  * source and destination ports, and protocol will point to first byte of
834  * destination port.
835  */
836 static int
837 test_invalid_layout(void)
838 {
839         struct rte_acl_ctx *acx;
840         int ret, i;
841
842         uint32_t results[RTE_DIM(invalid_layout_data)];
843         const uint8_t *data[RTE_DIM(invalid_layout_data)];
844
845         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
846                         /* proto points to destination port's first byte */
847                         offsetof(struct ipv4_7tuple, port_dst),
848
849                         0, /* VLAN not used */
850
851                         /* src and dst addresses are swapped */
852                         offsetof(struct ipv4_7tuple, ip_dst),
853                         offsetof(struct ipv4_7tuple, ip_src),
854
855                         /*
856                          * we can't swap ports here, so we will swap
857                          * them in the data
858                          */
859                         offsetof(struct ipv4_7tuple, port_src),
860         };
861
862         acx = rte_acl_create(&acl_param);
863         if (acx == NULL) {
864                 printf("Line %i: Error creating ACL context!\n", __LINE__);
865                 return -1;
866         }
867
868         /* putting a lot of rules into the context results in greater
869          * coverage numbers. it doesn't matter if they are identical */
870         for (i = 0; i < 1000; i++) {
871                 /* add rules to the context */
872                 ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
873                                 RTE_DIM(invalid_layout_rules));
874                 if (ret != 0) {
875                         printf("Line %i: Adding rules to ACL context failed!\n",
876                                 __LINE__);
877                         rte_acl_free(acx);
878                         return -1;
879                 }
880         }
881
882         /* try building the context */
883         ret = rte_acl_ipv4vlan_build(acx, layout, 1);
884         if (ret != 0) {
885                 printf("Line %i: Building ACL context failed!\n", __LINE__);
886                 rte_acl_free(acx);
887                 return -1;
888         }
889
890         /* swap all bytes in the data to network order */
891         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
892
893         /* prepare data */
894         for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
895                 data[i] = (uint8_t *)&invalid_layout_data[i];
896         }
897
898         /* classify tuples */
899         ret = rte_acl_classify_alg(acx, data, results,
900                         RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
901         if (ret != 0) {
902                 printf("Line %i: SSE classify failed!\n", __LINE__);
903                 rte_acl_free(acx);
904                 return -1;
905         }
906
907         for (i = 0; i < (int) RTE_DIM(results); i++) {
908                 if (results[i] != invalid_layout_data[i].allow) {
909                         printf("Line %i: Wrong results at %i "
910                                 "(result=%u, should be %u)!\n",
911                                 __LINE__, i, results[i],
912                                 invalid_layout_data[i].allow);
913                         goto err;
914                 }
915         }
916
917         /* classify tuples (scalar) */
918         ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
919                 RTE_ACL_CLASSIFY_SCALAR);
920
921         if (ret != 0) {
922                 printf("Line %i: Scalar classify failed!\n", __LINE__);
923                 rte_acl_free(acx);
924                 return -1;
925         }
926
927         for (i = 0; i < (int) RTE_DIM(results); i++) {
928                 if (results[i] != invalid_layout_data[i].allow) {
929                         printf("Line %i: Wrong results at %i "
930                                 "(result=%u, should be %u)!\n",
931                                 __LINE__, i, results[i],
932                                 invalid_layout_data[i].allow);
933                         goto err;
934                 }
935         }
936
937         rte_acl_free(acx);
938
939         /* swap data back to cpu order so that next time tests don't fail */
940         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
941
942         return 0;
943 err:
944
945         /* swap data back to cpu order so that next time tests don't fail */
946         bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
947
948         rte_acl_free(acx);
949
950         return -1;
951 }
952
953 /*
954  * Test creating and finding ACL contexts, and adding rules
955  */
956 static int
957 test_create_find_add(void)
958 {
959         struct rte_acl_param param;
960         struct rte_acl_ctx *acx, *acx2, *tmp;
961         struct rte_acl_ipv4vlan_rule rules[LEN];
962
963         const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
964
965         const char *acx_name = "acx";
966         const char *acx2_name = "acx2";
967         int i, ret;
968
969         /* create two contexts */
970         memcpy(&param, &acl_param, sizeof(param));
971         param.max_rule_num = 2;
972
973         param.name = acx_name;
974         acx = rte_acl_create(&param);
975         if (acx == NULL) {
976                 printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
977                 return -1;
978         }
979
980         param.name = acx2_name;
981         acx2 = rte_acl_create(&param);
982         if (acx2 == NULL || acx2 == acx) {
983                 printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
984                 rte_acl_free(acx);
985                 return -1;
986         }
987
988         /* try to create third one, with an existing name */
989         param.name = acx_name;
990         tmp = rte_acl_create(&param);
991         if (tmp != acx) {
992                 printf("Line %i: Creating context with existing name "
993                         "test failed!\n",
994                         __LINE__);
995                 if (tmp)
996                         rte_acl_free(tmp);
997                 goto err;
998         }
999
1000         param.name = acx2_name;
1001         tmp = rte_acl_create(&param);
1002         if (tmp != acx2) {
1003                 printf("Line %i: Creating context with existing "
1004                         "name test 2 failed!\n",
1005                         __LINE__);
1006                 if (tmp)
1007                         rte_acl_free(tmp);
1008                 goto err;
1009         }
1010
1011         /* try to find existing ACL contexts */
1012         tmp = rte_acl_find_existing(acx_name);
1013         if (tmp != acx) {
1014                 printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
1015                 if (tmp)
1016                         rte_acl_free(tmp);
1017                 goto err;
1018         }
1019
1020         tmp = rte_acl_find_existing(acx2_name);
1021         if (tmp != acx2) {
1022                 printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
1023                 if (tmp)
1024                         rte_acl_free(tmp);
1025                 goto err;
1026         }
1027
1028         /* try to find non-existing context */
1029         tmp = rte_acl_find_existing("invalid");
1030         if (tmp != NULL) {
1031                 printf("Line %i: Non-existent ACL context found!\n", __LINE__);
1032                 goto err;
1033         }
1034
1035         /* free context */
1036         rte_acl_free(acx);
1037
1038
1039         /* create valid (but severely limited) acx */
1040         memcpy(&param, &acl_param, sizeof(param));
1041         param.max_rule_num = LEN;
1042
1043         acx = rte_acl_create(&param);
1044         if (acx == NULL) {
1045                 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
1046                 goto err;
1047         }
1048
1049         /* create dummy acl */
1050         for (i = 0; i < LEN; i++) {
1051                 memcpy(&rules[i], &acl_rule,
1052                         sizeof(struct rte_acl_ipv4vlan_rule));
1053                 /* skip zero */
1054                 rules[i].data.userdata = i + 1;
1055                 /* one rule per category */
1056                 rules[i].data.category_mask = 1 << i;
1057         }
1058
1059         /* try filling up the context */
1060         ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
1061         if (ret != 0) {
1062                 printf("Line %i: Adding %i rules to ACL context failed!\n",
1063                                 __LINE__, LEN);
1064                 goto err;
1065         }
1066
1067         /* try adding to a (supposedly) full context */
1068         ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
1069         if (ret == 0) {
1070                 printf("Line %i: Adding rules to full ACL context should"
1071                                 "have failed!\n", __LINE__);
1072                 goto err;
1073         }
1074
1075         /* try building the context */
1076         ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
1077         if (ret != 0) {
1078                 printf("Line %i: Building ACL context failed!\n", __LINE__);
1079                 goto err;
1080         }
1081
1082         rte_acl_free(acx);
1083         rte_acl_free(acx2);
1084
1085         return 0;
1086 err:
1087         rte_acl_free(acx);
1088         rte_acl_free(acx2);
1089         return -1;
1090 }
1091
1092 /*
1093  * test various invalid rules
1094  */
1095 static int
1096 test_invalid_rules(void)
1097 {
1098         struct rte_acl_ctx *acx;
1099         int ret;
1100
1101         struct rte_acl_ipv4vlan_rule rule;
1102
1103         acx = rte_acl_create(&acl_param);
1104         if (acx == NULL) {
1105                 printf("Line %i: Error creating ACL context!\n", __LINE__);
1106                 return -1;
1107         }
1108
1109         /* test inverted high/low source and destination ports.
1110          * originally, there was a problem with memory consumption when using
1111          * such rules.
1112          */
1113         /* create dummy acl */
1114         memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
1115         rule.data.userdata = 1;
1116         rule.dst_port_low = 0xfff0;
1117         rule.dst_port_high = 0x0010;
1118
1119         /* add rules to context and try to build it */
1120         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1121         if (ret == 0) {
1122                 printf("Line %i: Adding rules to ACL context "
1123                                 "should have failed!\n", __LINE__);
1124                 goto err;
1125         }
1126
1127         rule.dst_port_low = 0x0;
1128         rule.dst_port_high = 0xffff;
1129         rule.src_port_low = 0xfff0;
1130         rule.src_port_high = 0x0010;
1131
1132         /* add rules to context and try to build it */
1133         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1134         if (ret == 0) {
1135                 printf("Line %i: Adding rules to ACL context "
1136                                 "should have failed!\n", __LINE__);
1137                 goto err;
1138         }
1139
1140         rule.dst_port_low = 0x0;
1141         rule.dst_port_high = 0xffff;
1142         rule.src_port_low = 0x0;
1143         rule.src_port_high = 0xffff;
1144
1145         rule.dst_mask_len = 33;
1146
1147         /* add rules to context and try to build it */
1148         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1149         if (ret == 0) {
1150                 printf("Line %i: Adding rules to ACL context "
1151                                 "should have failed!\n", __LINE__);
1152                 goto err;
1153         }
1154
1155         rule.dst_mask_len = 0;
1156         rule.src_mask_len = 33;
1157
1158         /* add rules to context and try to build it */
1159         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1160         if (ret == 0) {
1161                 printf("Line %i: Adding rules to ACL context "
1162                                 "should have failed!\n", __LINE__);
1163                 goto err;
1164         }
1165
1166         rule.dst_mask_len = 0;
1167         rule.src_mask_len = 0;
1168         rule.data.userdata = 0;
1169
1170         /* try adding this rule (it should fail because userdata is invalid) */
1171         ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1172         if (ret == 0) {
1173                 printf("Line %i: Adding a rule with invalid user data "
1174                                 "should have failed!\n", __LINE__);
1175                 rte_acl_free(acx);
1176                 return -1;
1177         }
1178
1179         rte_acl_free(acx);
1180
1181         return 0;
1182
1183 err:
1184         rte_acl_free(acx);
1185
1186         return -1;
1187 }
1188
1189 /*
1190  * test functions by passing invalid or
1191  * non-workable parameters.
1192  *
1193  * we do very limited testing of classify functions here
1194  * because those are performance-critical and
1195  * thus don't do much parameter checking.
1196  */
1197 static int
1198 test_invalid_parameters(void)
1199 {
1200         struct rte_acl_param param;
1201         struct rte_acl_ctx *acx;
1202         struct rte_acl_ipv4vlan_rule rule;
1203         int result;
1204
1205         uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1206
1207
1208         /**
1209          * rte_ac_create()
1210          */
1211
1212         /* NULL param */
1213         acx = rte_acl_create(NULL);
1214         if (acx != NULL) {
1215                 printf("Line %i: ACL context creation with NULL param "
1216                                 "should have failed!\n", __LINE__);
1217                 rte_acl_free(acx);
1218                 return -1;
1219         }
1220
1221         /* zero rule size */
1222         memcpy(&param, &acl_param, sizeof(param));
1223         param.rule_size = 0;
1224
1225         acx = rte_acl_create(&param);
1226         if (acx == NULL) {
1227                 printf("Line %i: ACL context creation with zero rule len "
1228                                 "failed!\n", __LINE__);
1229                 return -1;
1230         } else
1231                 rte_acl_free(acx);
1232
1233         /* zero max rule num */
1234         memcpy(&param, &acl_param, sizeof(param));
1235         param.max_rule_num = 0;
1236
1237         acx = rte_acl_create(&param);
1238         if (acx == NULL) {
1239                 printf("Line %i: ACL context creation with zero rule num "
1240                                 "failed!\n", __LINE__);
1241                 return -1;
1242         } else
1243                 rte_acl_free(acx);
1244
1245         /* invalid NUMA node */
1246         memcpy(&param, &acl_param, sizeof(param));
1247         param.socket_id = RTE_MAX_NUMA_NODES + 1;
1248
1249         acx = rte_acl_create(&param);
1250         if (acx != NULL) {
1251                 printf("Line %i: ACL context creation with invalid NUMA "
1252                                 "should have failed!\n", __LINE__);
1253                 rte_acl_free(acx);
1254                 return -1;
1255         }
1256
1257         /* NULL name */
1258         memcpy(&param, &acl_param, sizeof(param));
1259         param.name = NULL;
1260
1261         acx = rte_acl_create(&param);
1262         if (acx != NULL) {
1263                 printf("Line %i: ACL context creation with NULL name "
1264                                 "should have failed!\n", __LINE__);
1265                 rte_acl_free(acx);
1266                 return -1;
1267         }
1268
1269         /**
1270          * rte_acl_find_existing
1271          */
1272
1273         acx = rte_acl_find_existing(NULL);
1274         if (acx != NULL) {
1275                 printf("Line %i: NULL ACL context found!\n", __LINE__);
1276                 rte_acl_free(acx);
1277                 return -1;
1278         }
1279
1280         /**
1281          * rte_acl_ipv4vlan_add_rules
1282          */
1283
1284         /* initialize everything */
1285         memcpy(&param, &acl_param, sizeof(param));
1286         acx = rte_acl_create(&param);
1287         if (acx == NULL) {
1288                 printf("Line %i: ACL context creation failed!\n", __LINE__);
1289                 return -1;
1290         }
1291
1292         memcpy(&rule, &acl_rule, sizeof(rule));
1293
1294         /* NULL context */
1295         result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
1296         if (result == 0) {
1297                 printf("Line %i: Adding rules with NULL ACL context "
1298                                 "should have failed!\n", __LINE__);
1299                 rte_acl_free(acx);
1300                 return -1;
1301         }
1302
1303         /* NULL rule */
1304         result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
1305         if (result == 0) {
1306                 printf("Line %i: Adding NULL rule to ACL context "
1307                                 "should have failed!\n", __LINE__);
1308                 rte_acl_free(acx);
1309                 return -1;
1310         }
1311
1312         /* zero count (should succeed) */
1313         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
1314         if (result != 0) {
1315                 printf("Line %i: Adding 0 rules to ACL context failed!\n",
1316                         __LINE__);
1317                 rte_acl_free(acx);
1318                 return -1;
1319         }
1320
1321         /* free ACL context */
1322         rte_acl_free(acx);
1323
1324         /* set wrong rule_size so that adding any rules would fail */
1325         param.rule_size = RTE_ACL_IPV4VLAN_RULE_SZ + 4;
1326         acx = rte_acl_create(&param);
1327         if (acx == NULL) {
1328                 printf("Line %i: ACL context creation failed!\n", __LINE__);
1329                 return -1;
1330         }
1331
1332         /* try adding a rule with size different from context rule_size */
1333         result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1334         if (result == 0) {
1335                 printf("Line %i: Adding an invalid sized rule "
1336                                 "should have failed!\n", __LINE__);
1337                 rte_acl_free(acx);
1338                 return -1;
1339         }
1340
1341         /* free ACL context */
1342         rte_acl_free(acx);
1343
1344
1345         /**
1346          * rte_acl_ipv4vlan_build
1347          */
1348
1349         /* reinitialize context */
1350         memcpy(&param, &acl_param, sizeof(param));
1351         acx = rte_acl_create(&param);
1352         if (acx == NULL) {
1353                 printf("Line %i: ACL context creation failed!\n", __LINE__);
1354                 return -1;
1355         }
1356
1357         /* NULL context */
1358         result = rte_acl_ipv4vlan_build(NULL, layout, 1);
1359         if (result == 0) {
1360                 printf("Line %i: Building with NULL context "
1361                                 "should have failed!\n", __LINE__);
1362                 rte_acl_free(acx);
1363                 return -1;
1364         }
1365
1366         /* NULL layout */
1367         result = rte_acl_ipv4vlan_build(acx, NULL, 1);
1368         if (result == 0) {
1369                 printf("Line %i: Building with NULL layout "
1370                                 "should have failed!\n", __LINE__);
1371                 rte_acl_free(acx);
1372                 return -1;
1373         }
1374
1375         /* zero categories (should not fail) */
1376         result = rte_acl_ipv4vlan_build(acx, layout, 0);
1377         if (result == 0) {
1378                 printf("Line %i: Building with 0 categories should fail!\n",
1379                         __LINE__);
1380                 rte_acl_free(acx);
1381                 return -1;
1382         }
1383
1384         /* SSE classify test */
1385
1386         /* cover zero categories in classify (should not fail) */
1387         result = rte_acl_classify(acx, NULL, NULL, 0, 0);
1388         if (result != 0) {
1389                 printf("Line %i: SSE classify with zero categories "
1390                                 "failed!\n", __LINE__);
1391                 rte_acl_free(acx);
1392                 return -1;
1393         }
1394
1395         /* cover invalid but positive categories in classify */
1396         result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1397         if (result == 0) {
1398                 printf("Line %i: SSE classify with 3 categories "
1399                                 "should have failed!\n", __LINE__);
1400                 rte_acl_free(acx);
1401                 return -1;
1402         }
1403
1404         /* scalar classify test */
1405
1406         /* cover zero categories in classify (should not fail) */
1407         result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0,
1408                 RTE_ACL_CLASSIFY_SCALAR);
1409         if (result != 0) {
1410                 printf("Line %i: Scalar classify with zero categories "
1411                                 "failed!\n", __LINE__);
1412                 rte_acl_free(acx);
1413                 return -1;
1414         }
1415
1416         /* cover invalid but positive categories in classify */
1417         result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1418         if (result == 0) {
1419                 printf("Line %i: Scalar classify with 3 categories "
1420                                 "should have failed!\n", __LINE__);
1421                 rte_acl_free(acx);
1422                 return -1;
1423         }
1424
1425         /* free ACL context */
1426         rte_acl_free(acx);
1427
1428
1429         /**
1430          * make sure void functions don't crash with NULL parameters
1431          */
1432
1433         rte_acl_free(NULL);
1434
1435         rte_acl_dump(NULL);
1436
1437         return 0;
1438 }
1439
1440 /**
1441  * Various tests that don't test much but improve coverage
1442  */
1443 static int
1444 test_misc(void)
1445 {
1446         struct rte_acl_param param;
1447         struct rte_acl_ctx *acx;
1448
1449         /* create context */
1450         memcpy(&param, &acl_param, sizeof(param));
1451
1452         acx = rte_acl_create(&param);
1453         if (acx == NULL) {
1454                 printf("Line %i: Error creating ACL context!\n", __LINE__);
1455                 return -1;
1456         }
1457
1458         /* dump context with rules - useful for coverage */
1459         rte_acl_list_dump();
1460
1461         rte_acl_dump(acx);
1462
1463         rte_acl_free(acx);
1464
1465         return 0;
1466 }
1467
1468 static int
1469 test_acl(void)
1470 {
1471         if (test_invalid_parameters() < 0)
1472                 return -1;
1473         if (test_invalid_rules() < 0)
1474                 return -1;
1475         if (test_create_find_add() < 0)
1476                 return -1;
1477         if (test_invalid_layout() < 0)
1478                 return -1;
1479         if (test_misc() < 0)
1480                 return -1;
1481         if (test_classify() < 0)
1482                 return -1;
1483         if (test_build_ports_range() < 0)
1484                 return -1;
1485         if (test_convert() < 0)
1486                 return -1;
1487
1488         return 0;
1489 }
1490
1491 static struct test_command acl_cmd = {
1492         .command = "acl_autotest",
1493         .callback = test_acl,
1494 };
1495 REGISTER_TEST_COMMAND(acl_cmd);