Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #ifndef RTE_EXEC_ENV_WINDOWS
6 : :
7 : : #include <rte_ip.h>
8 : : #include <rte_string_fns.h>
9 : : #include <rte_hexdump.h>
10 : : #include "test_table.h"
11 : : #include "test_table_acl.h"
12 : :
13 : : /*
14 : : * Rule and trace formats definitions.
15 : : **/
16 : :
17 : : struct ipv4_5tuple {
18 : : uint8_t proto;
19 : : uint32_t ip_src;
20 : : uint32_t ip_dst;
21 : : uint16_t port_src;
22 : : uint16_t port_dst;
23 : : };
24 : :
25 : : enum {
26 : : PROTO_FIELD_IPV4,
27 : : SRC_FIELD_IPV4,
28 : : DST_FIELD_IPV4,
29 : : SRCP_FIELD_IPV4,
30 : : DSTP_FIELD_IPV4,
31 : : NUM_FIELDS_IPV4
32 : : };
33 : :
34 : : struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
35 : : {
36 : : .type = RTE_ACL_FIELD_TYPE_BITMASK,
37 : : .size = sizeof(uint8_t),
38 : : .field_index = PROTO_FIELD_IPV4,
39 : : .input_index = PROTO_FIELD_IPV4,
40 : : .offset = offsetof(struct ipv4_5tuple, proto),
41 : : },
42 : : {
43 : : .type = RTE_ACL_FIELD_TYPE_MASK,
44 : : .size = sizeof(uint32_t),
45 : : .field_index = SRC_FIELD_IPV4,
46 : : .input_index = SRC_FIELD_IPV4,
47 : : .offset = offsetof(struct ipv4_5tuple, ip_src),
48 : : },
49 : : {
50 : : .type = RTE_ACL_FIELD_TYPE_MASK,
51 : : .size = sizeof(uint32_t),
52 : : .field_index = DST_FIELD_IPV4,
53 : : .input_index = DST_FIELD_IPV4,
54 : : .offset = offsetof(struct ipv4_5tuple, ip_dst),
55 : : },
56 : : {
57 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
58 : : .size = sizeof(uint16_t),
59 : : .field_index = SRCP_FIELD_IPV4,
60 : : .input_index = SRCP_FIELD_IPV4,
61 : : .offset = offsetof(struct ipv4_5tuple, port_src),
62 : : },
63 : : {
64 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
65 : : .size = sizeof(uint16_t),
66 : : .field_index = DSTP_FIELD_IPV4,
67 : : .input_index = SRCP_FIELD_IPV4,
68 : : .offset = offsetof(struct ipv4_5tuple, port_dst),
69 : : },
70 : : };
71 : :
72 : : struct rte_table_acl_rule_add_params table_acl_IPv4_rule;
73 : :
74 : : typedef int (*parse_5tuple)(char *text,
75 : : struct rte_table_acl_rule_add_params *rule);
76 : :
77 : : /*
78 : : * The order of the fields in the rule string after the initial '@'
79 : : */
80 : : enum {
81 : : CB_FLD_SRC_ADDR,
82 : : CB_FLD_DST_ADDR,
83 : : CB_FLD_SRC_PORT_RANGE,
84 : : CB_FLD_DST_PORT_RANGE,
85 : : CB_FLD_PROTO,
86 : : CB_FLD_NUM,
87 : : };
88 : :
89 : :
90 : : #define GET_CB_FIELD(in, fd, base, lim, dlm) \
91 : : do { \
92 : : unsigned long val; \
93 : : char *end; \
94 : : \
95 : : errno = 0; \
96 : : val = strtoul((in), &end, (base)); \
97 : : if (errno != 0 || end[0] != (dlm) || val > (lim)) \
98 : : return -EINVAL; \
99 : : (fd) = (typeof(fd)) val; \
100 : : (in) = end + 1; \
101 : : } while (0)
102 : :
103 : :
104 : :
105 : :
106 : : static int
107 : 88 : parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
108 : : {
109 : : uint8_t a, b, c, d, m;
110 : :
111 [ + - + - : 88 : GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
- + ]
112 [ + - + - : 88 : GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
- + ]
113 [ + - + - : 88 : GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
- + ]
114 [ + - + - : 88 : GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
- + ]
115 [ + - + - : 88 : GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
- + ]
116 : :
117 : 88 : addr[0] = RTE_IPV4(a, b, c, d);
118 : 88 : mask_len[0] = m;
119 : :
120 : 88 : return 0;
121 : : }
122 : :
123 : : static int
124 : 88 : parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high)
125 : : {
126 : : uint16_t a, b;
127 : :
128 [ + - + - : 88 : GET_CB_FIELD(in, a, 0, UINT16_MAX, ':');
- + ]
129 [ + - + - : 88 : GET_CB_FIELD(in, b, 0, UINT16_MAX, 0);
- + ]
130 : :
131 : 88 : port_low[0] = a;
132 : 88 : port_high[0] = b;
133 : :
134 : 88 : return 0;
135 : : }
136 : :
137 : : static int
138 : 34 : parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
139 : : {
140 : : int i, rc;
141 : : char *s, *sp, *in[CB_FLD_NUM];
142 : : static const char *dlm = " \t\n";
143 : :
144 : : /*
145 : : ** Skip leading '@'
146 : : */
147 [ + - ]: 34 : if (strchr(str, '@') != str)
148 : : return -EINVAL;
149 : :
150 : 34 : s = str + 1;
151 : :
152 : : /*
153 : : * Populate the 'in' array with the location of each
154 : : * field in the string we're parsing
155 : : */
156 [ + + ]: 204 : for (i = 0; i != DIM(in); i++) {
157 : 170 : in[i] = strtok_r(s, dlm, &sp);
158 [ + - ]: 170 : if (in[i] == NULL)
159 : : return -EINVAL;
160 : : s = NULL;
161 : : }
162 : :
163 : : /* Parse x.x.x.x/x */
164 : 34 : rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
165 : : &v->field_value[SRC_FIELD_IPV4].value.u32,
166 : : &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
167 [ - + ]: 34 : if (rc != 0) {
168 : 0 : fprintf(stderr, "failed to read src address/mask: %s\n",
169 : : in[CB_FLD_SRC_ADDR]);
170 : 0 : return rc;
171 : : }
172 : :
173 : 34 : printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
174 : : v->field_value[SRC_FIELD_IPV4].mask_range.u32);
175 : :
176 : : /* Parse x.x.x.x/x */
177 : 34 : rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
178 : : &v->field_value[DST_FIELD_IPV4].value.u32,
179 : : &v->field_value[DST_FIELD_IPV4].mask_range.u32);
180 [ - + ]: 34 : if (rc != 0) {
181 : 0 : fprintf(stderr, "failed to read dest address/mask: %s\n",
182 : : in[CB_FLD_DST_ADDR]);
183 : 0 : return rc;
184 : : }
185 : :
186 : 34 : printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
187 : : v->field_value[DST_FIELD_IPV4].mask_range.u32);
188 : : /* Parse n:n */
189 : 34 : rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
190 : : &v->field_value[SRCP_FIELD_IPV4].value.u16,
191 : : &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
192 [ - + ]: 34 : if (rc != 0) {
193 : 0 : fprintf(stderr, "failed to read source port range: %s\n",
194 : : in[CB_FLD_SRC_PORT_RANGE]);
195 : 0 : return rc;
196 : : }
197 : :
198 : 34 : printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
199 : 34 : v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
200 : : /* Parse n:n */
201 : 34 : rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
202 : : &v->field_value[DSTP_FIELD_IPV4].value.u16,
203 : : &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
204 [ - + ]: 34 : if (rc != 0) {
205 : 0 : fprintf(stderr, "failed to read dest port range: %s\n",
206 : : in[CB_FLD_DST_PORT_RANGE]);
207 : 0 : return rc;
208 : : }
209 : :
210 : 34 : printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
211 : 34 : v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
212 : : /* parse 0/0xnn */
213 [ + - + - : 34 : GET_CB_FIELD(in[CB_FLD_PROTO],
- + ]
214 : : v->field_value[PROTO_FIELD_IPV4].value.u8,
215 : : 0, UINT8_MAX, '/');
216 [ + - + - : 34 : GET_CB_FIELD(in[CB_FLD_PROTO],
- + ]
217 : : v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
218 : : 0, UINT8_MAX, 0);
219 : :
220 : 34 : printf("V=%u, mask=%u\n",
221 : 34 : (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
222 : : v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
223 : 34 : return 0;
224 : : }
225 : :
226 : : static int
227 : 10 : parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v)
228 : : {
229 : : int i, rc;
230 : : char *s, *sp, *in[CB_FLD_NUM];
231 : : static const char *dlm = " \t\n";
232 : :
233 : : /*
234 : : ** Skip leading '@'
235 : : */
236 [ + - ]: 10 : if (strchr(str, '@') != str)
237 : : return -EINVAL;
238 : :
239 : 10 : s = str + 1;
240 : :
241 : : /*
242 : : * Populate the 'in' array with the location of each
243 : : * field in the string we're parsing
244 : : */
245 [ + + ]: 60 : for (i = 0; i != DIM(in); i++) {
246 : 50 : in[i] = strtok_r(s, dlm, &sp);
247 [ + - ]: 50 : if (in[i] == NULL)
248 : : return -EINVAL;
249 : : s = NULL;
250 : : }
251 : :
252 : : /* Parse x.x.x.x/x */
253 : 10 : rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
254 : : &v->field_value[SRC_FIELD_IPV4].value.u32,
255 : : &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
256 [ - + ]: 10 : if (rc != 0) {
257 : 0 : fprintf(stderr, "failed to read src address/mask: %s\n",
258 : : in[CB_FLD_SRC_ADDR]);
259 : 0 : return rc;
260 : : }
261 : :
262 : 10 : printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
263 : : v->field_value[SRC_FIELD_IPV4].mask_range.u32);
264 : :
265 : : /* Parse x.x.x.x/x */
266 : 10 : rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
267 : : &v->field_value[DST_FIELD_IPV4].value.u32,
268 : : &v->field_value[DST_FIELD_IPV4].mask_range.u32);
269 [ - + ]: 10 : if (rc != 0) {
270 : 0 : fprintf(stderr, "failed to read dest address/mask: %s\n",
271 : : in[CB_FLD_DST_ADDR]);
272 : 0 : return rc;
273 : : }
274 : :
275 : 10 : printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
276 : : v->field_value[DST_FIELD_IPV4].mask_range.u32);
277 : : /* Parse n:n */
278 : 10 : rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
279 : : &v->field_value[SRCP_FIELD_IPV4].value.u16,
280 : : &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
281 [ - + ]: 10 : if (rc != 0) {
282 : 0 : fprintf(stderr, "failed to read source port range: %s\n",
283 : : in[CB_FLD_SRC_PORT_RANGE]);
284 : 0 : return rc;
285 : : }
286 : :
287 : 10 : printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
288 : 10 : v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
289 : : /* Parse n:n */
290 : 10 : rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
291 : : &v->field_value[DSTP_FIELD_IPV4].value.u16,
292 : : &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
293 [ - + ]: 10 : if (rc != 0) {
294 : 0 : fprintf(stderr, "failed to read dest port range: %s\n",
295 : : in[CB_FLD_DST_PORT_RANGE]);
296 : 0 : return rc;
297 : : }
298 : :
299 : 10 : printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
300 : 10 : v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
301 : : /* parse 0/0xnn */
302 [ + - + - : 10 : GET_CB_FIELD(in[CB_FLD_PROTO],
- + ]
303 : : v->field_value[PROTO_FIELD_IPV4].value.u8,
304 : : 0, UINT8_MAX, '/');
305 [ + - + - : 10 : GET_CB_FIELD(in[CB_FLD_PROTO],
- + ]
306 : : v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
307 : : 0, UINT8_MAX, 0);
308 : :
309 : 10 : printf("V=%u, mask=%u\n",
310 : 10 : (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
311 : : v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
312 : 10 : return 0;
313 : : }
314 : :
315 : : /*
316 : : * The format for these rules DO NOT need the port ranges to be
317 : : * separated by ' : ', just ':'. It's a lot more readable and
318 : : * cleaner, IMO.
319 : : */
320 : : char lines[][128] = {
321 : : "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
322 : : "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */
323 : : "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
324 : : "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
325 : : "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
326 : : };
327 : :
328 : : char line[128];
329 : :
330 : :
331 : : static int
332 : 1 : setup_acl_pipeline(void)
333 : : {
334 : : int ret;
335 : : int i;
336 : 1 : struct rte_pipeline_params pipeline_params = {
337 : : .name = "PIPELINE",
338 : : .socket_id = 0,
339 : : };
340 : : uint32_t n;
341 : : struct rte_table_acl_rule_add_params rule_params;
342 : : struct rte_pipeline_table_acl_rule_delete_params *delete_params;
343 : : parse_5tuple parser;
344 : : char acl_name[64];
345 : :
346 : : /* Pipeline configuration */
347 : 1 : p = rte_pipeline_create(&pipeline_params);
348 [ - + ]: 1 : if (p == NULL) {
349 : 0 : fprintf(stderr, "%s: Failed to configure pipeline\n",
350 : : __func__);
351 : 0 : goto fail;
352 : : }
353 : :
354 : : /* Input port configuration */
355 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
356 : 2 : struct rte_port_ring_reader_params port_ring_params = {
357 : 2 : .ring = rings_rx[i],
358 : : };
359 : :
360 : 2 : struct rte_pipeline_port_in_params port_params = {
361 : : .ops = &rte_port_ring_reader_ops,
362 : : .arg_create = (void *) &port_ring_params,
363 : : .f_action = NULL,
364 : : .burst_size = BURST_SIZE,
365 : : };
366 : :
367 : : /* Put in action for some ports */
368 [ + + ]: 2 : if (i)
369 : 1 : port_params.f_action = port_in_action;
370 : :
371 : 2 : ret = rte_pipeline_port_in_create(p, &port_params,
372 : : &port_in_id[i]);
373 [ - + ]: 2 : if (ret) {
374 : 0 : rte_panic("Unable to configure input port %d, ret:%d\n",
375 : : i, ret);
376 : : goto fail;
377 : : }
378 : : }
379 : :
380 : : /* output Port configuration */
381 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
382 : 2 : struct rte_port_ring_writer_params port_ring_params = {
383 : 2 : .ring = rings_tx[i],
384 : : .tx_burst_sz = BURST_SIZE,
385 : : };
386 : :
387 : 2 : struct rte_pipeline_port_out_params port_params = {
388 : : .ops = &rte_port_ring_writer_ops,
389 : : .arg_create = (void *) &port_ring_params,
390 : : .f_action = NULL,
391 : : .arg_ah = NULL,
392 : : };
393 : :
394 : :
395 [ - + ]: 2 : if (rte_pipeline_port_out_create(p, &port_params,
396 : : &port_out_id[i])) {
397 : 0 : rte_panic("Unable to configure output port %d\n", i);
398 : : goto fail;
399 : : }
400 : : }
401 : :
402 : : /* Table configuration */
403 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
404 : : struct rte_pipeline_table_params table_params;
405 : :
406 : : /* Set up defaults for stub */
407 : 2 : table_params.ops = &rte_table_stub_ops;
408 : 2 : table_params.arg_create = NULL;
409 : 2 : table_params.f_action_hit = action_handler_hit;
410 : 2 : table_params.f_action_miss = NULL;
411 : 2 : table_params.action_data_size = 0;
412 : :
413 : 2 : printf("miss_action=%x\n",
414 : : table_entry_miss_action);
415 : :
416 : : printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
417 : : RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
418 : :
419 : : struct rte_table_acl_params acl_params;
420 : :
421 : 2 : acl_params.n_rules = 1 << 5;
422 : 2 : acl_params.n_rule_fields = DIM(ipv4_defs);
423 : : snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
424 : 2 : acl_params.name = acl_name;
425 : : memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
426 : :
427 : 2 : table_params.ops = &rte_table_acl_ops;
428 : 2 : table_params.arg_create = &acl_params;
429 : :
430 [ - + ]: 2 : if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
431 : 0 : rte_panic("Unable to configure table %u\n", i);
432 : : goto fail;
433 : : }
434 : :
435 [ - + ]: 2 : if (connect_miss_action_to_table) {
436 [ # # ]: 0 : if (rte_pipeline_table_create(p, &table_params,
437 : 0 : &table_id[i+2])) {
438 : 0 : rte_panic("Unable to configure table %u\n", i);
439 : : goto fail;
440 : : }
441 : : }
442 : : }
443 : :
444 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
445 [ - + ]: 2 : if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
446 : : table_id[i])) {
447 : 0 : rte_panic("Unable to connect input port %u to "
448 : : "table %u\n",
449 : : port_in_id[i], table_id[i]);
450 : : goto fail;
451 : : }
452 : : }
453 : :
454 : : /* Add bulk entries to tables */
455 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
456 : : struct rte_table_acl_rule_add_params keys[5];
457 : : struct rte_pipeline_table_entry entries[5];
458 : : struct rte_table_acl_rule_add_params *key_array[5];
459 : : struct rte_pipeline_table_entry *table_entries[5];
460 : : int key_found[5];
461 : : struct rte_pipeline_table_entry *table_entries_ptr[5];
462 : : struct rte_pipeline_table_entry entries_ptr[5];
463 : :
464 : : parser = parse_cb_ipv4_rule;
465 [ + + ]: 12 : for (n = 0; n < 5; n++) {
466 : 10 : memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
467 : 10 : key_array[n] = &keys[n];
468 : :
469 : 10 : strlcpy(line, lines[n], sizeof(line));
470 : : printf("PARSING [%s]\n", line);
471 : :
472 : 10 : ret = parser(line, &keys[n]);
473 [ - + ]: 10 : if (ret != 0) {
474 : 0 : fprintf(stderr,
475 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
476 : : n, ret, strerror(-ret));
477 : 0 : return ret;
478 : : }
479 : :
480 : 10 : keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
481 : :
482 : 10 : entries[n].action = RTE_PIPELINE_ACTION_PORT;
483 : 10 : entries[n].port_id = port_out_id[i^1];
484 : 10 : table_entries[n] = &entries[n];
485 : 10 : table_entries_ptr[n] = &entries_ptr[n];
486 : : }
487 : :
488 : 2 : ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
489 : : (void **)key_array, table_entries, 5, key_found, table_entries_ptr);
490 [ - + ]: 2 : if (ret < 0) {
491 : 0 : rte_panic("Add entry bulk to table %u failed (%d)\n",
492 : : table_id[i], ret);
493 : : goto fail;
494 : : }
495 : : }
496 : :
497 : : /* Delete bulk entries from tables */
498 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
499 : : struct rte_table_acl_rule_delete_params keys[5];
500 : : struct rte_table_acl_rule_delete_params *key_array[5];
501 : : struct rte_pipeline_table_entry *table_entries[5];
502 : : int key_found[5];
503 : :
504 : : memset(table_entries, 0, sizeof(table_entries));
505 : :
506 [ + + ]: 12 : for (n = 0; n < 5; n++) {
507 : 10 : memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
508 : 10 : key_array[n] = &keys[n];
509 : :
510 : 10 : strlcpy(line, lines[n], sizeof(line));
511 : : printf("PARSING [%s]\n", line);
512 : :
513 : 10 : ret = parse_cb_ipv4_rule_del(line, &keys[n]);
514 [ - + ]: 10 : if (ret != 0) {
515 : 0 : fprintf(stderr,
516 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
517 : : n, ret, strerror(-ret));
518 : 0 : return ret;
519 : : }
520 : : }
521 : :
522 : 2 : ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
523 : : (void **)key_array, 5, key_found, table_entries);
524 [ - + ]: 2 : if (ret < 0) {
525 : 0 : rte_panic("Delete bulk entries from table %u failed (%d)\n",
526 : : table_id[i], ret);
527 : : goto fail;
528 : : } else
529 : : printf("Bulk deleted rules.\n");
530 : : }
531 : :
532 : : /* Add entries to tables */
533 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
534 : 2 : struct rte_pipeline_table_entry table_entry = {
535 : : .action = RTE_PIPELINE_ACTION_PORT,
536 : 2 : {.port_id = port_out_id[i^1]},
537 : : };
538 : : int key_found;
539 : : struct rte_pipeline_table_entry *entry_ptr;
540 : :
541 : : memset(&rule_params, 0, sizeof(rule_params));
542 : : parser = parse_cb_ipv4_rule;
543 : :
544 [ + + ]: 12 : for (n = 1; n <= 5; n++) {
545 : 10 : strlcpy(line, lines[n - 1], sizeof(line));
546 : : printf("PARSING [%s]\n", line);
547 : :
548 : 10 : ret = parser(line, &rule_params);
549 [ - + ]: 10 : if (ret != 0) {
550 : 0 : fprintf(stderr,
551 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
552 : : n, ret, strerror(-ret));
553 : 0 : return ret;
554 : : }
555 : :
556 : 10 : rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
557 : :
558 : 10 : ret = rte_pipeline_table_entry_add(p, table_id[i],
559 : : &rule_params,
560 : : &table_entry, &key_found, &entry_ptr);
561 [ - + ]: 10 : if (ret < 0) {
562 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
563 : : table_id[i], ret);
564 : : goto fail;
565 : : }
566 : : }
567 : :
568 : : /* delete a few rules */
569 [ + + ]: 6 : for (n = 2; n <= 3; n++) {
570 : 4 : strlcpy(line, lines[n - 1], sizeof(line));
571 : : printf("PARSING [%s]\n", line);
572 : :
573 : 4 : ret = parser(line, &rule_params);
574 [ - + ]: 4 : if (ret != 0) {
575 : 0 : fprintf(stderr,
576 : : "line %u: parse rule failed, error code: %d (%s)\n",
577 : : n, ret, strerror(-ret));
578 : 0 : return ret;
579 : : }
580 : :
581 : : delete_params = (struct
582 : : rte_pipeline_table_acl_rule_delete_params *)
583 : : &(rule_params.field_value[0]);
584 : 4 : ret = rte_pipeline_table_entry_delete(p, table_id[i],
585 : : delete_params, &key_found, NULL);
586 [ - + ]: 4 : if (ret < 0) {
587 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
588 : : table_id[i], ret);
589 : : goto fail;
590 : : } else
591 : : printf("Deleted Rule.\n");
592 : : }
593 : :
594 : :
595 : : /* Try to add duplicates */
596 [ + + ]: 12 : for (n = 1; n <= 5; n++) {
597 : 10 : strlcpy(line, lines[n - 1], sizeof(line));
598 : : printf("PARSING [%s]\n", line);
599 : :
600 : 10 : ret = parser(line, &rule_params);
601 [ - + ]: 10 : if (ret != 0) {
602 : 0 : fprintf(stderr,
603 : : "line %u: parse rule failed, error code: %d (%s)\n",
604 : : n, ret, strerror(-ret));
605 : 0 : return ret;
606 : : }
607 : :
608 : 10 : rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
609 : :
610 : 10 : ret = rte_pipeline_table_entry_add(p, table_id[i],
611 : : &rule_params,
612 : : &table_entry, &key_found, &entry_ptr);
613 [ - + ]: 10 : if (ret < 0) {
614 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
615 : : table_id[i], ret);
616 : : goto fail;
617 : : }
618 : : }
619 : : }
620 : :
621 : : /* Enable input ports */
622 [ + + ]: 3 : for (i = 0; i < N_PORTS ; i++)
623 [ - + ]: 2 : if (rte_pipeline_port_in_enable(p, port_in_id[i]))
624 : 0 : rte_panic("Unable to enable input port %u\n",
625 : : port_in_id[i]);
626 : :
627 : : /* Check pipeline consistency */
628 [ - + ]: 1 : if (rte_pipeline_check(p) < 0) {
629 : 0 : rte_panic("Pipeline consistency check failed\n");
630 : : goto fail;
631 : : }
632 : :
633 : : return 0;
634 : : fail:
635 : :
636 : 0 : return -1;
637 : : }
638 : :
639 : : static int
640 : 1 : test_pipeline_single_filter(int expected_count)
641 : : {
642 : : int i, j, ret, tx_count;
643 : : struct ipv4_5tuple five_tuple;
644 : :
645 : : /* Allocate a few mbufs and manually insert into the rings. */
646 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
647 [ + + ]: 18 : for (j = 0; j < 8; j++) {
648 : : struct rte_mbuf *mbuf;
649 : :
650 : 16 : mbuf = rte_pktmbuf_alloc(pool);
651 [ + - ]: 16 : if (mbuf == NULL)
652 : : /* this will cause test failure after cleanup
653 : : * of already enqueued mbufs, as the mbuf
654 : : * counts won't match */
655 : : break;
656 [ - + ]: 16 : memset(rte_pktmbuf_mtod(mbuf, char *), 0x00,
657 : : sizeof(struct ipv4_5tuple));
658 : :
659 : 16 : five_tuple.proto = j;
660 [ - + ]: 16 : five_tuple.ip_src = rte_bswap32(RTE_IPV4(192, 168, j, 1));
661 [ - + ]: 16 : five_tuple.ip_dst = rte_bswap32(RTE_IPV4(10, 4, j, 1));
662 [ - + ]: 16 : five_tuple.port_src = rte_bswap16(100 + j);
663 [ - + ]: 16 : five_tuple.port_dst = rte_bswap16(200 + j);
664 : :
665 : 16 : memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple,
666 : : sizeof(struct ipv4_5tuple));
667 : : printf("%s: Enqueue onto ring %d\n",
668 : : __func__, i);
669 [ - + - - : 32 : rte_ring_enqueue(rings_rx[i], mbuf);
- ]
670 : : }
671 : : }
672 : :
673 : : /* Run pipeline once */
674 [ + + ]: 3 : for (i = 0; i< N_PORTS; i++)
675 : 2 : rte_pipeline_run(p);
676 : :
677 : 1 : rte_pipeline_flush(p);
678 : :
679 : : tx_count = 0;
680 : :
681 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
682 : : void *objs[RING_TX_SIZE];
683 : : struct rte_mbuf *mbuf;
684 : :
685 : 2 : ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
686 [ - + ]: 2 : if (ret <= 0) {
687 : : printf("Got no objects from ring %d - error code %d\n",
688 : : i, ret);
689 : : } else {
690 : : printf("Got %d object(s) from ring %d!\n", ret, i);
691 [ + + ]: 12 : for (j = 0; j < ret; j++) {
692 : 10 : mbuf = objs[j];
693 : 10 : rte_hexdump(stdout, "mbuf",
694 : 10 : rte_pktmbuf_mtod(mbuf, char *), 64);
695 : 10 : rte_pktmbuf_free(mbuf);
696 : : }
697 : 2 : tx_count += ret;
698 : : }
699 : : }
700 : :
701 [ - + ]: 1 : if (tx_count != expected_count) {
702 : 0 : fprintf(stderr,
703 : : "%s: Unexpected packets for ACL test, expected %d, got %d\n",
704 : : __func__, expected_count, tx_count);
705 : 0 : goto fail;
706 : : }
707 : :
708 : 1 : rte_pipeline_free(p);
709 : :
710 : 1 : return 0;
711 : : fail:
712 : 0 : return -1;
713 : :
714 : : }
715 : :
716 : : int
717 : 1 : test_table_acl(void)
718 : : {
719 : :
720 : :
721 : 1 : override_hit_mask = 0xFF; /* All packets are a hit */
722 : :
723 : 1 : setup_acl_pipeline();
724 [ - + ]: 1 : if (test_pipeline_single_filter(10) < 0)
725 : 0 : return -1;
726 : :
727 : : return 0;
728 : : }
729 : :
730 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
|