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