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