New upstream version 18.08
[deb_dpdk.git] / examples / ip_pipeline / pipeline.c
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 }