xref: /dpdk/examples/ip_pipeline/pipeline.c (revision 169a9da64a859e1782e49886e7214982304a580f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4 
5 #include <stdlib.h>
6 #include <string.h>
7 
8 #include <rte_common.h>
9 #include <rte_ip.h>
10 #include <rte_tcp.h>
11 
12 #include <rte_string_fns.h>
13 #include <rte_port_ethdev.h>
14 #ifdef RTE_LIBRTE_KNI
15 #include <rte_port_kni.h>
16 #endif
17 #include <rte_port_ring.h>
18 #include <rte_port_source_sink.h>
19 #include <rte_port_fd.h>
20 #include <rte_port_sched.h>
21 
22 #include <rte_table_acl.h>
23 #include <rte_table_array.h>
24 #include <rte_table_hash.h>
25 #include <rte_table_lpm.h>
26 #include <rte_table_lpm_ipv6.h>
27 #include <rte_table_stub.h>
28 
29 #ifdef RTE_LIBRTE_KNI
30 #include "kni.h"
31 #endif
32 #include "link.h"
33 #include "mempool.h"
34 #include "pipeline.h"
35 #include "tap.h"
36 #include "tmgr.h"
37 #include "swq.h"
38 
39 #include "hash_func.h"
40 
41 #ifndef PIPELINE_MSGQ_SIZE
42 #define PIPELINE_MSGQ_SIZE                                 64
43 #endif
44 
45 #ifndef TABLE_LPM_NUMBER_TBL8
46 #define TABLE_LPM_NUMBER_TBL8                              256
47 #endif
48 
49 static struct pipeline_list pipeline_list;
50 
51 int
52 pipeline_init(void)
53 {
54 	TAILQ_INIT(&pipeline_list);
55 
56 	return 0;
57 }
58 
59 struct pipeline *
60 pipeline_find(const char *name)
61 {
62 	struct pipeline *pipeline;
63 
64 	if (name == NULL)
65 		return NULL;
66 
67 	TAILQ_FOREACH(pipeline, &pipeline_list, node)
68 		if (strcmp(name, pipeline->name) == 0)
69 			return pipeline;
70 
71 	return NULL;
72 }
73 
74 struct pipeline *
75 pipeline_create(const char *name, struct pipeline_params *params)
76 {
77 	char msgq_name[NAME_MAX];
78 	struct rte_pipeline_params pp;
79 	struct pipeline *pipeline;
80 	struct rte_pipeline *p;
81 	struct rte_ring *msgq_req;
82 	struct rte_ring *msgq_rsp;
83 
84 	/* Check input params */
85 	if ((name == NULL) ||
86 		pipeline_find(name) ||
87 		(params == NULL) ||
88 		(params->timer_period_ms == 0))
89 		return NULL;
90 
91 	/* Resource create */
92 	snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-REQ", name);
93 
94 	msgq_req = rte_ring_create(msgq_name,
95 		PIPELINE_MSGQ_SIZE,
96 		params->cpu_id,
97 		RING_F_SP_ENQ | RING_F_SC_DEQ);
98 	if (msgq_req == NULL)
99 		return NULL;
100 
101 	snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-RSP", name);
102 
103 	msgq_rsp = rte_ring_create(msgq_name,
104 		PIPELINE_MSGQ_SIZE,
105 		params->cpu_id,
106 		RING_F_SP_ENQ | RING_F_SC_DEQ);
107 	if (msgq_rsp == NULL) {
108 		rte_ring_free(msgq_req);
109 		return NULL;
110 	}
111 
112 	pp.name = name;
113 	pp.socket_id = (int) params->cpu_id;
114 	pp.offset_port_id = params->offset_port_id;
115 
116 	p = rte_pipeline_create(&pp);
117 	if (p == NULL) {
118 		rte_ring_free(msgq_rsp);
119 		rte_ring_free(msgq_req);
120 		return NULL;
121 	}
122 
123 	/* Node allocation */
124 	pipeline = calloc(1, sizeof(struct pipeline));
125 	if (pipeline == NULL) {
126 		rte_pipeline_free(p);
127 		rte_ring_free(msgq_rsp);
128 		rte_ring_free(msgq_req);
129 		return NULL;
130 	}
131 
132 	/* Node fill in */
133 	strlcpy(pipeline->name, name, sizeof(pipeline->name));
134 	pipeline->p = p;
135 	pipeline->n_ports_in = 0;
136 	pipeline->n_ports_out = 0;
137 	pipeline->n_tables = 0;
138 	pipeline->msgq_req = msgq_req;
139 	pipeline->msgq_rsp = msgq_rsp;
140 	pipeline->timer_period_ms = params->timer_period_ms;
141 	pipeline->enabled = 0;
142 	pipeline->cpu_id = params->cpu_id;
143 
144 	/* Node add to list */
145 	TAILQ_INSERT_TAIL(&pipeline_list, pipeline, node);
146 
147 	return pipeline;
148 }
149 
150 int
151 pipeline_port_in_create(const char *pipeline_name,
152 	struct port_in_params *params,
153 	int enabled)
154 {
155 	struct rte_pipeline_port_in_params p;
156 
157 	union {
158 		struct rte_port_ethdev_reader_params ethdev;
159 		struct rte_port_ring_reader_params ring;
160 		struct rte_port_sched_reader_params sched;
161 		struct rte_port_fd_reader_params fd;
162 #ifdef RTE_LIBRTE_KNI
163 		struct rte_port_kni_reader_params kni;
164 #endif
165 		struct rte_port_source_params source;
166 	} pp;
167 
168 	struct pipeline *pipeline;
169 	struct port_in *port_in;
170 	struct port_in_action_profile *ap;
171 	struct rte_port_in_action *action;
172 	uint32_t port_id;
173 	int status;
174 
175 	memset(&p, 0, sizeof(p));
176 	memset(&pp, 0, sizeof(pp));
177 
178 	/* Check input params */
179 	if ((pipeline_name == NULL) ||
180 		(params == NULL) ||
181 		(params->burst_size == 0) ||
182 		(params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
183 		return -1;
184 
185 	pipeline = pipeline_find(pipeline_name);
186 	if (pipeline == NULL)
187 		return -1;
188 
189 	ap = NULL;
190 	if (params->action_profile_name) {
191 		ap = port_in_action_profile_find(params->action_profile_name);
192 		if (ap == NULL)
193 			return -1;
194 	}
195 
196 	switch (params->type) {
197 	case PORT_IN_RXQ:
198 	{
199 		struct link *link;
200 
201 		link = link_find(params->dev_name);
202 		if (link == NULL)
203 			return -1;
204 
205 		if (params->rxq.queue_id >= link->n_rxq)
206 			return -1;
207 
208 		pp.ethdev.port_id = link->port_id;
209 		pp.ethdev.queue_id = params->rxq.queue_id;
210 
211 		p.ops = &rte_port_ethdev_reader_ops;
212 		p.arg_create = &pp.ethdev;
213 		break;
214 	}
215 
216 	case PORT_IN_SWQ:
217 	{
218 		struct swq *swq;
219 
220 		swq = swq_find(params->dev_name);
221 		if (swq == NULL)
222 			return -1;
223 
224 		pp.ring.ring = swq->r;
225 
226 		p.ops = &rte_port_ring_reader_ops;
227 		p.arg_create = &pp.ring;
228 		break;
229 	}
230 
231 	case PORT_IN_TMGR:
232 	{
233 		struct tmgr_port *tmgr_port;
234 
235 		tmgr_port = tmgr_port_find(params->dev_name);
236 		if (tmgr_port == NULL)
237 			return -1;
238 
239 		pp.sched.sched = tmgr_port->s;
240 
241 		p.ops = &rte_port_sched_reader_ops;
242 		p.arg_create = &pp.sched;
243 		break;
244 	}
245 
246 	case PORT_IN_TAP:
247 	{
248 		struct tap *tap;
249 		struct mempool *mempool;
250 
251 		tap = tap_find(params->dev_name);
252 		mempool = mempool_find(params->tap.mempool_name);
253 		if ((tap == NULL) || (mempool == NULL))
254 			return -1;
255 
256 		pp.fd.fd = tap->fd;
257 		pp.fd.mempool = mempool->m;
258 		pp.fd.mtu = params->tap.mtu;
259 
260 		p.ops = &rte_port_fd_reader_ops;
261 		p.arg_create = &pp.fd;
262 		break;
263 	}
264 
265 #ifdef RTE_LIBRTE_KNI
266 	case PORT_IN_KNI:
267 	{
268 		struct kni *kni;
269 
270 		kni = kni_find(params->dev_name);
271 		if (kni == NULL)
272 			return -1;
273 
274 		pp.kni.kni = kni->k;
275 
276 		p.ops = &rte_port_kni_reader_ops;
277 		p.arg_create = &pp.kni;
278 		break;
279 	}
280 #endif
281 
282 	case PORT_IN_SOURCE:
283 	{
284 		struct mempool *mempool;
285 
286 		mempool = mempool_find(params->source.mempool_name);
287 		if (mempool == NULL)
288 			return -1;
289 
290 		pp.source.mempool = mempool->m;
291 		pp.source.file_name = params->source.file_name;
292 		pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt;
293 
294 		p.ops = &rte_port_source_ops;
295 		p.arg_create = &pp.source;
296 		break;
297 	}
298 
299 	default:
300 		return -1;
301 	}
302 
303 	p.burst_size = params->burst_size;
304 
305 	/* Resource create */
306 	action = NULL;
307 	p.f_action = NULL;
308 	p.arg_ah = NULL;
309 
310 	if (ap) {
311 		action = rte_port_in_action_create(ap->ap,
312 			pipeline->cpu_id);
313 		if (action == NULL)
314 			return -1;
315 
316 		status = rte_port_in_action_params_get(
317 			action,
318 			&p);
319 		if (status) {
320 			rte_port_in_action_free(action);
321 			return -1;
322 		}
323 	}
324 
325 	status = rte_pipeline_port_in_create(pipeline->p,
326 		&p,
327 		&port_id);
328 	if (status) {
329 		rte_port_in_action_free(action);
330 		return -1;
331 	}
332 
333 	if (enabled)
334 		rte_pipeline_port_in_enable(pipeline->p, port_id);
335 
336 	/* Pipeline */
337 	port_in = &pipeline->port_in[pipeline->n_ports_in];
338 	memcpy(&port_in->params, params, sizeof(*params));
339 	port_in->ap = ap;
340 	port_in->a = action;
341 	pipeline->n_ports_in++;
342 
343 	return 0;
344 }
345 
346 int
347 pipeline_port_in_connect_to_table(const char *pipeline_name,
348 	uint32_t port_id,
349 	uint32_t table_id)
350 {
351 	struct pipeline *pipeline;
352 	int status;
353 
354 	/* Check input params */
355 	if (pipeline_name == NULL)
356 		return -1;
357 
358 	pipeline = pipeline_find(pipeline_name);
359 	if ((pipeline == NULL) ||
360 		(port_id >= pipeline->n_ports_in) ||
361 		(table_id >= pipeline->n_tables))
362 		return -1;
363 
364 	/* Resource */
365 	status = rte_pipeline_port_in_connect_to_table(pipeline->p,
366 		port_id,
367 		table_id);
368 
369 	return status;
370 
371 }
372 
373 int
374 pipeline_port_out_create(const char *pipeline_name,
375 	struct port_out_params *params)
376 {
377 	struct rte_pipeline_port_out_params p;
378 
379 	union {
380 		struct rte_port_ethdev_writer_params ethdev;
381 		struct rte_port_ring_writer_params ring;
382 		struct rte_port_sched_writer_params sched;
383 		struct rte_port_fd_writer_params fd;
384 #ifdef RTE_LIBRTE_KNI
385 		struct rte_port_kni_writer_params kni;
386 #endif
387 		struct rte_port_sink_params sink;
388 	} pp;
389 
390 	union {
391 		struct rte_port_ethdev_writer_nodrop_params ethdev;
392 		struct rte_port_ring_writer_nodrop_params ring;
393 		struct rte_port_fd_writer_nodrop_params fd;
394 #ifdef RTE_LIBRTE_KNI
395 		struct rte_port_kni_writer_nodrop_params kni;
396 #endif
397 	} pp_nodrop;
398 
399 	struct pipeline *pipeline;
400 	uint32_t port_id;
401 	int status;
402 
403 	memset(&p, 0, sizeof(p));
404 	memset(&pp, 0, sizeof(pp));
405 	memset(&pp_nodrop, 0, sizeof(pp_nodrop));
406 
407 	/* Check input params */
408 	if ((pipeline_name == NULL) ||
409 		(params == NULL) ||
410 		(params->burst_size == 0) ||
411 		(params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
412 		return -1;
413 
414 	pipeline = pipeline_find(pipeline_name);
415 	if (pipeline == NULL)
416 		return -1;
417 
418 	switch (params->type) {
419 	case PORT_OUT_TXQ:
420 	{
421 		struct link *link;
422 
423 		link = link_find(params->dev_name);
424 		if (link == NULL)
425 			return -1;
426 
427 		if (params->txq.queue_id >= link->n_txq)
428 			return -1;
429 
430 		pp.ethdev.port_id = link->port_id;
431 		pp.ethdev.queue_id = params->txq.queue_id;
432 		pp.ethdev.tx_burst_sz = params->burst_size;
433 
434 		pp_nodrop.ethdev.port_id = link->port_id;
435 		pp_nodrop.ethdev.queue_id = params->txq.queue_id;
436 		pp_nodrop.ethdev.tx_burst_sz = params->burst_size;
437 		pp_nodrop.ethdev.n_retries = params->n_retries;
438 
439 		if (params->retry == 0) {
440 			p.ops = &rte_port_ethdev_writer_ops;
441 			p.arg_create = &pp.ethdev;
442 		} else {
443 			p.ops = &rte_port_ethdev_writer_nodrop_ops;
444 			p.arg_create = &pp_nodrop.ethdev;
445 		}
446 		break;
447 	}
448 
449 	case PORT_OUT_SWQ:
450 	{
451 		struct swq *swq;
452 
453 		swq = swq_find(params->dev_name);
454 		if (swq == NULL)
455 			return -1;
456 
457 		pp.ring.ring = swq->r;
458 		pp.ring.tx_burst_sz = params->burst_size;
459 
460 		pp_nodrop.ring.ring = swq->r;
461 		pp_nodrop.ring.tx_burst_sz = params->burst_size;
462 		pp_nodrop.ring.n_retries = params->n_retries;
463 
464 		if (params->retry == 0) {
465 			p.ops = &rte_port_ring_writer_ops;
466 			p.arg_create = &pp.ring;
467 		} else {
468 			p.ops = &rte_port_ring_writer_nodrop_ops;
469 			p.arg_create = &pp_nodrop.ring;
470 		}
471 		break;
472 	}
473 
474 	case PORT_OUT_TMGR:
475 	{
476 		struct tmgr_port *tmgr_port;
477 
478 		tmgr_port = tmgr_port_find(params->dev_name);
479 		if (tmgr_port == NULL)
480 			return -1;
481 
482 		pp.sched.sched = tmgr_port->s;
483 		pp.sched.tx_burst_sz = params->burst_size;
484 
485 		p.ops = &rte_port_sched_writer_ops;
486 		p.arg_create = &pp.sched;
487 		break;
488 	}
489 
490 	case PORT_OUT_TAP:
491 	{
492 		struct tap *tap;
493 
494 		tap = tap_find(params->dev_name);
495 		if (tap == NULL)
496 			return -1;
497 
498 		pp.fd.fd = tap->fd;
499 		pp.fd.tx_burst_sz = params->burst_size;
500 
501 		pp_nodrop.fd.fd = tap->fd;
502 		pp_nodrop.fd.tx_burst_sz = params->burst_size;
503 		pp_nodrop.fd.n_retries = params->n_retries;
504 
505 		if (params->retry == 0) {
506 			p.ops = &rte_port_fd_writer_ops;
507 			p.arg_create = &pp.fd;
508 		} else {
509 			p.ops = &rte_port_fd_writer_nodrop_ops;
510 			p.arg_create = &pp_nodrop.fd;
511 		}
512 		break;
513 	}
514 
515 #ifdef RTE_LIBRTE_KNI
516 	case PORT_OUT_KNI:
517 	{
518 		struct kni *kni;
519 
520 		kni = kni_find(params->dev_name);
521 		if (kni == NULL)
522 			return -1;
523 
524 		pp.kni.kni = kni->k;
525 		pp.kni.tx_burst_sz = params->burst_size;
526 
527 		pp_nodrop.kni.kni = kni->k;
528 		pp_nodrop.kni.tx_burst_sz = params->burst_size;
529 		pp_nodrop.kni.n_retries = params->n_retries;
530 
531 		if (params->retry == 0) {
532 			p.ops = &rte_port_kni_writer_ops;
533 			p.arg_create = &pp.kni;
534 		} else {
535 			p.ops = &rte_port_kni_writer_nodrop_ops;
536 			p.arg_create = &pp_nodrop.kni;
537 		}
538 		break;
539 	}
540 #endif
541 
542 	case PORT_OUT_SINK:
543 	{
544 		pp.sink.file_name = params->sink.file_name;
545 		pp.sink.max_n_pkts = params->sink.max_n_pkts;
546 
547 		p.ops = &rte_port_sink_ops;
548 		p.arg_create = &pp.sink;
549 		break;
550 	}
551 
552 	default:
553 		return -1;
554 	}
555 
556 	p.f_action = NULL;
557 	p.arg_ah = NULL;
558 
559 	/* Resource create */
560 	status = rte_pipeline_port_out_create(pipeline->p,
561 		&p,
562 		&port_id);
563 
564 	if (status)
565 		return -1;
566 
567 	/* Pipeline */
568 	pipeline->n_ports_out++;
569 
570 	return 0;
571 }
572 
573 static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
574 	/* Protocol */
575 	[0] = {
576 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
577 		.size = sizeof(uint8_t),
578 		.field_index = 0,
579 		.input_index = 0,
580 		.offset = offsetof(struct ipv4_hdr, next_proto_id),
581 	},
582 
583 	/* Source IP address (IPv4) */
584 	[1] = {
585 		.type = RTE_ACL_FIELD_TYPE_MASK,
586 		.size = sizeof(uint32_t),
587 		.field_index = 1,
588 		.input_index = 1,
589 		.offset = offsetof(struct ipv4_hdr, src_addr),
590 	},
591 
592 	/* Destination IP address (IPv4) */
593 	[2] = {
594 		.type = RTE_ACL_FIELD_TYPE_MASK,
595 		.size = sizeof(uint32_t),
596 		.field_index = 2,
597 		.input_index = 2,
598 		.offset = offsetof(struct ipv4_hdr, dst_addr),
599 	},
600 
601 	/* Source Port */
602 	[3] = {
603 		.type = RTE_ACL_FIELD_TYPE_RANGE,
604 		.size = sizeof(uint16_t),
605 		.field_index = 3,
606 		.input_index = 3,
607 		.offset = sizeof(struct ipv4_hdr) +
608 			offsetof(struct tcp_hdr, src_port),
609 	},
610 
611 	/* Destination Port */
612 	[4] = {
613 		.type = RTE_ACL_FIELD_TYPE_RANGE,
614 		.size = sizeof(uint16_t),
615 		.field_index = 4,
616 		.input_index = 3,
617 		.offset = sizeof(struct ipv4_hdr) +
618 			offsetof(struct tcp_hdr, dst_port),
619 	},
620 };
621 
622 static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
623 	/* Protocol */
624 	[0] = {
625 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
626 		.size = sizeof(uint8_t),
627 		.field_index = 0,
628 		.input_index = 0,
629 		.offset = offsetof(struct ipv6_hdr, proto),
630 	},
631 
632 	/* Source IP address (IPv6) */
633 	[1] = {
634 		.type = RTE_ACL_FIELD_TYPE_MASK,
635 		.size = sizeof(uint32_t),
636 		.field_index = 1,
637 		.input_index = 1,
638 		.offset = offsetof(struct ipv6_hdr, src_addr[0]),
639 	},
640 
641 	[2] = {
642 		.type = RTE_ACL_FIELD_TYPE_MASK,
643 		.size = sizeof(uint32_t),
644 		.field_index = 2,
645 		.input_index = 2,
646 		.offset = offsetof(struct ipv6_hdr, src_addr[4]),
647 	},
648 
649 	[3] = {
650 		.type = RTE_ACL_FIELD_TYPE_MASK,
651 		.size = sizeof(uint32_t),
652 		.field_index = 3,
653 		.input_index = 3,
654 		.offset = offsetof(struct ipv6_hdr, src_addr[8]),
655 	},
656 
657 	[4] = {
658 		.type = RTE_ACL_FIELD_TYPE_MASK,
659 		.size = sizeof(uint32_t),
660 		.field_index = 4,
661 		.input_index = 4,
662 		.offset = offsetof(struct ipv6_hdr, src_addr[12]),
663 	},
664 
665 	/* Destination IP address (IPv6) */
666 	[5] = {
667 		.type = RTE_ACL_FIELD_TYPE_MASK,
668 		.size = sizeof(uint32_t),
669 		.field_index = 5,
670 		.input_index = 5,
671 		.offset = offsetof(struct ipv6_hdr, dst_addr[0]),
672 	},
673 
674 	[6] = {
675 		.type = RTE_ACL_FIELD_TYPE_MASK,
676 		.size = sizeof(uint32_t),
677 		.field_index = 6,
678 		.input_index = 6,
679 		.offset = offsetof(struct ipv6_hdr, dst_addr[4]),
680 	},
681 
682 	[7] = {
683 		.type = RTE_ACL_FIELD_TYPE_MASK,
684 		.size = sizeof(uint32_t),
685 		.field_index = 7,
686 		.input_index = 7,
687 		.offset = offsetof(struct ipv6_hdr, dst_addr[8]),
688 	},
689 
690 	[8] = {
691 		.type = RTE_ACL_FIELD_TYPE_MASK,
692 		.size = sizeof(uint32_t),
693 		.field_index = 8,
694 		.input_index = 8,
695 		.offset = offsetof(struct ipv6_hdr, dst_addr[12]),
696 	},
697 
698 	/* Source Port */
699 	[9] = {
700 		.type = RTE_ACL_FIELD_TYPE_RANGE,
701 		.size = sizeof(uint16_t),
702 		.field_index = 9,
703 		.input_index = 9,
704 		.offset = sizeof(struct ipv6_hdr) +
705 			offsetof(struct tcp_hdr, src_port),
706 	},
707 
708 	/* Destination Port */
709 	[10] = {
710 		.type = RTE_ACL_FIELD_TYPE_RANGE,
711 		.size = sizeof(uint16_t),
712 		.field_index = 10,
713 		.input_index = 9,
714 		.offset = sizeof(struct ipv6_hdr) +
715 			offsetof(struct tcp_hdr, dst_port),
716 	},
717 };
718 
719 int
720 pipeline_table_create(const char *pipeline_name,
721 	struct table_params *params)
722 {
723 	char name[NAME_MAX];
724 	struct rte_pipeline_table_params p;
725 
726 	union {
727 		struct rte_table_acl_params acl;
728 		struct rte_table_array_params array;
729 		struct rte_table_hash_params hash;
730 		struct rte_table_lpm_params lpm;
731 		struct rte_table_lpm_ipv6_params lpm_ipv6;
732 	} pp;
733 
734 	struct pipeline *pipeline;
735 	struct table *table;
736 	struct table_action_profile *ap;
737 	struct rte_table_action *action;
738 	uint32_t table_id;
739 	int status;
740 
741 	memset(&p, 0, sizeof(p));
742 	memset(&pp, 0, sizeof(pp));
743 
744 	/* Check input params */
745 	if ((pipeline_name == NULL) ||
746 		(params == NULL))
747 		return -1;
748 
749 	pipeline = pipeline_find(pipeline_name);
750 	if ((pipeline == NULL) ||
751 		(pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX))
752 		return -1;
753 
754 	ap = NULL;
755 	if (params->action_profile_name) {
756 		ap = table_action_profile_find(params->action_profile_name);
757 		if (ap == NULL)
758 			return -1;
759 	}
760 
761 	snprintf(name, NAME_MAX, "%s_table%u",
762 		pipeline_name, pipeline->n_tables);
763 
764 	switch (params->match_type) {
765 	case TABLE_ACL:
766 	{
767 		uint32_t ip_header_offset = params->match.acl.ip_header_offset -
768 			(sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
769 		uint32_t i;
770 
771 		if (params->match.acl.n_rules == 0)
772 			return -1;
773 
774 		pp.acl.name = name;
775 		pp.acl.n_rules = params->match.acl.n_rules;
776 		if (params->match.acl.ip_version) {
777 			memcpy(&pp.acl.field_format,
778 				&table_acl_field_format_ipv4,
779 				sizeof(table_acl_field_format_ipv4));
780 			pp.acl.n_rule_fields =
781 				RTE_DIM(table_acl_field_format_ipv4);
782 		} else {
783 			memcpy(&pp.acl.field_format,
784 				&table_acl_field_format_ipv6,
785 				sizeof(table_acl_field_format_ipv6));
786 			pp.acl.n_rule_fields =
787 				RTE_DIM(table_acl_field_format_ipv6);
788 		}
789 
790 		for (i = 0; i < pp.acl.n_rule_fields; i++)
791 			pp.acl.field_format[i].offset += ip_header_offset;
792 
793 		p.ops = &rte_table_acl_ops;
794 		p.arg_create = &pp.acl;
795 		break;
796 	}
797 
798 	case TABLE_ARRAY:
799 	{
800 		if (params->match.array.n_keys == 0)
801 			return -1;
802 
803 		pp.array.n_entries = params->match.array.n_keys;
804 		pp.array.offset = params->match.array.key_offset;
805 
806 		p.ops = &rte_table_array_ops;
807 		p.arg_create = &pp.array;
808 		break;
809 	}
810 
811 	case TABLE_HASH:
812 	{
813 		struct rte_table_ops *ops;
814 		rte_table_hash_op_hash f_hash;
815 
816 		if (params->match.hash.n_keys == 0)
817 			return -1;
818 
819 		switch (params->match.hash.key_size) {
820 		case  8:
821 			f_hash = hash_default_key8;
822 			break;
823 		case 16:
824 			f_hash = hash_default_key16;
825 			break;
826 		case 24:
827 			f_hash = hash_default_key24;
828 			break;
829 		case 32:
830 			f_hash = hash_default_key32;
831 			break;
832 		case 40:
833 			f_hash = hash_default_key40;
834 			break;
835 		case 48:
836 			f_hash = hash_default_key48;
837 			break;
838 		case 56:
839 			f_hash = hash_default_key56;
840 			break;
841 		case 64:
842 			f_hash = hash_default_key64;
843 			break;
844 		default:
845 			return -1;
846 		}
847 
848 		pp.hash.name = name;
849 		pp.hash.key_size = params->match.hash.key_size;
850 		pp.hash.key_offset = params->match.hash.key_offset;
851 		pp.hash.key_mask = params->match.hash.key_mask;
852 		pp.hash.n_keys = params->match.hash.n_keys;
853 		pp.hash.n_buckets = params->match.hash.n_buckets;
854 		pp.hash.f_hash = f_hash;
855 		pp.hash.seed = 0;
856 
857 		if (params->match.hash.extendable_bucket)
858 			switch (params->match.hash.key_size) {
859 			case  8:
860 				ops = &rte_table_hash_key8_ext_ops;
861 				break;
862 			case 16:
863 				ops = &rte_table_hash_key16_ext_ops;
864 				break;
865 			default:
866 				ops = &rte_table_hash_ext_ops;
867 			}
868 		else
869 			switch (params->match.hash.key_size) {
870 			case  8:
871 				ops = &rte_table_hash_key8_lru_ops;
872 				break;
873 			case 16:
874 				ops = &rte_table_hash_key16_lru_ops;
875 				break;
876 			default:
877 				ops = &rte_table_hash_lru_ops;
878 			}
879 
880 		p.ops = ops;
881 		p.arg_create = &pp.hash;
882 		break;
883 	}
884 
885 	case TABLE_LPM:
886 	{
887 		if (params->match.lpm.n_rules == 0)
888 			return -1;
889 
890 		switch (params->match.lpm.key_size) {
891 		case 4:
892 		{
893 			pp.lpm.name = name;
894 			pp.lpm.n_rules = params->match.lpm.n_rules;
895 			pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
896 			pp.lpm.flags = 0;
897 			pp.lpm.entry_unique_size = p.action_data_size +
898 				sizeof(struct rte_pipeline_table_entry);
899 			pp.lpm.offset = params->match.lpm.key_offset;
900 
901 			p.ops = &rte_table_lpm_ops;
902 			p.arg_create = &pp.lpm;
903 			break;
904 		}
905 
906 		case 16:
907 		{
908 			pp.lpm_ipv6.name = name;
909 			pp.lpm_ipv6.n_rules = params->match.lpm.n_rules;
910 			pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
911 			pp.lpm_ipv6.entry_unique_size = p.action_data_size +
912 				sizeof(struct rte_pipeline_table_entry);
913 			pp.lpm_ipv6.offset = params->match.lpm.key_offset;
914 
915 			p.ops = &rte_table_lpm_ipv6_ops;
916 			p.arg_create = &pp.lpm_ipv6;
917 			break;
918 		}
919 
920 		default:
921 			return -1;
922 		}
923 
924 		break;
925 	}
926 
927 	case TABLE_STUB:
928 	{
929 		p.ops = &rte_table_stub_ops;
930 		p.arg_create = NULL;
931 		break;
932 	}
933 
934 	default:
935 		return -1;
936 	}
937 
938 	/* Resource create */
939 	action = NULL;
940 	p.f_action_hit = NULL;
941 	p.f_action_miss = NULL;
942 	p.arg_ah = NULL;
943 
944 	if (ap) {
945 		action = rte_table_action_create(ap->ap,
946 			pipeline->cpu_id);
947 		if (action == NULL)
948 			return -1;
949 
950 		status = rte_table_action_table_params_get(
951 			action,
952 			&p);
953 		if (status ||
954 			((p.action_data_size +
955 			sizeof(struct rte_pipeline_table_entry)) >
956 			TABLE_RULE_ACTION_SIZE_MAX)) {
957 			rte_table_action_free(action);
958 			return -1;
959 		}
960 	}
961 
962 	if (params->match_type == TABLE_LPM) {
963 		if (params->match.lpm.key_size == 4)
964 			pp.lpm.entry_unique_size = p.action_data_size +
965 				sizeof(struct rte_pipeline_table_entry);
966 
967 		if (params->match.lpm.key_size == 16)
968 			pp.lpm_ipv6.entry_unique_size = p.action_data_size +
969 				sizeof(struct rte_pipeline_table_entry);
970 	}
971 
972 	status = rte_pipeline_table_create(pipeline->p,
973 		&p,
974 		&table_id);
975 	if (status) {
976 		rte_table_action_free(action);
977 		return -1;
978 	}
979 
980 	/* Pipeline */
981 	table = &pipeline->table[pipeline->n_tables];
982 	memcpy(&table->params, params, sizeof(*params));
983 	table->ap = ap;
984 	table->a = action;
985 	pipeline->n_tables++;
986 
987 	return 0;
988 }
989