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