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