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 : 8314 : bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
62 : : {
63 : : int i;
64 : :
65 [ + + ]: 540144 : for (i = 0; i < len; i++) {
66 : :
67 [ + + ]: 531830 : if (to_be) {
68 : : /* swap all bytes so that they are in network order */
69 [ - + ]: 265915 : data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
70 [ - + ]: 265915 : data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
71 [ - + ]: 265915 : data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
72 [ - + ]: 265915 : data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
73 [ - + ]: 265915 : data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
74 [ - + ]: 531830 : data[i].domain = rte_cpu_to_be_16(data[i].domain);
75 : : } else {
76 [ - + ]: 265915 : data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
77 [ - + ]: 265915 : data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
78 [ - + ]: 265915 : data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
79 [ - + ]: 265915 : data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
80 [ - + ]: 265915 : data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
81 [ - + ]: 531830 : data[i].domain = rte_be_to_cpu_16(data[i].domain);
82 : : }
83 : : }
84 : 8314 : }
85 : :
86 : : static int
87 : : acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule)
88 : : {
89 : 12503 : if (rule->src_port_low > rule->src_port_high ||
90 [ + + ]: 6251 : rule->dst_port_low > rule->dst_port_high ||
91 [ + + ]: 6250 : rule->src_mask_len > BIT_SIZEOF(rule->src_addr) ||
92 [ + + ]: 6249 : 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 : 6248 : ro->data = ri->data;
102 : :
103 : 6248 : ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
104 : 6248 : ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
105 : 6248 : ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
106 : 6248 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
107 : 6248 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
108 : 6248 : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
109 : 6248 : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
110 : :
111 : 6248 : ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
112 : 6248 : ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
113 : 6248 : ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
114 : 6248 : ri->domain_mask;
115 : 6248 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
116 : 6248 : ri->src_mask_len;
117 : 6248 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
118 : 6248 : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
119 : 6248 : ri->src_port_high;
120 : 6248 : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
121 : 6248 : 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 : 1022 : 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 [ + + ]: 1022 : if (ctx == NULL || rules == NULL)
151 : : return -EINVAL;
152 : :
153 : : /* check input rules. */
154 [ + + ]: 7268 : for (i = 0; i != num; i++) {
155 [ + + ]: 6252 : 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 [ + + ]: 7264 : for (i = 0, rc = 0; i != num && rc == 0; i++) {
165 : 6248 : acl_ipv4vlan_convert_rule(rules + i, &rv);
166 : 6248 : rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&rv, 1);
167 : : }
168 : :
169 : : return rc;
170 : : }
171 : :
172 : : static void
173 : 16 : 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 : 16 : memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
224 : 16 : cfg->num_fields = RTE_DIM(ipv4_defs);
225 : :
226 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
227 : 16 : layout[RTE_ACL_IPV4VLAN_PROTO];
228 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
229 : 16 : layout[RTE_ACL_IPV4VLAN_VLAN];
230 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
231 : 16 : layout[RTE_ACL_IPV4VLAN_VLAN] +
232 : : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
233 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
234 : 16 : layout[RTE_ACL_IPV4VLAN_SRC];
235 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
236 : 16 : layout[RTE_ACL_IPV4VLAN_DST];
237 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
238 : 16 : layout[RTE_ACL_IPV4VLAN_PORTS];
239 : 16 : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
240 : 16 : layout[RTE_ACL_IPV4VLAN_PORTS] +
241 : : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
242 : :
243 : 16 : cfg->num_categories = num_categories;
244 : 16 : }
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 : 18 : 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 [ + + ]: 18 : if (ctx == NULL || layout == NULL)
271 : : return -EINVAL;
272 : :
273 : : memset(&cfg, 0, sizeof(cfg));
274 : 16 : acl_ipv4vlan_config(&cfg, layout, num_categories);
275 : 16 : return rte_acl_build(ctx, &cfg);
276 : : }
277 : :
278 : : /*
279 : : * Test ACL lookup (selected alg).
280 : : */
281 : : static int
282 : 33240 : 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 : 33240 : {
285 : : int32_t ret;
286 : : uint32_t i, result, count;
287 : 33240 : uint32_t results[dim * RTE_ACL_MAX_CATEGORIES];
288 : :
289 : : /* set given classify alg, skip test if alg is not supported */
290 : 33240 : ret = rte_acl_set_ctx_classify(acx, alg);
291 [ + + ]: 33240 : if (ret != 0)
292 [ + - ]: 16620 : 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 [ + + ]: 1096876 : for (count = 0; count <= dim; count++) {
299 : 1080256 : ret = rte_acl_classify(acx, data, results,
300 : : count, RTE_ACL_MAX_CATEGORIES);
301 [ - + ]: 1080256 : 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 [ + + ]: 35655164 : for (i = 0; i < count; i++) {
309 : 34574908 : result =
310 : 34574908 : results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
311 [ - + ]: 34574908 : 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 [ + + ]: 35655164 : for (i = 0; i < count; i++) {
322 : 34574908 : result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
323 [ - + ]: 34574908 : 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 : 16620 : 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 : 4155 : test_classify_run(struct rte_acl_ctx *acx, struct ipv4_7tuple test_data[],
342 : : size_t dim)
343 : 4155 : {
344 : : int32_t ret;
345 : : uint32_t i;
346 : 4155 : 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 : : RTE_ACL_CLASSIFY_RVV,
357 : : };
358 : :
359 : : /* swap all bytes in the data to network order */
360 : 4155 : bswap_test_data(test_data, dim, 1);
361 : :
362 : : /* store pointers to test data */
363 [ + + ]: 270064 : for (i = 0; i < dim; i++)
364 : 265909 : data[i] = (uint8_t *)&test_data[i];
365 : :
366 : : ret = 0;
367 [ + + ]: 37395 : for (i = 0; i != RTE_DIM(alg); i++) {
368 : 33240 : ret = test_classify_alg(acx, test_data, data, dim, alg[i]);
369 [ - + ]: 33240 : if (ret < 0) {
370 : 0 : printf("Line %i: %s() for alg=%d failed, errno=%d\n",
371 : : __LINE__, __func__, alg[i], -ret);
372 : : break;
373 : : }
374 : : }
375 : :
376 : : /* swap data back to cpu order so that next time tests don't fail */
377 : 4155 : bswap_test_data(test_data, dim, 0);
378 : 4155 : return ret;
379 : : }
380 : :
381 : : static int
382 : 13 : test_classify_buid(struct rte_acl_ctx *acx,
383 : : const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
384 : : {
385 : : int ret;
386 : :
387 : : /* add rules to the context */
388 : 13 : ret = rte_acl_ipv4vlan_add_rules(acx, rules, num);
389 [ - + ]: 13 : if (ret != 0) {
390 : : printf("Line %i: Adding rules to ACL context failed!\n",
391 : : __LINE__);
392 : 0 : return ret;
393 : : }
394 : :
395 : : /* try building the context */
396 : 13 : ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout,
397 : : RTE_ACL_MAX_CATEGORIES);
398 [ - + ]: 13 : if (ret != 0) {
399 : : printf("Line %i: Building ACL context failed!\n", __LINE__);
400 : 0 : return ret;
401 : : }
402 : :
403 : : return 0;
404 : : }
405 : :
406 : : #define TEST_CLASSIFY_ITER 4
407 : :
408 : : /*
409 : : * Test scalar and SSE ACL lookup.
410 : : */
411 : : static int
412 : 1 : test_classify(void)
413 : : {
414 : : struct rte_acl_ctx *acx;
415 : : int i, ret;
416 : :
417 : 1 : acx = rte_acl_create(&acl_param);
418 [ - + ]: 1 : if (acx == NULL) {
419 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
420 : 0 : return -1;
421 : : }
422 : :
423 : : ret = 0;
424 [ + + ]: 5 : for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
425 : :
426 [ + + ]: 4 : if ((i & 1) == 0)
427 : 2 : rte_acl_reset(acx);
428 : : else
429 : 2 : rte_acl_reset_rules(acx);
430 : :
431 : 4 : ret = test_classify_buid(acx, acl_test_rules,
432 : : RTE_DIM(acl_test_rules));
433 [ - + ]: 4 : if (ret != 0) {
434 : : printf("Line %i, iter: %d: "
435 : : "Adding rules to ACL context failed!\n",
436 : : __LINE__, i);
437 : : break;
438 : : }
439 : :
440 : 4 : ret = test_classify_run(acx, acl_test_data,
441 : : RTE_DIM(acl_test_data));
442 [ - + ]: 4 : if (ret != 0) {
443 : : printf("Line %i, iter: %d: %s failed!\n",
444 : : __LINE__, i, __func__);
445 : : break;
446 : : }
447 : :
448 : : /* reset rules and make sure that classify still works ok. */
449 : 4 : rte_acl_reset_rules(acx);
450 : 4 : ret = test_classify_run(acx, acl_test_data,
451 : : RTE_DIM(acl_test_data));
452 [ - + ]: 4 : if (ret != 0) {
453 : : printf("Line %i, iter: %d: %s failed!\n",
454 : : __LINE__, i, __func__);
455 : : break;
456 : : }
457 : : }
458 : :
459 : 1 : rte_acl_free(acx);
460 : 1 : return ret;
461 : : }
462 : :
463 : : static int
464 : 1 : test_build_ports_range(void)
465 : : {
466 : : static const struct rte_acl_ipv4vlan_rule test_rules[] = {
467 : : {
468 : : /* match all packets. */
469 : : .data = {
470 : : .userdata = 1,
471 : : .category_mask = ACL_ALLOW_MASK,
472 : : .priority = 101,
473 : : },
474 : : .src_port_low = 0,
475 : : .src_port_high = UINT16_MAX,
476 : : .dst_port_low = 0,
477 : : .dst_port_high = UINT16_MAX,
478 : : },
479 : : {
480 : : /* match all packets with dst ports [54-65280]. */
481 : : .data = {
482 : : .userdata = 2,
483 : : .category_mask = ACL_ALLOW_MASK,
484 : : .priority = 102,
485 : : },
486 : : .src_port_low = 0,
487 : : .src_port_high = UINT16_MAX,
488 : : .dst_port_low = 54,
489 : : .dst_port_high = 65280,
490 : : },
491 : : {
492 : : /* match all packets with dst ports [0-52]. */
493 : : .data = {
494 : : .userdata = 3,
495 : : .category_mask = ACL_ALLOW_MASK,
496 : : .priority = 103,
497 : : },
498 : : .src_port_low = 0,
499 : : .src_port_high = UINT16_MAX,
500 : : .dst_port_low = 0,
501 : : .dst_port_high = 52,
502 : : },
503 : : {
504 : : /* match all packets with dst ports [53]. */
505 : : .data = {
506 : : .userdata = 4,
507 : : .category_mask = ACL_ALLOW_MASK,
508 : : .priority = 99,
509 : : },
510 : : .src_port_low = 0,
511 : : .src_port_high = UINT16_MAX,
512 : : .dst_port_low = 53,
513 : : .dst_port_high = 53,
514 : : },
515 : : {
516 : : /* match all packets with dst ports [65279-65535]. */
517 : : .data = {
518 : : .userdata = 5,
519 : : .category_mask = ACL_ALLOW_MASK,
520 : : .priority = 98,
521 : : },
522 : : .src_port_low = 0,
523 : : .src_port_high = UINT16_MAX,
524 : : .dst_port_low = 65279,
525 : : .dst_port_high = UINT16_MAX,
526 : : },
527 : : };
528 : :
529 : : static struct ipv4_7tuple test_data[] = {
530 : : {
531 : : .proto = 6,
532 : : .ip_src = RTE_IPV4(10, 1, 1, 1),
533 : : .ip_dst = RTE_IPV4(192, 168, 0, 33),
534 : : .port_dst = 53,
535 : : .allow = 1,
536 : : },
537 : : {
538 : : .proto = 6,
539 : : .ip_src = RTE_IPV4(127, 84, 33, 1),
540 : : .ip_dst = RTE_IPV4(1, 2, 3, 4),
541 : : .port_dst = 65281,
542 : : .allow = 1,
543 : : },
544 : : };
545 : :
546 : : struct rte_acl_ctx *acx;
547 : : int32_t ret, i, j;
548 : : uint32_t results[RTE_DIM(test_data)];
549 : : const uint8_t *data[RTE_DIM(test_data)];
550 : :
551 : 1 : acx = rte_acl_create(&acl_param);
552 [ - + ]: 1 : if (acx == NULL) {
553 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
554 : 0 : return -1;
555 : : }
556 : :
557 : : /* swap all bytes in the data to network order */
558 : 1 : bswap_test_data(test_data, RTE_DIM(test_data), 1);
559 : :
560 : : /* store pointers to test data */
561 [ + + ]: 3 : for (i = 0; i != RTE_DIM(test_data); i++)
562 : 2 : data[i] = (uint8_t *)&test_data[i];
563 : :
564 [ + + ]: 6 : for (i = 0; i != RTE_DIM(test_rules); i++) {
565 : 5 : rte_acl_reset(acx);
566 : 5 : ret = test_classify_buid(acx, test_rules, i + 1);
567 [ - + ]: 5 : if (ret != 0) {
568 : : printf("Line %i, iter: %d: "
569 : : "Adding rules to ACL context failed!\n",
570 : : __LINE__, i);
571 : : break;
572 : : }
573 : 5 : ret = rte_acl_classify(acx, data, results,
574 : : RTE_DIM(data), 1);
575 [ - + ]: 5 : if (ret != 0) {
576 : : printf("Line %i, iter: %d: classify failed!\n",
577 : : __LINE__, i);
578 : : break;
579 : : }
580 : :
581 : : /* check results */
582 [ + + ]: 15 : for (j = 0; j != RTE_DIM(results); j++) {
583 [ - + ]: 10 : if (results[j] != test_data[j].allow) {
584 : : printf("Line %i: Error in allow results at %i "
585 : : "(expected %"PRIu32" got %"PRIu32")!\n",
586 : : __LINE__, j, test_data[j].allow,
587 : : results[j]);
588 : : ret = -EINVAL;
589 : : }
590 : : }
591 : : }
592 : :
593 : 1 : bswap_test_data(test_data, RTE_DIM(test_data), 0);
594 : :
595 : 1 : rte_acl_free(acx);
596 : 1 : return ret;
597 : : }
598 : :
599 : : static void
600 : 27 : convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
601 : : struct acl_ipv4vlan_rule *ro)
602 : : {
603 : 139 : ro->data = ri->data;
604 : :
605 : 139 : ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
606 : 139 : ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
607 : 139 : ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
608 : 139 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
609 : 139 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
610 : 139 : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
611 : 139 : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
612 : :
613 : 139 : ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
614 : 139 : ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
615 : 139 : ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
616 : 139 : ri->domain_mask;
617 : 139 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
618 : 139 : ri->src_mask_len;
619 : 139 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
620 : 139 : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
621 : 139 : ri->src_port_high;
622 : 139 : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
623 : 139 : ri->dst_port_high;
624 : 27 : }
625 : :
626 : : /*
627 : : * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
628 : : * RTE_ACL_FIELD_TYPE_BITMASK.
629 : : */
630 : : static void
631 : 27 : convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
632 : : struct acl_ipv4vlan_rule *ro)
633 : : {
634 : : uint32_t v;
635 : :
636 : : convert_rule(ri, ro);
637 : : v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
638 : 27 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
639 [ + + ]: 27 : RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
640 : : v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
641 : 27 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 =
642 [ + + ]: 27 : RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
643 : 27 : }
644 : :
645 : : /*
646 : : * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
647 : : * RTE_ACL_FIELD_TYPE_RANGE.
648 : : */
649 : : static void
650 : 27 : convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
651 : : struct acl_ipv4vlan_rule *ro)
652 : : {
653 : : uint32_t hi, lo, mask;
654 : :
655 : : convert_rule(ri, ro);
656 : :
657 : : mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
658 [ + + ]: 27 : mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
659 : 27 : lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask;
660 : 27 : hi = lo + ~mask;
661 : 27 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
662 : 27 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
663 : :
664 : : mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
665 [ + + ]: 27 : mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
666 : 27 : lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask;
667 : 27 : hi = lo + ~mask;
668 : 27 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
669 : 27 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
670 : 27 : }
671 : :
672 : : /*
673 : : * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
674 : : */
675 : : static void
676 : 27 : convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
677 : : struct acl_ipv4vlan_rule *ro)
678 : : {
679 : : struct rte_acl_field t1, t2;
680 : :
681 : : convert_rule(ri, ro);
682 : :
683 : 27 : t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
684 : 27 : t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
685 : :
686 : 27 : ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
687 : : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD];
688 : 27 : ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
689 : : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD];
690 : :
691 : 27 : ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
692 : 27 : ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
693 : 27 : }
694 : :
695 : : /*
696 : : * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
697 : : */
698 : : static void
699 : 27 : convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
700 : : struct acl_ipv4vlan_rule *ro)
701 : : {
702 : : struct rte_acl_field t;
703 : :
704 : : convert_rule(ri, ro);
705 : :
706 : 27 : t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD];
707 : 27 : ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] =
708 : : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD];
709 : :
710 : 27 : ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
711 : 27 : }
712 : :
713 : : static void
714 : 11 : ipv4vlan_config(struct rte_acl_config *cfg,
715 : : const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
716 : : uint32_t num_categories)
717 : : {
718 : : static const struct rte_acl_field_def
719 : : ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
720 : : {
721 : : .type = RTE_ACL_FIELD_TYPE_BITMASK,
722 : : .size = sizeof(uint8_t),
723 : : .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
724 : : .input_index = RTE_ACL_IPV4VLAN_PROTO,
725 : : },
726 : : {
727 : : .type = RTE_ACL_FIELD_TYPE_BITMASK,
728 : : .size = sizeof(uint16_t),
729 : : .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
730 : : .input_index = RTE_ACL_IPV4VLAN_VLAN,
731 : : },
732 : : {
733 : : .type = RTE_ACL_FIELD_TYPE_BITMASK,
734 : : .size = sizeof(uint16_t),
735 : : .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
736 : : .input_index = RTE_ACL_IPV4VLAN_VLAN,
737 : : },
738 : : {
739 : : .type = RTE_ACL_FIELD_TYPE_MASK,
740 : : .size = sizeof(uint32_t),
741 : : .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
742 : : .input_index = RTE_ACL_IPV4VLAN_SRC,
743 : : },
744 : : {
745 : : .type = RTE_ACL_FIELD_TYPE_MASK,
746 : : .size = sizeof(uint32_t),
747 : : .field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
748 : : .input_index = RTE_ACL_IPV4VLAN_DST,
749 : : },
750 : : {
751 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
752 : : .size = sizeof(uint16_t),
753 : : .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
754 : : .input_index = RTE_ACL_IPV4VLAN_PORTS,
755 : : },
756 : : {
757 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
758 : : .size = sizeof(uint16_t),
759 : : .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
760 : : .input_index = RTE_ACL_IPV4VLAN_PORTS,
761 : : },
762 : : };
763 : :
764 : 11 : memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
765 : 11 : cfg->num_fields = RTE_DIM(ipv4_defs);
766 : :
767 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
768 : 11 : layout[RTE_ACL_IPV4VLAN_PROTO];
769 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
770 : 11 : layout[RTE_ACL_IPV4VLAN_VLAN];
771 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
772 : 11 : layout[RTE_ACL_IPV4VLAN_VLAN] +
773 : : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
774 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
775 : 11 : layout[RTE_ACL_IPV4VLAN_SRC];
776 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
777 : 11 : layout[RTE_ACL_IPV4VLAN_DST];
778 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
779 : 11 : layout[RTE_ACL_IPV4VLAN_PORTS];
780 : 11 : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
781 : 11 : layout[RTE_ACL_IPV4VLAN_PORTS] +
782 : : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
783 : :
784 : 11 : cfg->num_categories = num_categories;
785 : 11 : }
786 : :
787 : : static int
788 : 5 : convert_rules(struct rte_acl_ctx *acx,
789 : : void (*convert)(const struct rte_acl_ipv4vlan_rule *,
790 : : struct acl_ipv4vlan_rule *),
791 : : const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
792 : : {
793 : : int32_t rc;
794 : : uint32_t i;
795 : : struct acl_ipv4vlan_rule r;
796 : :
797 [ + + ]: 140 : for (i = 0; i != num; i++) {
798 : 135 : convert(rules + i, &r);
799 : 135 : rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
800 [ - + ]: 135 : if (rc != 0) {
801 : : printf("Line %i: Adding rule %u to ACL context "
802 : : "failed with error code: %d\n",
803 : : __LINE__, i, rc);
804 : 0 : return rc;
805 : : }
806 : : }
807 : :
808 : : return 0;
809 : : }
810 : :
811 : : static void
812 : 2 : convert_config(struct rte_acl_config *cfg)
813 : : {
814 : 2 : ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
815 : 2 : }
816 : :
817 : : /*
818 : : * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
819 : : */
820 : : static void
821 : 2 : convert_config_1(struct rte_acl_config *cfg)
822 : : {
823 : 2 : ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
824 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
825 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
826 : 2 : }
827 : :
828 : : /*
829 : : * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
830 : : */
831 : : static void
832 : 3 : convert_config_2(struct rte_acl_config *cfg)
833 : : {
834 : 3 : ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
835 : 3 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
836 : 3 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
837 : 3 : }
838 : :
839 : : /*
840 : : * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
841 : : */
842 : : static void
843 : 2 : convert_config_3(struct rte_acl_config *cfg)
844 : : {
845 : : struct rte_acl_field_def t1, t2;
846 : :
847 : 2 : ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
848 : :
849 : 2 : t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
850 : 2 : t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
851 : :
852 : : /* swap VLAN1 and SRCP rule definition. */
853 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
854 : : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD];
855 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index;
856 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index;
857 : :
858 : : /* swap VLAN2 and DSTP rule definition. */
859 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
860 : : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD];
861 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index;
862 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index;
863 : :
864 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type;
865 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size;
866 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset;
867 : :
868 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type;
869 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size;
870 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset;
871 : 2 : }
872 : :
873 : : /*
874 : : * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
875 : : */
876 : : static void
877 : 2 : convert_config_4(struct rte_acl_config *cfg)
878 : : {
879 : : struct rte_acl_field_def t;
880 : :
881 : 2 : ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
882 : :
883 : 2 : t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
884 : :
885 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] =
886 : : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD];
887 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index;
888 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index;
889 : :
890 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type;
891 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size;
892 : 2 : cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset;
893 : 2 : }
894 : :
895 : :
896 : : static int
897 : 11 : build_convert_rules(struct rte_acl_ctx *acx,
898 : : void (*config)(struct rte_acl_config *),
899 : : size_t max_size)
900 : : {
901 : : struct rte_acl_config cfg;
902 : :
903 : : memset(&cfg, 0, sizeof(cfg));
904 : 11 : config(&cfg);
905 : 11 : cfg.max_size = max_size;
906 : 11 : return rte_acl_build(acx, &cfg);
907 : : }
908 : :
909 : : static int
910 : 5 : test_convert_rules(const char *desc,
911 : : void (*config)(struct rte_acl_config *),
912 : : void (*convert)(const struct rte_acl_ipv4vlan_rule *,
913 : : struct acl_ipv4vlan_rule *))
914 : : {
915 : : struct rte_acl_ctx *acx;
916 : : int32_t rc;
917 : : uint32_t i;
918 : : static const size_t mem_sizes[] = {0, -1};
919 : :
920 : : printf("running %s(%s)\n", __func__, desc);
921 : :
922 : 5 : acx = rte_acl_create(&acl_param);
923 [ - + ]: 5 : if (acx == NULL) {
924 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
925 : 0 : return -1;
926 : : }
927 : :
928 : 5 : rc = convert_rules(acx, convert, acl_test_rules,
929 : : RTE_DIM(acl_test_rules));
930 [ - + ]: 5 : if (rc != 0)
931 : : printf("Line %i: Error converting ACL rules!\n", __LINE__);
932 : :
933 [ + + ]: 15 : for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
934 : :
935 : 10 : rc = build_convert_rules(acx, config, mem_sizes[i]);
936 [ - + ]: 10 : if (rc != 0) {
937 : : printf("Line %i: Error @ build_convert_rules(%zu)!\n",
938 : : __LINE__, mem_sizes[i]);
939 : : break;
940 : : }
941 : :
942 : 10 : rc = test_classify_run(acx, acl_test_data,
943 : : RTE_DIM(acl_test_data));
944 [ - + ]: 10 : if (rc != 0)
945 : : printf("%s failed at line %i, max_size=%zu\n",
946 : : __func__, __LINE__, mem_sizes[i]);
947 : : }
948 : :
949 : 5 : rte_acl_free(acx);
950 : 5 : return rc;
951 : : }
952 : :
953 : : static int
954 : 1 : test_convert(void)
955 : : {
956 : : static const struct {
957 : : const char *desc;
958 : : void (*config)(struct rte_acl_config *);
959 : : void (*convert)(const struct rte_acl_ipv4vlan_rule *,
960 : : struct acl_ipv4vlan_rule *);
961 : : } convert_param[] = {
962 : : {
963 : : "acl_ipv4vlan_tuple",
964 : : convert_config,
965 : : convert_rule,
966 : : },
967 : : {
968 : : "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
969 : : "for IPv4",
970 : : convert_config_1,
971 : : convert_rule_1,
972 : : },
973 : : {
974 : : "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
975 : : "for IPv4",
976 : : convert_config_2,
977 : : convert_rule_2,
978 : : },
979 : : {
980 : : "acl_ipv4vlan_tuple: swap VLAN and PORTs order",
981 : : convert_config_3,
982 : : convert_rule_3,
983 : : },
984 : : {
985 : : "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
986 : : convert_config_4,
987 : : convert_rule_4,
988 : : },
989 : : };
990 : :
991 : : uint32_t i;
992 : : int32_t rc;
993 : :
994 [ + + ]: 6 : for (i = 0; i != RTE_DIM(convert_param); i++) {
995 : 5 : rc = test_convert_rules(convert_param[i].desc,
996 : 5 : convert_param[i].config,
997 : 5 : convert_param[i].convert);
998 [ - + ]: 5 : if (rc != 0) {
999 : : printf("%s for test-case: %s failed, error code: %d;\n",
1000 : : __func__, convert_param[i].desc, rc);
1001 : 0 : return rc;
1002 : : }
1003 : : }
1004 : :
1005 : : return 0;
1006 : : }
1007 : :
1008 : : /*
1009 : : * Test wrong layout behavior
1010 : : * This test supplies the ACL context with invalid layout, which results in
1011 : : * ACL matching the wrong stuff. However, it should match the wrong stuff
1012 : : * the right way. We switch around source and destination addresses,
1013 : : * source and destination ports, and protocol will point to first byte of
1014 : : * destination port.
1015 : : */
1016 : : static int
1017 : 1 : test_invalid_layout(void)
1018 : : {
1019 : : struct rte_acl_ctx *acx;
1020 : : int ret, i;
1021 : :
1022 : : uint32_t results[RTE_DIM(invalid_layout_data)];
1023 : : const uint8_t *data[RTE_DIM(invalid_layout_data)];
1024 : :
1025 : 1 : const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
1026 : : /* proto points to destination port's first byte */
1027 : : offsetof(struct ipv4_7tuple, port_dst),
1028 : :
1029 : : 0, /* VLAN not used */
1030 : :
1031 : : /* src and dst addresses are swapped */
1032 : : offsetof(struct ipv4_7tuple, ip_dst),
1033 : : offsetof(struct ipv4_7tuple, ip_src),
1034 : :
1035 : : /*
1036 : : * we can't swap ports here, so we will swap
1037 : : * them in the data
1038 : : */
1039 : : offsetof(struct ipv4_7tuple, port_src),
1040 : : };
1041 : :
1042 : 1 : acx = rte_acl_create(&acl_param);
1043 [ - + ]: 1 : if (acx == NULL) {
1044 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
1045 : 0 : return -1;
1046 : : }
1047 : :
1048 : : /* putting a lot of rules into the context results in greater
1049 : : * coverage numbers. it doesn't matter if they are identical */
1050 [ + + ]: 1001 : for (i = 0; i < 1000; i++) {
1051 : : /* add rules to the context */
1052 : 1000 : ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
1053 : : RTE_DIM(invalid_layout_rules));
1054 [ - + ]: 1000 : if (ret != 0) {
1055 : : printf("Line %i: Adding rules to ACL context failed!\n",
1056 : : __LINE__);
1057 : 0 : rte_acl_free(acx);
1058 : 0 : return -1;
1059 : : }
1060 : : }
1061 : :
1062 : : /* try building the context */
1063 : 1 : ret = rte_acl_ipv4vlan_build(acx, layout, 1);
1064 [ - + ]: 1 : if (ret != 0) {
1065 : : printf("Line %i: Building ACL context failed!\n", __LINE__);
1066 : 0 : rte_acl_free(acx);
1067 : 0 : return -1;
1068 : : }
1069 : :
1070 : : /* swap all bytes in the data to network order */
1071 : 1 : bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
1072 : :
1073 : : /* prepare data */
1074 [ + + ]: 5 : for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
1075 : 4 : data[i] = (uint8_t *)&invalid_layout_data[i];
1076 : : }
1077 : :
1078 : : /* classify tuples */
1079 : 1 : ret = rte_acl_classify_alg(acx, data, results,
1080 : : RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
1081 [ - + ]: 1 : if (ret != 0) {
1082 : : printf("Line %i: SSE classify failed!\n", __LINE__);
1083 : 0 : rte_acl_free(acx);
1084 : 0 : return -1;
1085 : : }
1086 : :
1087 [ + + ]: 5 : for (i = 0; i < (int) RTE_DIM(results); i++) {
1088 [ - + ]: 4 : if (results[i] != invalid_layout_data[i].allow) {
1089 : : printf("Line %i: Wrong results at %i "
1090 : : "(result=%u, should be %u)!\n",
1091 : : __LINE__, i, results[i],
1092 : : invalid_layout_data[i].allow);
1093 : 0 : goto err;
1094 : : }
1095 : : }
1096 : :
1097 : : /* classify tuples (scalar) */
1098 : 1 : ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
1099 : : RTE_ACL_CLASSIFY_SCALAR);
1100 : :
1101 [ - + ]: 1 : if (ret != 0) {
1102 : : printf("Line %i: Scalar classify failed!\n", __LINE__);
1103 : 0 : rte_acl_free(acx);
1104 : 0 : return -1;
1105 : : }
1106 : :
1107 [ + + ]: 5 : for (i = 0; i < (int) RTE_DIM(results); i++) {
1108 [ - + ]: 4 : if (results[i] != invalid_layout_data[i].allow) {
1109 : : printf("Line %i: Wrong results at %i "
1110 : : "(result=%u, should be %u)!\n",
1111 : : __LINE__, i, results[i],
1112 : : invalid_layout_data[i].allow);
1113 : 0 : goto err;
1114 : : }
1115 : : }
1116 : :
1117 : 1 : rte_acl_free(acx);
1118 : :
1119 : : /* swap data back to cpu order so that next time tests don't fail */
1120 : 1 : bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
1121 : :
1122 : 1 : return 0;
1123 : 0 : err:
1124 : :
1125 : : /* swap data back to cpu order so that next time tests don't fail */
1126 : 0 : bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
1127 : :
1128 : 0 : rte_acl_free(acx);
1129 : :
1130 : 0 : return -1;
1131 : : }
1132 : :
1133 : : /*
1134 : : * Test creating and finding ACL contexts, and adding rules
1135 : : */
1136 : : static int
1137 : 1 : test_create_find_add(void)
1138 : : {
1139 : : struct rte_acl_param param;
1140 : : struct rte_acl_ctx *acx, *acx2, *tmp;
1141 : : struct rte_acl_ipv4vlan_rule rules[LEN];
1142 : :
1143 : 1 : const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
1144 : :
1145 : : const char *acx_name = "acx";
1146 : : const char *acx2_name = "acx2";
1147 : : int i, ret;
1148 : :
1149 : : /* create two contexts */
1150 : : memcpy(¶m, &acl_param, sizeof(param));
1151 : 1 : param.max_rule_num = 2;
1152 : :
1153 : 1 : param.name = acx_name;
1154 : 1 : acx = rte_acl_create(¶m);
1155 [ - + ]: 1 : if (acx == NULL) {
1156 : : printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
1157 : 0 : return -1;
1158 : : }
1159 : :
1160 : 1 : param.name = acx2_name;
1161 : 1 : acx2 = rte_acl_create(¶m);
1162 [ - + ]: 1 : if (acx2 == NULL || acx2 == acx) {
1163 : : printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
1164 : 0 : rte_acl_free(acx);
1165 : 0 : return -1;
1166 : : }
1167 : :
1168 : : /* try to create third one, with an existing name */
1169 : 1 : param.name = acx_name;
1170 : 1 : tmp = rte_acl_create(¶m);
1171 [ - + ]: 1 : if (tmp != acx) {
1172 : : printf("Line %i: Creating context with existing name "
1173 : : "test failed!\n",
1174 : : __LINE__);
1175 : 0 : rte_acl_free(tmp);
1176 : 0 : goto err;
1177 : : }
1178 : :
1179 : 1 : param.name = acx2_name;
1180 : 1 : tmp = rte_acl_create(¶m);
1181 [ - + ]: 1 : if (tmp != acx2) {
1182 : : printf("Line %i: Creating context with existing "
1183 : : "name test 2 failed!\n",
1184 : : __LINE__);
1185 : 0 : rte_acl_free(tmp);
1186 : 0 : goto err;
1187 : : }
1188 : :
1189 : : /* try to find existing ACL contexts */
1190 : 1 : tmp = rte_acl_find_existing(acx_name);
1191 [ - + ]: 1 : if (tmp != acx) {
1192 : : printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
1193 : 0 : rte_acl_free(tmp);
1194 : 0 : goto err;
1195 : : }
1196 : :
1197 : 1 : tmp = rte_acl_find_existing(acx2_name);
1198 [ - + ]: 1 : if (tmp != acx2) {
1199 : : printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
1200 : 0 : rte_acl_free(tmp);
1201 : 0 : goto err;
1202 : : }
1203 : :
1204 : : /* try to find non-existing context */
1205 : 1 : tmp = rte_acl_find_existing("invalid");
1206 [ - + ]: 1 : if (tmp != NULL) {
1207 : : printf("Line %i: Non-existent ACL context found!\n", __LINE__);
1208 : 0 : goto err;
1209 : : }
1210 : :
1211 : : /* free context */
1212 : 1 : rte_acl_free(acx);
1213 : :
1214 : :
1215 : : /* create valid (but severely limited) acx */
1216 : : memcpy(¶m, &acl_param, sizeof(param));
1217 : 1 : param.max_rule_num = LEN;
1218 : :
1219 : 1 : acx = rte_acl_create(¶m);
1220 [ - + ]: 1 : if (acx == NULL) {
1221 : 0 : printf("Line %i: Error creating %s!\n", __LINE__, param.name);
1222 : 0 : goto err;
1223 : : }
1224 : :
1225 : : /* create dummy acl */
1226 [ + + ]: 17 : for (i = 0; i < LEN; i++) {
1227 : 16 : rules[i] = acl_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 : 1 : rule = acl_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 struct rte_acl_ctx *acl_ctx;
1726 : :
1727 : : static void *
1728 : 4 : running_alloc(char *name, size_t size,
1729 : : size_t align, int32_t socket_id, void *udata)
1730 : : {
1731 : 4 : size_t aligned_size = RTE_ALIGN_CEIL(size, align);
1732 : : RTE_SET_USED(name);
1733 : : RTE_SET_USED(socket_id);
1734 : :
1735 [ - + ]: 4 : if (udata != acl_ctx) {
1736 : : printf("%s#%i udata mismatch!\n",
1737 : : __func__, __LINE__);
1738 : 0 : return NULL;
1739 : : }
1740 : 4 : void *addr = aligned_alloc(align, aligned_size);
1741 [ - + ]: 4 : if (addr == NULL) {
1742 : : printf("%s#%i alloc memory failed!\n",
1743 : : __func__, __LINE__);
1744 : : }
1745 : : return addr;
1746 : : }
1747 : :
1748 : : static void
1749 : 6 : running_free(void *ptr, void *udata)
1750 : : {
1751 [ - + ]: 6 : if (udata != acl_ctx) {
1752 : : printf("%s#%i udata mismatch!\n",
1753 : : __func__, __LINE__);
1754 : 0 : return;
1755 : : }
1756 : 6 : free(ptr);
1757 : : }
1758 : :
1759 : : static int
1760 : 1 : test_mem_hook(void)
1761 : : {
1762 : : int i, ret;
1763 : : struct rte_acl_mem_hook new_hook;
1764 : :
1765 : 1 : acl_ctx = rte_acl_create(&acl_param);
1766 [ - + ]: 1 : if (acl_ctx == NULL) {
1767 : : printf("Line %i: Error creating ACL context!\n", __LINE__);
1768 : 0 : return -1;
1769 : : }
1770 : :
1771 : 1 : struct rte_acl_mem_hook mhook = {
1772 : : .zalloc = running_alloc,
1773 : : .free = running_free,
1774 : : .udata = acl_ctx
1775 : : };
1776 : :
1777 : 1 : ret = rte_acl_set_mem_hook(acl_ctx, &mhook);
1778 [ - + ]: 1 : if (ret != 0) {
1779 : : printf("Line %i: Error set mem hook for acl context!\n", __LINE__);
1780 : 0 : rte_acl_free(acl_ctx);
1781 : 0 : return -1;
1782 : : }
1783 : :
1784 : : memset(&new_hook, 0, sizeof(struct rte_acl_mem_hook));
1785 [ + - ]: 1 : if (rte_acl_get_mem_hook(acl_ctx, &new_hook) != 0
1786 [ - + ]: 1 : || memcmp(&mhook, &new_hook, sizeof(struct rte_acl_mem_hook)) != 0) {
1787 : : printf("Line %i: Error get mem hook for acl context!\n", __LINE__);
1788 : 0 : rte_acl_free(acl_ctx);
1789 : 0 : return -1;
1790 : : }
1791 : :
1792 : : ret = 0;
1793 [ + + ]: 5 : for (i = 0; i < TEST_CLASSIFY_ITER; i++) {
1794 [ + + ]: 4 : if ((i & 1) == 0)
1795 : 2 : rte_acl_reset(acl_ctx);
1796 : : else
1797 : 2 : rte_acl_reset_rules(acl_ctx);
1798 : :
1799 : 4 : ret = test_classify_buid(acl_ctx, acl_test_rules,
1800 : : RTE_DIM(acl_test_rules));
1801 [ - + ]: 4 : if (ret != 0) {
1802 : : printf("Line %i, iter: %d: Adding rules to ACL context failed!\n",
1803 : : __LINE__, i);
1804 : : break;
1805 : : }
1806 : :
1807 : 4 : ret = test_classify_run(acl_ctx, acl_test_data,
1808 : : RTE_DIM(acl_test_data));
1809 [ - + ]: 4 : if (ret != 0) {
1810 : : printf("Line %i, iter: %d: %s failed!\n",
1811 : : __LINE__, i, __func__);
1812 : : break;
1813 : : }
1814 : :
1815 : : /* reset rules and make sure that classify still works ok. */
1816 : 4 : rte_acl_reset_rules(acl_ctx);
1817 : 4 : ret = test_classify_run(acl_ctx, acl_test_data,
1818 : : RTE_DIM(acl_test_data));
1819 [ - + ]: 4 : if (ret != 0) {
1820 : : printf("Line %i, iter: %d: %s failed!\n",
1821 : : __LINE__, i, __func__);
1822 : : break;
1823 : : }
1824 : : }
1825 : :
1826 : 1 : rte_acl_free(acl_ctx);
1827 : 1 : acl_ctx = NULL;
1828 : 1 : return ret;
1829 : : }
1830 : :
1831 : : static int
1832 : 1 : test_acl(void)
1833 : : {
1834 [ + - ]: 1 : if (test_invalid_parameters() < 0)
1835 : : return -1;
1836 [ + - ]: 1 : if (test_invalid_rules() < 0)
1837 : : return -1;
1838 [ + - ]: 1 : if (test_create_find_add() < 0)
1839 : : return -1;
1840 [ + - ]: 1 : if (test_invalid_layout() < 0)
1841 : : return -1;
1842 [ + - ]: 1 : if (test_misc() < 0)
1843 : : return -1;
1844 [ + - ]: 1 : if (test_classify() < 0)
1845 : : return -1;
1846 [ + - ]: 1 : if (test_build_ports_range() < 0)
1847 : : return -1;
1848 [ + - ]: 1 : if (test_convert() < 0)
1849 : : return -1;
1850 [ + - ]: 1 : if (test_u32_range() < 0)
1851 : : return -1;
1852 [ - + ]: 1 : if (test_mem_hook() < 0)
1853 : 0 : return -1;
1854 : :
1855 : : return 0;
1856 : : }
1857 : :
1858 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1859 : :
1860 : 301 : REGISTER_FAST_TEST(acl_autotest, NOHUGE_OK, ASAN_OK, test_acl);
|