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