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