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