1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
8 #include <rte_common.h>
12 #include <rte_string_fns.h>
13 #include <rte_port_ethdev.h>
15 #include <rte_port_kni.h>
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>
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>
39 #include "hash_func.h"
41 #ifndef PIPELINE_MSGQ_SIZE
42 #define PIPELINE_MSGQ_SIZE 64
45 #ifndef TABLE_LPM_NUMBER_TBL8
46 #define TABLE_LPM_NUMBER_TBL8 256
49 static struct pipeline_list pipeline_list;
54 TAILQ_INIT(&pipeline_list);
60 pipeline_find(const char *name)
62 struct pipeline *pipeline;
67 TAILQ_FOREACH(pipeline, &pipeline_list, node)
68 if (strcmp(name, pipeline->name) == 0)
75 pipeline_create(const char *name, struct pipeline_params *params)
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;
84 /* Check input params */
86 pipeline_find(name) ||
88 (params->timer_period_ms == 0))
92 snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-REQ", name);
94 msgq_req = rte_ring_create(msgq_name,
97 RING_F_SP_ENQ | RING_F_SC_DEQ);
101 snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-RSP", name);
103 msgq_rsp = rte_ring_create(msgq_name,
106 RING_F_SP_ENQ | RING_F_SC_DEQ);
107 if (msgq_rsp == NULL) {
108 rte_ring_free(msgq_req);
113 pp.socket_id = (int) params->cpu_id;
114 pp.offset_port_id = params->offset_port_id;
116 p = rte_pipeline_create(&pp);
118 rte_ring_free(msgq_rsp);
119 rte_ring_free(msgq_req);
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);
133 strlcpy(pipeline->name, name, sizeof(pipeline->name));
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;
144 /* Node add to list */
145 TAILQ_INSERT_TAIL(&pipeline_list, pipeline, node);
151 pipeline_port_in_create(const char *pipeline_name,
152 struct port_in_params *params,
155 struct rte_pipeline_port_in_params p;
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;
165 struct rte_port_source_params source;
168 struct pipeline *pipeline;
169 struct port_in *port_in;
170 struct port_in_action_profile *ap;
171 struct rte_port_in_action *action;
175 memset(&p, 0, sizeof(p));
176 memset(&pp, 0, sizeof(pp));
178 /* Check input params */
179 if ((pipeline_name == NULL) ||
181 (params->burst_size == 0) ||
182 (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
185 pipeline = pipeline_find(pipeline_name);
186 if (pipeline == NULL)
190 if (params->action_profile_name) {
191 ap = port_in_action_profile_find(params->action_profile_name);
196 switch (params->type) {
201 link = link_find(params->dev_name);
205 if (params->rxq.queue_id >= link->n_rxq)
208 pp.ethdev.port_id = link->port_id;
209 pp.ethdev.queue_id = params->rxq.queue_id;
211 p.ops = &rte_port_ethdev_reader_ops;
212 p.arg_create = &pp.ethdev;
220 swq = swq_find(params->dev_name);
224 pp.ring.ring = swq->r;
226 p.ops = &rte_port_ring_reader_ops;
227 p.arg_create = &pp.ring;
233 struct tmgr_port *tmgr_port;
235 tmgr_port = tmgr_port_find(params->dev_name);
236 if (tmgr_port == NULL)
239 pp.sched.sched = tmgr_port->s;
241 p.ops = &rte_port_sched_reader_ops;
242 p.arg_create = &pp.sched;
249 struct mempool *mempool;
251 tap = tap_find(params->dev_name);
252 mempool = mempool_find(params->tap.mempool_name);
253 if ((tap == NULL) || (mempool == NULL))
257 pp.fd.mempool = mempool->m;
258 pp.fd.mtu = params->tap.mtu;
260 p.ops = &rte_port_fd_reader_ops;
261 p.arg_create = &pp.fd;
265 #ifdef RTE_LIBRTE_KNI
270 kni = kni_find(params->dev_name);
276 p.ops = &rte_port_kni_reader_ops;
277 p.arg_create = &pp.kni;
284 struct mempool *mempool;
286 mempool = mempool_find(params->source.mempool_name);
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;
294 p.ops = &rte_port_source_ops;
295 p.arg_create = &pp.source;
303 p.burst_size = params->burst_size;
305 /* Resource create */
311 action = rte_port_in_action_create(ap->ap,
316 status = rte_port_in_action_params_get(
320 rte_port_in_action_free(action);
325 status = rte_pipeline_port_in_create(pipeline->p,
329 rte_port_in_action_free(action);
334 rte_pipeline_port_in_enable(pipeline->p, port_id);
337 port_in = &pipeline->port_in[pipeline->n_ports_in];
338 memcpy(&port_in->params, params, sizeof(*params));
341 pipeline->n_ports_in++;
347 pipeline_port_in_connect_to_table(const char *pipeline_name,
351 struct pipeline *pipeline;
354 /* Check input params */
355 if (pipeline_name == NULL)
358 pipeline = pipeline_find(pipeline_name);
359 if ((pipeline == NULL) ||
360 (port_id >= pipeline->n_ports_in) ||
361 (table_id >= pipeline->n_tables))
365 status = rte_pipeline_port_in_connect_to_table(pipeline->p,
374 pipeline_port_out_create(const char *pipeline_name,
375 struct port_out_params *params)
377 struct rte_pipeline_port_out_params p;
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;
387 struct rte_port_sink_params sink;
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;
399 struct pipeline *pipeline;
403 memset(&p, 0, sizeof(p));
404 memset(&pp, 0, sizeof(pp));
405 memset(&pp_nodrop, 0, sizeof(pp_nodrop));
407 /* Check input params */
408 if ((pipeline_name == NULL) ||
410 (params->burst_size == 0) ||
411 (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
414 pipeline = pipeline_find(pipeline_name);
415 if (pipeline == NULL)
418 switch (params->type) {
423 link = link_find(params->dev_name);
427 if (params->txq.queue_id >= link->n_txq)
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;
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;
439 if (params->retry == 0) {
440 p.ops = &rte_port_ethdev_writer_ops;
441 p.arg_create = &pp.ethdev;
443 p.ops = &rte_port_ethdev_writer_nodrop_ops;
444 p.arg_create = &pp_nodrop.ethdev;
453 swq = swq_find(params->dev_name);
457 pp.ring.ring = swq->r;
458 pp.ring.tx_burst_sz = params->burst_size;
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;
464 if (params->retry == 0) {
465 p.ops = &rte_port_ring_writer_ops;
466 p.arg_create = &pp.ring;
468 p.ops = &rte_port_ring_writer_nodrop_ops;
469 p.arg_create = &pp_nodrop.ring;
476 struct tmgr_port *tmgr_port;
478 tmgr_port = tmgr_port_find(params->dev_name);
479 if (tmgr_port == NULL)
482 pp.sched.sched = tmgr_port->s;
483 pp.sched.tx_burst_sz = params->burst_size;
485 p.ops = &rte_port_sched_writer_ops;
486 p.arg_create = &pp.sched;
494 tap = tap_find(params->dev_name);
499 pp.fd.tx_burst_sz = params->burst_size;
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;
505 if (params->retry == 0) {
506 p.ops = &rte_port_fd_writer_ops;
507 p.arg_create = &pp.fd;
509 p.ops = &rte_port_fd_writer_nodrop_ops;
510 p.arg_create = &pp_nodrop.fd;
515 #ifdef RTE_LIBRTE_KNI
520 kni = kni_find(params->dev_name);
525 pp.kni.tx_burst_sz = params->burst_size;
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;
531 if (params->retry == 0) {
532 p.ops = &rte_port_kni_writer_ops;
533 p.arg_create = &pp.kni;
535 p.ops = &rte_port_kni_writer_nodrop_ops;
536 p.arg_create = &pp_nodrop.kni;
544 pp.sink.file_name = params->sink.file_name;
545 pp.sink.max_n_pkts = params->sink.max_n_pkts;
547 p.ops = &rte_port_sink_ops;
548 p.arg_create = &pp.sink;
559 /* Resource create */
560 status = rte_pipeline_port_out_create(pipeline->p,
568 pipeline->n_ports_out++;
573 static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
576 .type = RTE_ACL_FIELD_TYPE_BITMASK,
577 .size = sizeof(uint8_t),
580 .offset = offsetof(struct ipv4_hdr, next_proto_id),
583 /* Source IP address (IPv4) */
585 .type = RTE_ACL_FIELD_TYPE_MASK,
586 .size = sizeof(uint32_t),
589 .offset = offsetof(struct ipv4_hdr, src_addr),
592 /* Destination IP address (IPv4) */
594 .type = RTE_ACL_FIELD_TYPE_MASK,
595 .size = sizeof(uint32_t),
598 .offset = offsetof(struct ipv4_hdr, dst_addr),
603 .type = RTE_ACL_FIELD_TYPE_RANGE,
604 .size = sizeof(uint16_t),
607 .offset = sizeof(struct ipv4_hdr) +
608 offsetof(struct tcp_hdr, src_port),
611 /* Destination Port */
613 .type = RTE_ACL_FIELD_TYPE_RANGE,
614 .size = sizeof(uint16_t),
617 .offset = sizeof(struct ipv4_hdr) +
618 offsetof(struct tcp_hdr, dst_port),
622 static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
625 .type = RTE_ACL_FIELD_TYPE_BITMASK,
626 .size = sizeof(uint8_t),
629 .offset = offsetof(struct ipv6_hdr, proto),
632 /* Source IP address (IPv6) */
634 .type = RTE_ACL_FIELD_TYPE_MASK,
635 .size = sizeof(uint32_t),
638 .offset = offsetof(struct ipv6_hdr, src_addr[0]),
642 .type = RTE_ACL_FIELD_TYPE_MASK,
643 .size = sizeof(uint32_t),
646 .offset = offsetof(struct ipv6_hdr, src_addr[4]),
650 .type = RTE_ACL_FIELD_TYPE_MASK,
651 .size = sizeof(uint32_t),
654 .offset = offsetof(struct ipv6_hdr, src_addr[8]),
658 .type = RTE_ACL_FIELD_TYPE_MASK,
659 .size = sizeof(uint32_t),
662 .offset = offsetof(struct ipv6_hdr, src_addr[12]),
665 /* Destination IP address (IPv6) */
667 .type = RTE_ACL_FIELD_TYPE_MASK,
668 .size = sizeof(uint32_t),
671 .offset = offsetof(struct ipv6_hdr, dst_addr[0]),
675 .type = RTE_ACL_FIELD_TYPE_MASK,
676 .size = sizeof(uint32_t),
679 .offset = offsetof(struct ipv6_hdr, dst_addr[4]),
683 .type = RTE_ACL_FIELD_TYPE_MASK,
684 .size = sizeof(uint32_t),
687 .offset = offsetof(struct ipv6_hdr, dst_addr[8]),
691 .type = RTE_ACL_FIELD_TYPE_MASK,
692 .size = sizeof(uint32_t),
695 .offset = offsetof(struct ipv6_hdr, dst_addr[12]),
700 .type = RTE_ACL_FIELD_TYPE_RANGE,
701 .size = sizeof(uint16_t),
704 .offset = sizeof(struct ipv6_hdr) +
705 offsetof(struct tcp_hdr, src_port),
708 /* Destination Port */
710 .type = RTE_ACL_FIELD_TYPE_RANGE,
711 .size = sizeof(uint16_t),
714 .offset = sizeof(struct ipv6_hdr) +
715 offsetof(struct tcp_hdr, dst_port),
720 pipeline_table_create(const char *pipeline_name,
721 struct table_params *params)
724 struct rte_pipeline_table_params p;
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;
734 struct pipeline *pipeline;
736 struct table_action_profile *ap;
737 struct rte_table_action *action;
741 memset(&p, 0, sizeof(p));
742 memset(&pp, 0, sizeof(pp));
744 /* Check input params */
745 if ((pipeline_name == NULL) ||
749 pipeline = pipeline_find(pipeline_name);
750 if ((pipeline == NULL) ||
751 (pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX))
755 if (params->action_profile_name) {
756 ap = table_action_profile_find(params->action_profile_name);
761 snprintf(name, NAME_MAX, "%s_table%u",
762 pipeline_name, pipeline->n_tables);
764 switch (params->match_type) {
767 uint32_t ip_header_offset = params->match.acl.ip_header_offset -
768 (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
771 if (params->match.acl.n_rules == 0)
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);
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);
790 for (i = 0; i < pp.acl.n_rule_fields; i++)
791 pp.acl.field_format[i].offset += ip_header_offset;
793 p.ops = &rte_table_acl_ops;
794 p.arg_create = &pp.acl;
800 if (params->match.array.n_keys == 0)
803 pp.array.n_entries = params->match.array.n_keys;
804 pp.array.offset = params->match.array.key_offset;
806 p.ops = &rte_table_array_ops;
807 p.arg_create = &pp.array;
813 struct rte_table_ops *ops;
814 rte_table_hash_op_hash f_hash;
816 if (params->match.hash.n_keys == 0)
819 switch (params->match.hash.key_size) {
821 f_hash = hash_default_key8;
824 f_hash = hash_default_key16;
827 f_hash = hash_default_key24;
830 f_hash = hash_default_key32;
833 f_hash = hash_default_key40;
836 f_hash = hash_default_key48;
839 f_hash = hash_default_key56;
842 f_hash = hash_default_key64;
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;
857 if (params->match.hash.extendable_bucket)
858 switch (params->match.hash.key_size) {
860 ops = &rte_table_hash_key8_ext_ops;
863 ops = &rte_table_hash_key16_ext_ops;
866 ops = &rte_table_hash_ext_ops;
869 switch (params->match.hash.key_size) {
871 ops = &rte_table_hash_key8_lru_ops;
874 ops = &rte_table_hash_key16_lru_ops;
877 ops = &rte_table_hash_lru_ops;
881 p.arg_create = &pp.hash;
887 if (params->match.lpm.n_rules == 0)
890 switch (params->match.lpm.key_size) {
894 pp.lpm.n_rules = params->match.lpm.n_rules;
895 pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
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;
901 p.ops = &rte_table_lpm_ops;
902 p.arg_create = &pp.lpm;
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;
915 p.ops = &rte_table_lpm_ipv6_ops;
916 p.arg_create = &pp.lpm_ipv6;
929 p.ops = &rte_table_stub_ops;
938 /* Resource create */
940 p.f_action_hit = NULL;
941 p.f_action_miss = NULL;
945 action = rte_table_action_create(ap->ap,
950 status = rte_table_action_table_params_get(
954 ((p.action_data_size +
955 sizeof(struct rte_pipeline_table_entry)) >
956 TABLE_RULE_ACTION_SIZE_MAX)) {
957 rte_table_action_free(action);
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);
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);
972 status = rte_pipeline_table_create(pipeline->p,
976 rte_table_action_free(action);
981 table = &pipeline->table[pipeline->n_tables];
982 memcpy(&table->params, params, sizeof(*params));
985 pipeline->n_tables++;