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