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 : : static int
316 : 1 : setup_acl_pipeline(void)
317 : : {
318 : : int ret;
319 : : int i;
320 : 1 : struct rte_pipeline_params pipeline_params = {
321 : : .name = "PIPELINE",
322 : : .socket_id = 0,
323 : : };
324 : : uint32_t n;
325 : : struct rte_table_acl_rule_add_params rule_params;
326 : : struct rte_pipeline_table_acl_rule_delete_params *delete_params;
327 : : parse_5tuple parser;
328 : : char acl_name[64];
329 : :
330 : : /*
331 : : * The format for these rules DO NOT need the port ranges to be
332 : : * separated by ' : ', just ':'. It's a lot more readable and
333 : : * cleaner, IMO.
334 : : */
335 : : static const char * const lines[] = {
336 : : "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
337 : : "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP check */
338 : : "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
339 : : "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
340 : : "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
341 : : };
342 : : char line[LINE_MAX];
343 : :
344 : : /* Pipeline configuration */
345 : 1 : p = rte_pipeline_create(&pipeline_params);
346 [ - + ]: 1 : if (p == NULL) {
347 : 0 : fprintf(stderr, "%s: Failed to configure pipeline\n",
348 : : __func__);
349 : 0 : goto fail;
350 : : }
351 : :
352 : : /* Input port configuration */
353 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
354 : 2 : struct rte_port_ring_reader_params port_ring_params = {
355 : 2 : .ring = rings_rx[i],
356 : : };
357 : :
358 : 2 : struct rte_pipeline_port_in_params port_params = {
359 : : .ops = &rte_port_ring_reader_ops,
360 : : .arg_create = (void *) &port_ring_params,
361 : : .f_action = NULL,
362 : : .burst_size = BURST_SIZE,
363 : : };
364 : :
365 : : /* Put in action for some ports */
366 [ + + ]: 2 : if (i)
367 : 1 : port_params.f_action = port_in_action;
368 : :
369 : 2 : ret = rte_pipeline_port_in_create(p, &port_params,
370 : : &port_in_id[i]);
371 [ - + ]: 2 : if (ret) {
372 : 0 : rte_panic("Unable to configure input port %d, ret:%d\n",
373 : : i, ret);
374 : : goto fail;
375 : : }
376 : : }
377 : :
378 : : /* output Port configuration */
379 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
380 : 2 : struct rte_port_ring_writer_params port_ring_params = {
381 : 2 : .ring = rings_tx[i],
382 : : .tx_burst_sz = BURST_SIZE,
383 : : };
384 : :
385 : 2 : struct rte_pipeline_port_out_params port_params = {
386 : : .ops = &rte_port_ring_writer_ops,
387 : : .arg_create = (void *) &port_ring_params,
388 : : .f_action = NULL,
389 : : .arg_ah = NULL,
390 : : };
391 : :
392 : :
393 [ - + ]: 2 : if (rte_pipeline_port_out_create(p, &port_params,
394 : : &port_out_id[i])) {
395 : 0 : rte_panic("Unable to configure output port %d\n", i);
396 : : goto fail;
397 : : }
398 : : }
399 : :
400 : : /* Table configuration */
401 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
402 : : struct rte_pipeline_table_params table_params;
403 : :
404 : : /* Set up defaults for stub */
405 : 2 : table_params.ops = &rte_table_stub_ops;
406 : 2 : table_params.arg_create = NULL;
407 : 2 : table_params.f_action_hit = action_handler_hit;
408 : 2 : table_params.f_action_miss = NULL;
409 : 2 : table_params.action_data_size = 0;
410 : :
411 : 2 : printf("miss_action=%x\n",
412 : : table_entry_miss_action);
413 : :
414 : : printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
415 : : RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
416 : :
417 : : struct rte_table_acl_params acl_params;
418 : :
419 : 2 : acl_params.n_rules = 1 << 5;
420 : 2 : acl_params.n_rule_fields = DIM(ipv4_defs);
421 : : snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
422 : 2 : acl_params.name = acl_name;
423 : : memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
424 : :
425 : 2 : table_params.ops = &rte_table_acl_ops;
426 : 2 : table_params.arg_create = &acl_params;
427 : :
428 [ - + ]: 2 : if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
429 : 0 : rte_panic("Unable to configure table %u\n", i);
430 : : goto fail;
431 : : }
432 : :
433 [ - + ]: 2 : if (connect_miss_action_to_table) {
434 [ # # ]: 0 : if (rte_pipeline_table_create(p, &table_params,
435 : 0 : &table_id[i+2])) {
436 : 0 : rte_panic("Unable to configure table %u\n", i);
437 : : goto fail;
438 : : }
439 : : }
440 : : }
441 : :
442 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
443 [ - + ]: 2 : if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
444 : : table_id[i])) {
445 : 0 : rte_panic("Unable to connect input port %u to "
446 : : "table %u\n",
447 : : port_in_id[i], table_id[i]);
448 : : goto fail;
449 : : }
450 : : }
451 : :
452 : : /* Add bulk entries to tables */
453 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
454 : : struct rte_table_acl_rule_add_params keys[5];
455 : : struct rte_pipeline_table_entry entries[5];
456 : : struct rte_table_acl_rule_add_params *key_array[5];
457 : : struct rte_pipeline_table_entry *table_entries[5];
458 : : int key_found[5];
459 : : struct rte_pipeline_table_entry *table_entries_ptr[5];
460 : : struct rte_pipeline_table_entry entries_ptr[5];
461 : :
462 : : parser = parse_cb_ipv4_rule;
463 [ + + ]: 12 : for (n = 0; n < 5; n++) {
464 : 10 : memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
465 : 10 : key_array[n] = &keys[n];
466 : :
467 : 10 : strlcpy(line, lines[n], sizeof(line));
468 : : printf("PARSING [%s]\n", line);
469 : :
470 : 10 : ret = parser(line, &keys[n]);
471 [ - + ]: 10 : if (ret != 0) {
472 : 0 : fprintf(stderr,
473 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
474 : : n, ret, strerror(-ret));
475 : 0 : return ret;
476 : : }
477 : :
478 : 10 : keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
479 : :
480 : 10 : entries[n].action = RTE_PIPELINE_ACTION_PORT;
481 : 10 : entries[n].port_id = port_out_id[i^1];
482 : 10 : table_entries[n] = &entries[n];
483 : 10 : table_entries_ptr[n] = &entries_ptr[n];
484 : : }
485 : :
486 : 2 : ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
487 : : (void **)key_array, table_entries, 5, key_found, table_entries_ptr);
488 [ - + ]: 2 : if (ret < 0) {
489 : 0 : rte_panic("Add entry bulk to table %u failed (%d)\n",
490 : : table_id[i], ret);
491 : : goto fail;
492 : : }
493 : : }
494 : :
495 : : /* Delete bulk entries from tables */
496 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
497 : : struct rte_table_acl_rule_delete_params keys[5];
498 : : struct rte_table_acl_rule_delete_params *key_array[5];
499 : : struct rte_pipeline_table_entry *table_entries[5];
500 : : int key_found[5];
501 : :
502 : : memset(table_entries, 0, sizeof(table_entries));
503 : :
504 [ + + ]: 12 : for (n = 0; n < 5; n++) {
505 : 10 : memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
506 : 10 : key_array[n] = &keys[n];
507 : :
508 : 10 : strlcpy(line, lines[n], sizeof(line));
509 : : printf("PARSING [%s]\n", line);
510 : :
511 : 10 : ret = parse_cb_ipv4_rule_del(line, &keys[n]);
512 [ - + ]: 10 : if (ret != 0) {
513 : 0 : fprintf(stderr,
514 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
515 : : n, ret, strerror(-ret));
516 : 0 : return ret;
517 : : }
518 : : }
519 : :
520 : 2 : ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
521 : : (void **)key_array, 5, key_found, table_entries);
522 [ - + ]: 2 : if (ret < 0) {
523 : 0 : rte_panic("Delete bulk entries from table %u failed (%d)\n",
524 : : table_id[i], ret);
525 : : goto fail;
526 : : } else
527 : : printf("Bulk deleted rules.\n");
528 : : }
529 : :
530 : : /* Add entries to tables */
531 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
532 : 2 : struct rte_pipeline_table_entry table_entry = {
533 : : .action = RTE_PIPELINE_ACTION_PORT,
534 : 2 : {.port_id = port_out_id[i^1]},
535 : : };
536 : : int key_found;
537 : : struct rte_pipeline_table_entry *entry_ptr;
538 : :
539 : : memset(&rule_params, 0, sizeof(rule_params));
540 : : parser = parse_cb_ipv4_rule;
541 : :
542 [ + + ]: 12 : for (n = 1; n <= 5; n++) {
543 : 10 : strlcpy(line, lines[n - 1], sizeof(line));
544 : : printf("PARSING [%s]\n", line);
545 : :
546 : 10 : ret = parser(line, &rule_params);
547 [ - + ]: 10 : if (ret != 0) {
548 : 0 : fprintf(stderr,
549 : : "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
550 : : n, ret, strerror(-ret));
551 : 0 : return ret;
552 : : }
553 : :
554 : 10 : rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
555 : :
556 : 10 : ret = rte_pipeline_table_entry_add(p, table_id[i],
557 : : &rule_params,
558 : : &table_entry, &key_found, &entry_ptr);
559 [ - + ]: 10 : if (ret < 0) {
560 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
561 : : table_id[i], ret);
562 : : goto fail;
563 : : }
564 : : }
565 : :
566 : : /* delete a few rules */
567 [ + + ]: 6 : for (n = 2; n <= 3; n++) {
568 : 4 : strlcpy(line, lines[n - 1], sizeof(line));
569 : : printf("PARSING [%s]\n", line);
570 : :
571 : 4 : ret = parser(line, &rule_params);
572 [ - + ]: 4 : if (ret != 0) {
573 : 0 : fprintf(stderr,
574 : : "line %u: parse rule failed, error code: %d (%s)\n",
575 : : n, ret, strerror(-ret));
576 : 0 : return ret;
577 : : }
578 : :
579 : : delete_params = (struct
580 : : rte_pipeline_table_acl_rule_delete_params *)
581 : : &(rule_params.field_value[0]);
582 : 4 : ret = rte_pipeline_table_entry_delete(p, table_id[i],
583 : : delete_params, &key_found, NULL);
584 [ - + ]: 4 : if (ret < 0) {
585 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
586 : : table_id[i], ret);
587 : : goto fail;
588 : : } else
589 : : printf("Deleted Rule.\n");
590 : : }
591 : :
592 : :
593 : : /* Try to add duplicates */
594 [ + + ]: 12 : for (n = 1; n <= 5; n++) {
595 : 10 : strlcpy(line, lines[n - 1], sizeof(line));
596 : : printf("PARSING [%s]\n", line);
597 : :
598 : 10 : ret = parser(line, &rule_params);
599 [ - + ]: 10 : if (ret != 0) {
600 : 0 : fprintf(stderr,
601 : : "line %u: parse rule failed, error code: %d (%s)\n",
602 : : n, ret, strerror(-ret));
603 : 0 : return ret;
604 : : }
605 : :
606 : 10 : rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
607 : :
608 : 10 : ret = rte_pipeline_table_entry_add(p, table_id[i],
609 : : &rule_params,
610 : : &table_entry, &key_found, &entry_ptr);
611 [ - + ]: 10 : if (ret < 0) {
612 : 0 : rte_panic("Add entry to table %u failed (%d)\n",
613 : : table_id[i], ret);
614 : : goto fail;
615 : : }
616 : : }
617 : : }
618 : :
619 : : /* Enable input ports */
620 [ + + ]: 3 : for (i = 0; i < N_PORTS ; i++)
621 [ - + ]: 2 : if (rte_pipeline_port_in_enable(p, port_in_id[i]))
622 : 0 : rte_panic("Unable to enable input port %u\n",
623 : : port_in_id[i]);
624 : :
625 : : /* Check pipeline consistency */
626 [ - + ]: 1 : if (rte_pipeline_check(p) < 0) {
627 : 0 : rte_panic("Pipeline consistency check failed\n");
628 : : goto fail;
629 : : }
630 : :
631 : : return 0;
632 : : fail:
633 : :
634 : 0 : return -1;
635 : : }
636 : :
637 : : static int
638 : 1 : test_pipeline_single_filter(int expected_count)
639 : : {
640 : : int i, j, ret, tx_count;
641 : : struct ipv4_5tuple five_tuple;
642 : :
643 : : /* Allocate a few mbufs and manually insert into the rings. */
644 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
645 [ + + ]: 18 : for (j = 0; j < 8; j++) {
646 : : struct rte_mbuf *mbuf;
647 : :
648 : 16 : mbuf = rte_pktmbuf_alloc(pool);
649 [ + - ]: 16 : if (mbuf == NULL)
650 : : /* this will cause test failure after cleanup
651 : : * of already enqueued mbufs, as the mbuf
652 : : * counts won't match */
653 : : break;
654 [ - + ]: 16 : memset(rte_pktmbuf_mtod(mbuf, char *), 0x00,
655 : : sizeof(struct ipv4_5tuple));
656 : :
657 : 16 : five_tuple.proto = j;
658 [ - + ]: 16 : five_tuple.ip_src = rte_bswap32(RTE_IPV4(192, 168, j, 1));
659 [ - + ]: 16 : five_tuple.ip_dst = rte_bswap32(RTE_IPV4(10, 4, j, 1));
660 [ - + ]: 16 : five_tuple.port_src = rte_bswap16(100 + j);
661 [ - + ]: 16 : five_tuple.port_dst = rte_bswap16(200 + j);
662 : :
663 : 16 : memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple,
664 : : sizeof(struct ipv4_5tuple));
665 : : printf("%s: Enqueue onto ring %d\n",
666 : : __func__, i);
667 [ - + - - : 32 : rte_ring_enqueue(rings_rx[i], mbuf);
- ]
668 : : }
669 : : }
670 : :
671 : : /* Run pipeline once */
672 [ + + ]: 3 : for (i = 0; i< N_PORTS; i++)
673 : 2 : rte_pipeline_run(p);
674 : :
675 : 1 : rte_pipeline_flush(p);
676 : :
677 : : tx_count = 0;
678 : :
679 [ + + ]: 3 : for (i = 0; i < N_PORTS; i++) {
680 : : void *objs[RING_TX_SIZE];
681 : : struct rte_mbuf *mbuf;
682 : :
683 : 2 : ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
684 [ - + ]: 2 : if (ret <= 0) {
685 : : printf("Got no objects from ring %d - error code %d\n",
686 : : i, ret);
687 : : } else {
688 : : printf("Got %d object(s) from ring %d!\n", ret, i);
689 [ + + ]: 12 : for (j = 0; j < ret; j++) {
690 : 10 : mbuf = objs[j];
691 : 10 : rte_hexdump(stdout, "mbuf",
692 : 10 : rte_pktmbuf_mtod(mbuf, char *), 64);
693 : 10 : rte_pktmbuf_free(mbuf);
694 : : }
695 : 2 : tx_count += ret;
696 : : }
697 : : }
698 : :
699 [ - + ]: 1 : if (tx_count != expected_count) {
700 : 0 : fprintf(stderr,
701 : : "%s: Unexpected packets for ACL test, expected %d, got %d\n",
702 : : __func__, expected_count, tx_count);
703 : 0 : goto fail;
704 : : }
705 : :
706 : 1 : rte_pipeline_free(p);
707 : :
708 : 1 : return 0;
709 : : fail:
710 : 0 : return -1;
711 : :
712 : : }
713 : :
714 : : int
715 : 1 : test_table_acl(void)
716 : : {
717 : :
718 : :
719 : 1 : override_hit_mask = 0xFF; /* All packets are a hit */
720 : :
721 : 1 : setup_acl_pipeline();
722 [ - + ]: 1 : if (test_pipeline_single_filter(10) < 0)
723 : 0 : return -1;
724 : :
725 : : return 0;
726 : : }
727 : :
728 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
|