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