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