fix ethdev port id validation
[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_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 }