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 : rules[i] = acl_rule;
1227 : : /* skip zero */
1228 : 16 : rules[i].data.userdata = i + 1;
1229 : : /* one rule per category */
1230 : 16 : rules[i].data.category_mask = 1 << i;
1231 : : }
1232 : :
1233 : : /* try filling up the context */
1234 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
1235 [ - + ]: 1 : if (ret != 0) {
1236 : : printf("Line %i: Adding %i rules to ACL context failed!\n",
1237 : : __LINE__, LEN);
1238 : 0 : goto err;
1239 : : }
1240 : :
1241 : : /* try adding to a (supposedly) full context */
1242 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
1243 [ - + ]: 1 : if (ret == 0) {
1244 : : printf("Line %i: Adding rules to full ACL context should"
1245 : : "have failed!\n", __LINE__);
1246 : 0 : goto err;
1247 : : }
1248 : :
1249 : : /* try building the context */
1250 : 1 : ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
1251 [ - + ]: 1 : if (ret != 0) {
1252 : : printf("Line %i: Building ACL context failed!\n", __LINE__);
1253 : 0 : goto err;
1254 : : }
1255 : :
1256 : 1 : rte_acl_free(acx);
1257 : 1 : rte_acl_free(acx2);
1258 : :
1259 : 1 : return 0;
1260 : 0 : err:
1261 : 0 : rte_acl_free(acx);
1262 : 0 : rte_acl_free(acx2);
1263 : 0 : return -1;
1264 : : }
1265 : :
1266 : : /*
1267 : : * test various invalid rules
1268 : : */
1269 : : static int
1270 : 1 : test_invalid_rules(void)
1271 : : {
1272 : : struct rte_acl_ctx *acx;
1273 : : int ret;
1274 : :
1275 : : struct rte_acl_ipv4vlan_rule rule;
1276 : :
1277 : 1 : acx = rte_acl_create(&acl_param);
1278 [ - + ]: 1 : if (acx == NULL) {
1279 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
1280 : 0 : return -1;
1281 : : }
1282 : :
1283 : : /* test inverted high/low source and destination ports.
1284 : : * originally, there was a problem with memory consumption when using
1285 : : * such rules.
1286 : : */
1287 : : /* create dummy acl */
1288 : 1 : rule = acl_rule;
1289 : 1 : rule.data.userdata = 1;
1290 : 1 : rule.dst_port_low = 0xfff0;
1291 : 1 : rule.dst_port_high = 0x0010;
1292 : :
1293 : : /* add rules to context and try to build it */
1294 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1295 [ - + ]: 1 : if (ret == 0) {
1296 : : printf("Line %i: Adding rules to ACL context "
1297 : : "should have failed!\n", __LINE__);
1298 : 0 : goto err;
1299 : : }
1300 : :
1301 : 1 : rule.dst_port_low = 0x0;
1302 : 1 : rule.dst_port_high = 0xffff;
1303 : 1 : rule.src_port_low = 0xfff0;
1304 : 1 : rule.src_port_high = 0x0010;
1305 : :
1306 : : /* add rules to context and try to build it */
1307 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1308 [ - + ]: 1 : if (ret == 0) {
1309 : : printf("Line %i: Adding rules to ACL context "
1310 : : "should have failed!\n", __LINE__);
1311 : 0 : goto err;
1312 : : }
1313 : :
1314 : 1 : rule.dst_port_low = 0x0;
1315 : 1 : rule.dst_port_high = 0xffff;
1316 : 1 : rule.src_port_low = 0x0;
1317 : 1 : rule.src_port_high = 0xffff;
1318 : :
1319 : 1 : rule.dst_mask_len = 33;
1320 : :
1321 : : /* add rules to context and try to build it */
1322 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1323 [ - + ]: 1 : if (ret == 0) {
1324 : : printf("Line %i: Adding rules to ACL context "
1325 : : "should have failed!\n", __LINE__);
1326 : 0 : goto err;
1327 : : }
1328 : :
1329 : 1 : rule.dst_mask_len = 0;
1330 : 1 : rule.src_mask_len = 33;
1331 : :
1332 : : /* add rules to context and try to build it */
1333 : 1 : ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
1334 [ - + ]: 1 : if (ret == 0) {
1335 : : printf("Line %i: Adding rules to ACL context "
1336 : : "should have failed!\n", __LINE__);
1337 : 0 : goto err;
1338 : : }
1339 : :
1340 : 1 : rte_acl_free(acx);
1341 : :
1342 : 1 : return 0;
1343 : :
1344 : 0 : err:
1345 : 0 : rte_acl_free(acx);
1346 : :
1347 : 0 : return -1;
1348 : : }
1349 : :
1350 : : /*
1351 : : * test functions by passing invalid or
1352 : : * non-workable parameters.
1353 : : *
1354 : : * we do very limited testing of classify functions here
1355 : : * because those are performance-critical and
1356 : : * thus don't do much parameter checking.
1357 : : */
1358 : : static int
1359 : 1 : test_invalid_parameters(void)
1360 : : {
1361 : : struct rte_acl_param param;
1362 : : struct rte_acl_ctx *acx;
1363 : : struct rte_acl_ipv4vlan_rule rule;
1364 : : int result;
1365 : :
1366 : 1 : uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1367 : :
1368 : :
1369 : : /**
1370 : : * rte_ac_create()
1371 : : */
1372 : :
1373 : : /* NULL param */
1374 : 1 : acx = rte_acl_create(NULL);
1375 [ - + ]: 1 : if (acx != NULL) {
1376 : : printf("Line %i: ACL context creation with NULL param "
1377 : : "should have failed!\n", __LINE__);
1378 : 0 : rte_acl_free(acx);
1379 : 0 : return -1;
1380 : : }
1381 : :
1382 : : /* zero rule size */
1383 : : memcpy(¶m, &acl_param, sizeof(param));
1384 : 1 : param.rule_size = 0;
1385 : :
1386 : 1 : acx = rte_acl_create(¶m);
1387 [ - + ]: 1 : if (acx == NULL) {
1388 : : printf("Line %i: ACL context creation with zero rule len "
1389 : : "failed!\n", __LINE__);
1390 : 0 : return -1;
1391 : : } else
1392 : 1 : rte_acl_free(acx);
1393 : :
1394 : : /* zero max rule num */
1395 : : memcpy(¶m, &acl_param, sizeof(param));
1396 : 1 : param.max_rule_num = 0;
1397 : :
1398 : 1 : acx = rte_acl_create(¶m);
1399 [ - + ]: 1 : if (acx == NULL) {
1400 : : printf("Line %i: ACL context creation with zero rule num "
1401 : : "failed!\n", __LINE__);
1402 : 0 : return -1;
1403 : : } else
1404 : 1 : rte_acl_free(acx);
1405 : :
1406 [ - + ]: 1 : if (rte_eal_has_hugepages()) {
1407 : : /* invalid NUMA node */
1408 : : memcpy(¶m, &acl_param, sizeof(param));
1409 : 0 : param.socket_id = RTE_MAX_NUMA_NODES + 1;
1410 : :
1411 : 0 : acx = rte_acl_create(¶m);
1412 [ # # ]: 0 : if (acx != NULL) {
1413 : : printf("Line %i: ACL context creation with invalid "
1414 : : "NUMA should have failed!\n", __LINE__);
1415 : 0 : rte_acl_free(acx);
1416 : 0 : return -1;
1417 : : }
1418 : : }
1419 : :
1420 : : /* NULL name */
1421 : : memcpy(¶m, &acl_param, sizeof(param));
1422 : 1 : param.name = NULL;
1423 : :
1424 : 1 : acx = rte_acl_create(¶m);
1425 [ - + ]: 1 : if (acx != NULL) {
1426 : : printf("Line %i: ACL context creation with NULL name "
1427 : : "should have failed!\n", __LINE__);
1428 : 0 : rte_acl_free(acx);
1429 : 0 : return -1;
1430 : : }
1431 : :
1432 : : /**
1433 : : * rte_acl_find_existing
1434 : : */
1435 : :
1436 : 1 : acx = rte_acl_find_existing(NULL);
1437 [ - + ]: 1 : if (acx != NULL) {
1438 : : printf("Line %i: NULL ACL context found!\n", __LINE__);
1439 : 0 : rte_acl_free(acx);
1440 : 0 : return -1;
1441 : : }
1442 : :
1443 : : /**
1444 : : * rte_acl_ipv4vlan_add_rules
1445 : : */
1446 : :
1447 : : /* initialize everything */
1448 : : memcpy(¶m, &acl_param, sizeof(param));
1449 : 1 : acx = rte_acl_create(¶m);
1450 [ - + ]: 1 : if (acx == NULL) {
1451 : : printf("Line %i: ACL context creation failed!\n", __LINE__);
1452 : 0 : return -1;
1453 : : }
1454 : :
1455 : : memcpy(&rule, &acl_rule, sizeof(rule));
1456 : :
1457 : : /* NULL context */
1458 : 1 : result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
1459 [ - + ]: 1 : if (result == 0) {
1460 : : printf("Line %i: Adding rules with NULL ACL context "
1461 : : "should have failed!\n", __LINE__);
1462 : 0 : rte_acl_free(acx);
1463 : 0 : return -1;
1464 : : }
1465 : :
1466 : : /* NULL rule */
1467 : 1 : result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
1468 [ - + ]: 1 : if (result == 0) {
1469 : : printf("Line %i: Adding NULL rule to ACL context "
1470 : : "should have failed!\n", __LINE__);
1471 : 0 : rte_acl_free(acx);
1472 : 0 : return -1;
1473 : : }
1474 : :
1475 : : /* zero count (should succeed) */
1476 : 1 : result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
1477 [ - + ]: 1 : if (result != 0) {
1478 : : printf("Line %i: Adding 0 rules to ACL context failed!\n",
1479 : : __LINE__);
1480 : 0 : rte_acl_free(acx);
1481 : 0 : return -1;
1482 : : }
1483 : :
1484 : : /* free ACL context */
1485 : 1 : rte_acl_free(acx);
1486 : :
1487 : :
1488 : : /**
1489 : : * rte_acl_ipv4vlan_build
1490 : : */
1491 : :
1492 : : /* reinitialize context */
1493 : : memcpy(¶m, &acl_param, sizeof(param));
1494 : 1 : acx = rte_acl_create(¶m);
1495 [ - + ]: 1 : if (acx == NULL) {
1496 : : printf("Line %i: ACL context creation failed!\n", __LINE__);
1497 : 0 : return -1;
1498 : : }
1499 : :
1500 : : /* NULL context */
1501 : 1 : result = rte_acl_ipv4vlan_build(NULL, layout, 1);
1502 [ - + ]: 1 : if (result == 0) {
1503 : : printf("Line %i: Building with NULL context "
1504 : : "should have failed!\n", __LINE__);
1505 : 0 : rte_acl_free(acx);
1506 : 0 : return -1;
1507 : : }
1508 : :
1509 : : /* NULL layout */
1510 : 1 : result = rte_acl_ipv4vlan_build(acx, NULL, 1);
1511 [ - + ]: 1 : if (result == 0) {
1512 : : printf("Line %i: Building with NULL layout "
1513 : : "should have failed!\n", __LINE__);
1514 : 0 : rte_acl_free(acx);
1515 : 0 : return -1;
1516 : : }
1517 : :
1518 : : /* zero categories (should not fail) */
1519 : 1 : result = rte_acl_ipv4vlan_build(acx, layout, 0);
1520 [ - + ]: 1 : if (result == 0) {
1521 : : printf("Line %i: Building with 0 categories should fail!\n",
1522 : : __LINE__);
1523 : 0 : rte_acl_free(acx);
1524 : 0 : return -1;
1525 : : }
1526 : :
1527 : : /* SSE classify test */
1528 : :
1529 : : /* cover zero categories in classify (should not fail) */
1530 : 1 : result = rte_acl_classify(acx, NULL, NULL, 0, 0);
1531 [ - + ]: 1 : if (result != 0) {
1532 : : printf("Line %i: SSE classify with zero categories "
1533 : : "failed!\n", __LINE__);
1534 : 0 : rte_acl_free(acx);
1535 : 0 : return -1;
1536 : : }
1537 : :
1538 : : /* cover invalid but positive categories in classify */
1539 : 1 : result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1540 [ - + ]: 1 : if (result == 0) {
1541 : : printf("Line %i: SSE classify with 3 categories "
1542 : : "should have failed!\n", __LINE__);
1543 : 0 : rte_acl_free(acx);
1544 : 0 : return -1;
1545 : : }
1546 : :
1547 : : /* scalar classify test */
1548 : :
1549 : : /* cover zero categories in classify (should not fail) */
1550 : 1 : result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0,
1551 : : RTE_ACL_CLASSIFY_SCALAR);
1552 [ - + ]: 1 : if (result != 0) {
1553 : : printf("Line %i: Scalar classify with zero categories "
1554 : : "failed!\n", __LINE__);
1555 : 0 : rte_acl_free(acx);
1556 : 0 : return -1;
1557 : : }
1558 : :
1559 : : /* cover invalid but positive categories in classify */
1560 : 1 : result = rte_acl_classify(acx, NULL, NULL, 0, 3);
1561 [ - + ]: 1 : if (result == 0) {
1562 : : printf("Line %i: Scalar classify with 3 categories "
1563 : : "should have failed!\n", __LINE__);
1564 : 0 : rte_acl_free(acx);
1565 : 0 : return -1;
1566 : : }
1567 : :
1568 : : /* free ACL context */
1569 : 1 : rte_acl_free(acx);
1570 : :
1571 : :
1572 : : /**
1573 : : * make sure void functions don't crash with NULL parameters
1574 : : */
1575 : :
1576 : 1 : rte_acl_free(NULL);
1577 : :
1578 : 1 : rte_acl_dump(NULL);
1579 : :
1580 : 1 : return 0;
1581 : : }
1582 : :
1583 : : /**
1584 : : * Various tests that don't test much but improve coverage
1585 : : */
1586 : : static int
1587 : 1 : test_misc(void)
1588 : : {
1589 : : struct rte_acl_param param;
1590 : : struct rte_acl_ctx *acx;
1591 : :
1592 : : /* create context */
1593 : : memcpy(¶m, &acl_param, sizeof(param));
1594 : :
1595 : 1 : acx = rte_acl_create(¶m);
1596 [ - + ]: 1 : if (acx == NULL) {
1597 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
1598 : 0 : return -1;
1599 : : }
1600 : :
1601 : : /* dump context with rules - useful for coverage */
1602 : 1 : rte_acl_list_dump();
1603 : :
1604 : 1 : rte_acl_dump(acx);
1605 : :
1606 : 1 : rte_acl_free(acx);
1607 : :
1608 : 1 : return 0;
1609 : : }
1610 : :
1611 : : static uint32_t
1612 : : get_u32_range_max(void)
1613 : : {
1614 : : uint32_t i, max;
1615 : :
1616 : : max = 0;
1617 [ + + ]: 5 : for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1618 : 4 : max = RTE_MAX(max, acl_u32_range_test_rules[i].src_mask_len);
1619 : : return max;
1620 : : }
1621 : :
1622 : : static uint32_t
1623 : : get_u32_range_min(void)
1624 : : {
1625 : : uint32_t i, min;
1626 : :
1627 : : min = UINT32_MAX;
1628 [ + + ]: 5 : for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1629 : 4 : min = RTE_MIN(min, acl_u32_range_test_rules[i].src_addr);
1630 : : return min;
1631 : : }
1632 : :
1633 : : static const struct rte_acl_ipv4vlan_rule *
1634 : : find_u32_range_rule(uint32_t val)
1635 : : {
1636 : : uint32_t i;
1637 : :
1638 [ + + ]: 921692 : for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1639 [ + + ]: 921690 : if (val >= acl_u32_range_test_rules[i].src_addr &&
1640 [ + + ]: 591292 : val <= acl_u32_range_test_rules[i].src_mask_len)
1641 : 264191 : return acl_u32_range_test_rules + i;
1642 : : }
1643 : : return NULL;
1644 : : }
1645 : :
1646 : : static void
1647 : 4129 : fill_u32_range_data(struct ipv4_7tuple tdata[], uint32_t start, uint32_t num)
1648 : : {
1649 : : uint32_t i;
1650 : : const struct rte_acl_ipv4vlan_rule *r;
1651 : :
1652 [ + + ]: 268322 : for (i = 0; i != num; i++) {
1653 : 264193 : tdata[i].ip_src = start + i;
1654 : : r = find_u32_range_rule(start + i);
1655 [ + + ]: 264193 : if (r != NULL)
1656 : 264191 : tdata[i].allow = r->data.userdata;
1657 : : }
1658 : 4129 : }
1659 : :
1660 : : static int
1661 : 1 : test_u32_range(void)
1662 : : {
1663 : : int32_t rc;
1664 : : uint32_t i, k, max, min;
1665 : : struct rte_acl_ctx *acx;
1666 : : struct acl_ipv4vlan_rule r;
1667 : : struct ipv4_7tuple test_data[64];
1668 : :
1669 : 1 : acx = rte_acl_create(&acl_param);
1670 [ - + ]: 1 : if (acx == NULL) {
1671 : : printf("%s#%i: Error creating ACL context!\n",
1672 : : __func__, __LINE__);
1673 : 0 : return -1;
1674 : : }
1675 : :
1676 [ + + ]: 5 : for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1677 : : convert_rule(&acl_u32_range_test_rules[i], &r);
1678 : 4 : rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
1679 [ - + ]: 4 : if (rc != 0) {
1680 : : printf("%s#%i: Adding rule to ACL context "
1681 : : "failed with error code: %d\n",
1682 : : __func__, __LINE__, rc);
1683 : 0 : rte_acl_free(acx);
1684 : 0 : return rc;
1685 : : }
1686 : : }
1687 : :
1688 : 1 : rc = build_convert_rules(acx, convert_config_2, 0);
1689 [ - + ]: 1 : if (rc != 0) {
1690 : : printf("%s#%i Error @ build_convert_rules!\n",
1691 : : __func__, __LINE__);
1692 : 0 : rte_acl_free(acx);
1693 : 0 : return rc;
1694 : : }
1695 : :
1696 : : max = get_u32_range_max();
1697 : : min = get_u32_range_min();
1698 : :
1699 : 1 : max = RTE_MAX(max, max + 1);
1700 : 1 : min = RTE_MIN(min, min - 1);
1701 : :
1702 : : printf("%s#%d starting range test from %u to %u\n",
1703 : : __func__, __LINE__, min, max);
1704 : :
1705 [ + + ]: 4130 : for (i = min; i <= max; i += k) {
1706 : :
1707 : 4129 : k = RTE_MIN(max - i + 1, RTE_DIM(test_data));
1708 : :
1709 : : memset(test_data, 0, sizeof(test_data));
1710 : 4129 : fill_u32_range_data(test_data, i, k);
1711 : :
1712 : 4129 : rc = test_classify_run(acx, test_data, k);
1713 [ - + ]: 4129 : if (rc != 0) {
1714 : 0 : printf("%s#%d failed at [%u, %u) interval\n",
1715 : : __func__, __LINE__, i, i + k);
1716 : : break;
1717 : : }
1718 : : }
1719 : :
1720 : 1 : rte_acl_free(acx);
1721 : 1 : return rc;
1722 : : }
1723 : :
1724 : : static int
1725 : 1 : test_acl(void)
1726 : : {
1727 [ + - ]: 1 : if (test_invalid_parameters() < 0)
1728 : : return -1;
1729 [ + - ]: 1 : if (test_invalid_rules() < 0)
1730 : : return -1;
1731 [ + - ]: 1 : if (test_create_find_add() < 0)
1732 : : return -1;
1733 [ + - ]: 1 : if (test_invalid_layout() < 0)
1734 : : return -1;
1735 [ + - ]: 1 : if (test_misc() < 0)
1736 : : return -1;
1737 [ + - ]: 1 : if (test_classify() < 0)
1738 : : return -1;
1739 [ + - ]: 1 : if (test_build_ports_range() < 0)
1740 : : return -1;
1741 [ + - ]: 1 : if (test_convert() < 0)
1742 : : return -1;
1743 [ - + ]: 1 : if (test_u32_range() < 0)
1744 : 0 : return -1;
1745 : :
1746 : : return 0;
1747 : : }
1748 : :
1749 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1750 : :
1751 : 254 : REGISTER_FAST_TEST(acl_autotest, true, true, test_acl);
|