1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
8 #include <rte_common.h>
12 #include <rte_port_ethdev.h>
14 #include <rte_port_kni.h>
16 #include <rte_port_ring.h>
17 #include <rte_port_source_sink.h>
18 #include <rte_port_fd.h>
19 #include <rte_port_sched.h>
21 #include <rte_table_acl.h>
22 #include <rte_table_array.h>
23 #include <rte_table_hash.h>
24 #include <rte_table_lpm.h>
25 #include <rte_table_lpm_ipv6.h>
26 #include <rte_table_stub.h>
38 #include "hash_func.h"
40 #ifndef PIPELINE_MSGQ_SIZE
41 #define PIPELINE_MSGQ_SIZE 64
44 #ifndef TABLE_LPM_NUMBER_TBL8
45 #define TABLE_LPM_NUMBER_TBL8 256
48 static struct pipeline_list pipeline_list;
53 TAILQ_INIT(&pipeline_list);
59 pipeline_find(const char *name)
61 struct pipeline *pipeline;
66 TAILQ_FOREACH(pipeline, &pipeline_list, node)
67 if (strcmp(name, pipeline->name) == 0)
74 pipeline_create(const char *name, struct pipeline_params *params)
76 char msgq_name[NAME_MAX];
77 struct rte_pipeline_params pp;
78 struct pipeline *pipeline;
79 struct rte_pipeline *p;
80 struct rte_ring *msgq_req;
81 struct rte_ring *msgq_rsp;
83 /* Check input params */
85 pipeline_find(name) ||
87 (params->timer_period_ms == 0))
91 snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-REQ", name);
93 msgq_req = rte_ring_create(msgq_name,
96 RING_F_SP_ENQ | RING_F_SC_DEQ);
100 snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-RSP", name);
102 msgq_rsp = rte_ring_create(msgq_name,
105 RING_F_SP_ENQ | RING_F_SC_DEQ);
106 if (msgq_rsp == NULL) {
107 rte_ring_free(msgq_req);
112 pp.socket_id = (int) params->cpu_id;
113 pp.offset_port_id = params->offset_port_id;
115 p = rte_pipeline_create(&pp);
117 rte_ring_free(msgq_rsp);
118 rte_ring_free(msgq_req);
122 /* Node allocation */
123 pipeline = calloc(1, sizeof(struct pipeline));
124 if (pipeline == NULL) {
125 rte_pipeline_free(p);
126 rte_ring_free(msgq_rsp);
127 rte_ring_free(msgq_req);
132 strncpy(pipeline->name, name, sizeof(pipeline->name));
134 pipeline->n_ports_in = 0;
135 pipeline->n_ports_out = 0;
136 pipeline->n_tables = 0;
137 pipeline->msgq_req = msgq_req;
138 pipeline->msgq_rsp = msgq_rsp;
139 pipeline->timer_period_ms = params->timer_period_ms;
140 pipeline->enabled = 0;
141 pipeline->cpu_id = params->cpu_id;
143 /* Node add to list */
144 TAILQ_INSERT_TAIL(&pipeline_list, pipeline, node);
150 pipeline_port_in_create(const char *pipeline_name,
151 struct port_in_params *params,
154 struct rte_pipeline_port_in_params p;
157 struct rte_port_ethdev_reader_params ethdev;
158 struct rte_port_ring_reader_params ring;
159 struct rte_port_sched_reader_params sched;
160 struct rte_port_fd_reader_params fd;
161 #ifdef RTE_LIBRTE_KNI
162 struct rte_port_kni_reader_params kni;
164 struct rte_port_source_params source;
167 struct pipeline *pipeline;
168 struct port_in *port_in;
169 struct port_in_action_profile *ap;
170 struct rte_port_in_action *action;
174 memset(&p, 0, sizeof(p));
175 memset(&pp, 0, sizeof(pp));
177 /* Check input params */
178 if ((pipeline_name == NULL) ||
180 (params->burst_size == 0) ||
181 (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
184 pipeline = pipeline_find(pipeline_name);
185 if (pipeline == NULL)
189 if (params->action_profile_name) {
190 ap = port_in_action_profile_find(params->action_profile_name);
195 switch (params->type) {
200 link = link_find(params->dev_name);
204 if (params->rxq.queue_id >= link->n_rxq)
207 pp.ethdev.port_id = link->port_id;
208 pp.ethdev.queue_id = params->rxq.queue_id;
210 p.ops = &rte_port_ethdev_reader_ops;
211 p.arg_create = &pp.ethdev;
219 swq = swq_find(params->dev_name);
223 pp.ring.ring = swq->r;
225 p.ops = &rte_port_ring_reader_ops;
226 p.arg_create = &pp.ring;
232 struct tmgr_port *tmgr_port;
234 tmgr_port = tmgr_port_find(params->dev_name);
235 if (tmgr_port == NULL)
238 pp.sched.sched = tmgr_port->s;
240 p.ops = &rte_port_sched_reader_ops;
241 p.arg_create = &pp.sched;
248 struct mempool *mempool;
250 tap = tap_find(params->dev_name);
251 mempool = mempool_find(params->tap.mempool_name);
252 if ((tap == NULL) || (mempool == NULL))
256 pp.fd.mempool = mempool->m;
257 pp.fd.mtu = params->tap.mtu;
259 p.ops = &rte_port_fd_reader_ops;
260 p.arg_create = &pp.fd;
264 #ifdef RTE_LIBRTE_KNI
269 kni = kni_find(params->dev_name);
275 p.ops = &rte_port_kni_reader_ops;
276 p.arg_create = &pp.kni;
283 struct mempool *mempool;
285 mempool = mempool_find(params->source.mempool_name);
289 pp.source.mempool = mempool->m;
290 pp.source.file_name = params->source.file_name;
291 pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt;
293 p.ops = &rte_port_source_ops;
294 p.arg_create = &pp.source;
302 p.burst_size = params->burst_size;
304 /* Resource create */
310 action = rte_port_in_action_create(ap->ap,
315 status = rte_port_in_action_params_get(
319 rte_port_in_action_free(action);
324 status = rte_pipeline_port_in_create(pipeline->p,
328 rte_port_in_action_free(action);
333 rte_pipeline_port_in_enable(pipeline->p, port_id);
336 port_in = &pipeline->port_in[pipeline->n_ports_in];
337 memcpy(&port_in->params, params, sizeof(*params));
340 pipeline->n_ports_in++;
346 pipeline_port_in_connect_to_table(const char *pipeline_name,
350 struct pipeline *pipeline;
353 /* Check input params */
354 if (pipeline_name == NULL)
357 pipeline = pipeline_find(pipeline_name);
358 if ((pipeline == NULL) ||
359 (port_id >= pipeline->n_ports_in) ||
360 (table_id >= pipeline->n_tables))
364 status = rte_pipeline_port_in_connect_to_table(pipeline->p,
373 pipeline_port_out_create(const char *pipeline_name,
374 struct port_out_params *params)
376 struct rte_pipeline_port_out_params p;
379 struct rte_port_ethdev_writer_params ethdev;
380 struct rte_port_ring_writer_params ring;
381 struct rte_port_sched_writer_params sched;
382 struct rte_port_fd_writer_params fd;
383 #ifdef RTE_LIBRTE_KNI
384 struct rte_port_kni_writer_params kni;
386 struct rte_port_sink_params sink;
390 struct rte_port_ethdev_writer_nodrop_params ethdev;
391 struct rte_port_ring_writer_nodrop_params ring;
392 struct rte_port_fd_writer_nodrop_params fd;
393 #ifdef RTE_LIBRTE_KNI
394 struct rte_port_kni_writer_nodrop_params kni;
398 struct pipeline *pipeline;
402 memset(&p, 0, sizeof(p));
403 memset(&pp, 0, sizeof(pp));
404 memset(&pp_nodrop, 0, sizeof(pp_nodrop));
406 /* Check input params */
407 if ((pipeline_name == NULL) ||
409 (params->burst_size == 0) ||
410 (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
413 pipeline = pipeline_find(pipeline_name);
414 if (pipeline == NULL)
417 switch (params->type) {
422 link = link_find(params->dev_name);
426 if (params->txq.queue_id >= link->n_txq)
429 pp.ethdev.port_id = link->port_id;
430 pp.ethdev.queue_id = params->txq.queue_id;
431 pp.ethdev.tx_burst_sz = params->burst_size;
433 pp_nodrop.ethdev.port_id = link->port_id;
434 pp_nodrop.ethdev.queue_id = params->txq.queue_id;
435 pp_nodrop.ethdev.tx_burst_sz = params->burst_size;
436 pp_nodrop.ethdev.n_retries = params->n_retries;
438 if (params->retry == 0) {
439 p.ops = &rte_port_ethdev_writer_ops;
440 p.arg_create = &pp.ethdev;
442 p.ops = &rte_port_ethdev_writer_nodrop_ops;
443 p.arg_create = &pp_nodrop.ethdev;
452 swq = swq_find(params->dev_name);
456 pp.ring.ring = swq->r;
457 pp.ring.tx_burst_sz = params->burst_size;
459 pp_nodrop.ring.ring = swq->r;
460 pp_nodrop.ring.tx_burst_sz = params->burst_size;
461 pp_nodrop.ring.n_retries = params->n_retries;
463 if (params->retry == 0) {
464 p.ops = &rte_port_ring_writer_ops;
465 p.arg_create = &pp.ring;
467 p.ops = &rte_port_ring_writer_nodrop_ops;
468 p.arg_create = &pp_nodrop.ring;
475 struct tmgr_port *tmgr_port;
477 tmgr_port = tmgr_port_find(params->dev_name);
478 if (tmgr_port == NULL)
481 pp.sched.sched = tmgr_port->s;
482 pp.sched.tx_burst_sz = params->burst_size;
484 p.ops = &rte_port_sched_writer_ops;
485 p.arg_create = &pp.sched;
493 tap = tap_find(params->dev_name);
498 pp.fd.tx_burst_sz = params->burst_size;
500 pp_nodrop.fd.fd = tap->fd;
501 pp_nodrop.fd.tx_burst_sz = params->burst_size;
502 pp_nodrop.fd.n_retries = params->n_retries;
504 if (params->retry == 0) {
505 p.ops = &rte_port_fd_writer_ops;
506 p.arg_create = &pp.fd;
508 p.ops = &rte_port_fd_writer_nodrop_ops;
509 p.arg_create = &pp_nodrop.fd;
514 #ifdef RTE_LIBRTE_KNI
519 kni = kni_find(params->dev_name);
524 pp.kni.tx_burst_sz = params->burst_size;
526 pp_nodrop.kni.kni = kni->k;
527 pp_nodrop.kni.tx_burst_sz = params->burst_size;
528 pp_nodrop.kni.n_retries = params->n_retries;
530 if (params->retry == 0) {
531 p.ops = &rte_port_kni_writer_ops;
532 p.arg_create = &pp.kni;
534 p.ops = &rte_port_kni_writer_nodrop_ops;
535 p.arg_create = &pp_nodrop.kni;
543 pp.sink.file_name = params->sink.file_name;
544 pp.sink.max_n_pkts = params->sink.max_n_pkts;
546 p.ops = &rte_port_sink_ops;
547 p.arg_create = &pp.sink;
558 /* Resource create */
559 status = rte_pipeline_port_out_create(pipeline->p,
567 pipeline->n_ports_out++;
572 static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
575 .type = RTE_ACL_FIELD_TYPE_BITMASK,
576 .size = sizeof(uint8_t),
579 .offset = offsetof(struct ipv4_hdr, next_proto_id),
582 /* Source IP address (IPv4) */
584 .type = RTE_ACL_FIELD_TYPE_MASK,
585 .size = sizeof(uint32_t),
588 .offset = offsetof(struct ipv4_hdr, src_addr),
591 /* Destination IP address (IPv4) */
593 .type = RTE_ACL_FIELD_TYPE_MASK,
594 .size = sizeof(uint32_t),
597 .offset = offsetof(struct ipv4_hdr, dst_addr),
602 .type = RTE_ACL_FIELD_TYPE_RANGE,
603 .size = sizeof(uint16_t),
606 .offset = sizeof(struct ipv4_hdr) +
607 offsetof(struct tcp_hdr, src_port),
610 /* Destination Port */
612 .type = RTE_ACL_FIELD_TYPE_RANGE,
613 .size = sizeof(uint16_t),
616 .offset = sizeof(struct ipv4_hdr) +
617 offsetof(struct tcp_hdr, dst_port),
621 static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
624 .type = RTE_ACL_FIELD_TYPE_BITMASK,
625 .size = sizeof(uint8_t),
628 .offset = offsetof(struct ipv6_hdr, proto),
631 /* Source IP address (IPv6) */
633 .type = RTE_ACL_FIELD_TYPE_MASK,
634 .size = sizeof(uint32_t),
637 .offset = offsetof(struct ipv6_hdr, src_addr[0]),
641 .type = RTE_ACL_FIELD_TYPE_MASK,
642 .size = sizeof(uint32_t),
645 .offset = offsetof(struct ipv6_hdr, src_addr[4]),
649 .type = RTE_ACL_FIELD_TYPE_MASK,
650 .size = sizeof(uint32_t),
653 .offset = offsetof(struct ipv6_hdr, src_addr[8]),
657 .type = RTE_ACL_FIELD_TYPE_MASK,
658 .size = sizeof(uint32_t),
661 .offset = offsetof(struct ipv6_hdr, src_addr[12]),
664 /* Destination IP address (IPv6) */
666 .type = RTE_ACL_FIELD_TYPE_MASK,
667 .size = sizeof(uint32_t),
670 .offset = offsetof(struct ipv6_hdr, dst_addr[0]),
674 .type = RTE_ACL_FIELD_TYPE_MASK,
675 .size = sizeof(uint32_t),
678 .offset = offsetof(struct ipv6_hdr, dst_addr[4]),
682 .type = RTE_ACL_FIELD_TYPE_MASK,
683 .size = sizeof(uint32_t),
686 .offset = offsetof(struct ipv6_hdr, dst_addr[8]),
690 .type = RTE_ACL_FIELD_TYPE_MASK,
691 .size = sizeof(uint32_t),
694 .offset = offsetof(struct ipv6_hdr, dst_addr[12]),
699 .type = RTE_ACL_FIELD_TYPE_RANGE,
700 .size = sizeof(uint16_t),
703 .offset = sizeof(struct ipv6_hdr) +
704 offsetof(struct tcp_hdr, src_port),
707 /* Destination Port */
709 .type = RTE_ACL_FIELD_TYPE_RANGE,
710 .size = sizeof(uint16_t),
713 .offset = sizeof(struct ipv6_hdr) +
714 offsetof(struct tcp_hdr, dst_port),
719 pipeline_table_create(const char *pipeline_name,
720 struct table_params *params)
723 struct rte_pipeline_table_params p;
726 struct rte_table_acl_params acl;
727 struct rte_table_array_params array;
728 struct rte_table_hash_params hash;
729 struct rte_table_lpm_params lpm;
730 struct rte_table_lpm_ipv6_params lpm_ipv6;
733 struct pipeline *pipeline;
735 struct table_action_profile *ap;
736 struct rte_table_action *action;
740 memset(&p, 0, sizeof(p));
741 memset(&pp, 0, sizeof(pp));
743 /* Check input params */
744 if ((pipeline_name == NULL) ||
748 pipeline = pipeline_find(pipeline_name);
749 if ((pipeline == NULL) ||
750 (pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX))
754 if (params->action_profile_name) {
755 ap = table_action_profile_find(params->action_profile_name);
760 snprintf(name, NAME_MAX, "%s_table%u",
761 pipeline_name, pipeline->n_tables);
763 switch (params->match_type) {
766 uint32_t ip_header_offset = params->match.acl.ip_header_offset -
767 (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
770 if (params->match.acl.n_rules == 0)
774 pp.acl.n_rules = params->match.acl.n_rules;
775 if (params->match.acl.ip_version) {
776 memcpy(&pp.acl.field_format,
777 &table_acl_field_format_ipv4,
778 sizeof(table_acl_field_format_ipv4));
779 pp.acl.n_rule_fields =
780 RTE_DIM(table_acl_field_format_ipv4);
782 memcpy(&pp.acl.field_format,
783 &table_acl_field_format_ipv6,
784 sizeof(table_acl_field_format_ipv6));
785 pp.acl.n_rule_fields =
786 RTE_DIM(table_acl_field_format_ipv6);
789 for (i = 0; i < pp.acl.n_rule_fields; i++)
790 pp.acl.field_format[i].offset += ip_header_offset;
792 p.ops = &rte_table_acl_ops;
793 p.arg_create = &pp.acl;
799 if (params->match.array.n_keys == 0)
802 pp.array.n_entries = params->match.array.n_keys;
803 pp.array.offset = params->match.array.key_offset;
805 p.ops = &rte_table_array_ops;
806 p.arg_create = &pp.array;
812 struct rte_table_ops *ops;
813 rte_table_hash_op_hash f_hash;
815 if (params->match.hash.n_keys == 0)
818 switch (params->match.hash.key_size) {
820 f_hash = hash_default_key8;
823 f_hash = hash_default_key16;
826 f_hash = hash_default_key24;
829 f_hash = hash_default_key32;
832 f_hash = hash_default_key40;
835 f_hash = hash_default_key48;
838 f_hash = hash_default_key56;
841 f_hash = hash_default_key64;
848 pp.hash.key_size = params->match.hash.key_size;
849 pp.hash.key_offset = params->match.hash.key_offset;
850 pp.hash.key_mask = params->match.hash.key_mask;
851 pp.hash.n_keys = params->match.hash.n_keys;
852 pp.hash.n_buckets = params->match.hash.n_buckets;
853 pp.hash.f_hash = f_hash;
856 if (params->match.hash.extendable_bucket)
857 switch (params->match.hash.key_size) {
859 ops = &rte_table_hash_key8_ext_ops;
862 ops = &rte_table_hash_key16_ext_ops;
865 ops = &rte_table_hash_ext_ops;
868 switch (params->match.hash.key_size) {
870 ops = &rte_table_hash_key8_lru_ops;
873 ops = &rte_table_hash_key16_lru_ops;
876 ops = &rte_table_hash_lru_ops;
880 p.arg_create = &pp.hash;
886 if (params->match.lpm.n_rules == 0)
889 switch (params->match.lpm.key_size) {
893 pp.lpm.n_rules = params->match.lpm.n_rules;
894 pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
896 pp.lpm.entry_unique_size = p.action_data_size +
897 sizeof(struct rte_pipeline_table_entry);
898 pp.lpm.offset = params->match.lpm.key_offset;
900 p.ops = &rte_table_lpm_ops;
901 p.arg_create = &pp.lpm;
907 pp.lpm_ipv6.name = name;
908 pp.lpm_ipv6.n_rules = params->match.lpm.n_rules;
909 pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
910 pp.lpm_ipv6.entry_unique_size = p.action_data_size +
911 sizeof(struct rte_pipeline_table_entry);
912 pp.lpm_ipv6.offset = params->match.lpm.key_offset;
914 p.ops = &rte_table_lpm_ipv6_ops;
915 p.arg_create = &pp.lpm_ipv6;
928 p.ops = &rte_table_stub_ops;
937 /* Resource create */
939 p.f_action_hit = NULL;
940 p.f_action_miss = NULL;
944 action = rte_table_action_create(ap->ap,
949 status = rte_table_action_table_params_get(
953 ((p.action_data_size +
954 sizeof(struct rte_pipeline_table_entry)) >
955 TABLE_RULE_ACTION_SIZE_MAX)) {
956 rte_table_action_free(action);
961 if (params->match_type == TABLE_LPM) {
962 if (params->match.lpm.key_size == 4)
963 pp.lpm.entry_unique_size = p.action_data_size +
964 sizeof(struct rte_pipeline_table_entry);
966 if (params->match.lpm.key_size == 16)
967 pp.lpm_ipv6.entry_unique_size = p.action_data_size +
968 sizeof(struct rte_pipeline_table_entry);
971 status = rte_pipeline_table_create(pipeline->p,
975 rte_table_action_free(action);
980 table = &pipeline->table[pipeline->n_tables];
981 memcpy(&table->params, params, sizeof(*params));
984 pipeline->n_tables++;