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