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