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>
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>
19 #include <rte_table_acl.h>
20 #include <rte_table_array.h>
21 #include <rte_table_hash.h>
22 #include <rte_table_hash_func.h>
23 #include <rte_table_lpm.h>
24 #include <rte_table_lpm_ipv6.h>
25 #include <rte_table_stub.h>
27 #include "rte_eth_softnic_internals.h"
29 #ifndef PIPELINE_MSGQ_SIZE
30 #define PIPELINE_MSGQ_SIZE 64
33 #ifndef TABLE_LPM_NUMBER_TBL8
34 #define TABLE_LPM_NUMBER_TBL8 256
38 softnic_pipeline_init(struct pmd_internals *p)
40 TAILQ_INIT(&p->pipeline_list);
46 softnic_pipeline_free(struct pmd_internals *p)
49 struct pipeline *pipeline;
51 pipeline = TAILQ_FIRST(&p->pipeline_list);
55 TAILQ_REMOVE(&p->pipeline_list, pipeline, node);
56 rte_ring_free(pipeline->msgq_req);
57 rte_ring_free(pipeline->msgq_rsp);
58 rte_pipeline_free(pipeline->p);
64 softnic_pipeline_disable_all(struct pmd_internals *p)
66 struct pipeline *pipeline;
68 TAILQ_FOREACH(pipeline, &p->pipeline_list, node)
69 if (pipeline->enabled)
70 softnic_thread_pipeline_disable(p,
76 softnic_pipeline_find(struct pmd_internals *p,
79 struct pipeline *pipeline;
84 TAILQ_FOREACH(pipeline, &p->pipeline_list, node)
85 if (strcmp(name, pipeline->name) == 0)
92 softnic_pipeline_create(struct pmd_internals *softnic,
94 struct pipeline_params *params)
96 char resource_name[NAME_MAX];
97 struct rte_pipeline_params pp;
98 struct pipeline *pipeline;
99 struct rte_pipeline *p;
100 struct rte_ring *msgq_req;
101 struct rte_ring *msgq_rsp;
103 /* Check input params */
105 softnic_pipeline_find(softnic, name) ||
107 params->timer_period_ms == 0)
110 /* Resource create */
111 snprintf(resource_name, sizeof(resource_name), "%s-%s-REQ",
112 softnic->params.name,
115 msgq_req = rte_ring_create(resource_name,
117 softnic->params.cpu_id,
118 RING_F_SP_ENQ | RING_F_SC_DEQ);
119 if (msgq_req == NULL)
122 snprintf(resource_name, sizeof(resource_name), "%s-%s-RSP",
123 softnic->params.name,
126 msgq_rsp = rte_ring_create(resource_name,
128 softnic->params.cpu_id,
129 RING_F_SP_ENQ | RING_F_SC_DEQ);
130 if (msgq_rsp == NULL) {
131 rte_ring_free(msgq_req);
135 snprintf(resource_name, sizeof(resource_name), "%s_%s",
136 softnic->params.name,
139 pp.name = resource_name;
140 pp.socket_id = (int)softnic->params.cpu_id;
141 pp.offset_port_id = params->offset_port_id;
143 p = rte_pipeline_create(&pp);
145 rte_ring_free(msgq_rsp);
146 rte_ring_free(msgq_req);
150 /* Node allocation */
151 pipeline = calloc(1, sizeof(struct pipeline));
152 if (pipeline == NULL) {
153 rte_pipeline_free(p);
154 rte_ring_free(msgq_rsp);
155 rte_ring_free(msgq_req);
160 strlcpy(pipeline->name, name, sizeof(pipeline->name));
162 pipeline->n_ports_in = 0;
163 pipeline->n_ports_out = 0;
164 pipeline->n_tables = 0;
165 pipeline->msgq_req = msgq_req;
166 pipeline->msgq_rsp = msgq_rsp;
167 pipeline->timer_period_ms = params->timer_period_ms;
168 pipeline->enabled = 0;
169 pipeline->cpu_id = softnic->params.cpu_id;
171 /* Node add to list */
172 TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node);
178 softnic_pipeline_port_in_create(struct pmd_internals *softnic,
179 const char *pipeline_name,
180 struct softnic_port_in_params *params,
183 struct rte_pipeline_port_in_params p;
186 struct rte_port_ethdev_reader_params ethdev;
187 struct rte_port_ring_reader_params ring;
188 struct rte_port_sched_reader_params sched;
189 struct rte_port_fd_reader_params fd;
190 struct rte_port_source_params source;
193 struct pipeline *pipeline;
194 struct softnic_port_in *port_in;
195 struct softnic_port_in_action_profile *ap;
196 struct rte_port_in_action *action;
200 memset(&p, 0, sizeof(p));
201 memset(&pp, 0, sizeof(pp));
203 /* Check input params */
204 if (pipeline_name == NULL ||
206 params->burst_size == 0 ||
207 params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)
210 pipeline = softnic_pipeline_find(softnic, pipeline_name);
211 if (pipeline == NULL)
215 if (params->action_profile_name) {
216 ap = softnic_port_in_action_profile_find(softnic,
217 params->action_profile_name);
222 switch (params->type) {
225 struct softnic_link *link;
227 link = softnic_link_find(softnic, params->dev_name);
231 if (params->rxq.queue_id >= link->n_rxq)
234 pp.ethdev.port_id = link->port_id;
235 pp.ethdev.queue_id = params->rxq.queue_id;
237 p.ops = &rte_port_ethdev_reader_ops;
238 p.arg_create = &pp.ethdev;
244 struct softnic_swq *swq;
246 swq = softnic_swq_find(softnic, params->dev_name);
250 pp.ring.ring = swq->r;
252 p.ops = &rte_port_ring_reader_ops;
253 p.arg_create = &pp.ring;
259 struct softnic_tmgr_port *tmgr_port;
261 tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
262 if (tmgr_port == NULL)
265 pp.sched.sched = tmgr_port->s;
267 p.ops = &rte_port_sched_reader_ops;
268 p.arg_create = &pp.sched;
274 struct softnic_tap *tap;
275 struct softnic_mempool *mempool;
277 tap = softnic_tap_find(softnic, params->dev_name);
278 mempool = softnic_mempool_find(softnic, params->tap.mempool_name);
279 if (tap == NULL || mempool == NULL)
283 pp.fd.mempool = mempool->m;
284 pp.fd.mtu = params->tap.mtu;
286 p.ops = &rte_port_fd_reader_ops;
287 p.arg_create = &pp.fd;
293 struct softnic_mempool *mempool;
295 mempool = softnic_mempool_find(softnic, params->source.mempool_name);
299 pp.source.mempool = mempool->m;
300 pp.source.file_name = params->source.file_name;
301 pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt;
303 p.ops = &rte_port_source_ops;
304 p.arg_create = &pp.source;
312 p.burst_size = params->burst_size;
314 /* Resource create */
320 action = rte_port_in_action_create(ap->ap,
321 softnic->params.cpu_id);
325 status = rte_port_in_action_params_get(action,
328 rte_port_in_action_free(action);
333 status = rte_pipeline_port_in_create(pipeline->p,
337 rte_port_in_action_free(action);
342 rte_pipeline_port_in_enable(pipeline->p, port_id);
345 port_in = &pipeline->port_in[pipeline->n_ports_in];
346 memcpy(&port_in->params, params, sizeof(*params));
349 pipeline->n_ports_in++;
355 softnic_pipeline_port_in_connect_to_table(struct pmd_internals *softnic,
356 const char *pipeline_name,
360 struct pipeline *pipeline;
363 /* Check input params */
364 if (pipeline_name == NULL)
367 pipeline = softnic_pipeline_find(softnic, pipeline_name);
368 if (pipeline == NULL ||
369 port_id >= pipeline->n_ports_in ||
370 table_id >= pipeline->n_tables)
374 status = rte_pipeline_port_in_connect_to_table(pipeline->p,
382 softnic_pipeline_port_out_create(struct pmd_internals *softnic,
383 const char *pipeline_name,
384 struct softnic_port_out_params *params)
386 struct rte_pipeline_port_out_params p;
389 struct rte_port_ethdev_writer_params ethdev;
390 struct rte_port_ring_writer_params ring;
391 struct rte_port_sched_writer_params sched;
392 struct rte_port_fd_writer_params fd;
393 struct rte_port_sink_params sink;
397 struct rte_port_ethdev_writer_nodrop_params ethdev;
398 struct rte_port_ring_writer_nodrop_params ring;
399 struct rte_port_fd_writer_nodrop_params fd;
402 struct pipeline *pipeline;
406 memset(&p, 0, sizeof(p));
407 memset(&pp, 0, sizeof(pp));
408 memset(&pp_nodrop, 0, sizeof(pp_nodrop));
410 /* Check input params */
411 if (pipeline_name == NULL ||
413 params->burst_size == 0 ||
414 params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)
417 pipeline = softnic_pipeline_find(softnic, pipeline_name);
418 if (pipeline == NULL)
421 switch (params->type) {
424 struct softnic_link *link;
426 link = softnic_link_find(softnic, params->dev_name);
430 if (params->txq.queue_id >= link->n_txq)
433 pp.ethdev.port_id = link->port_id;
434 pp.ethdev.queue_id = params->txq.queue_id;
435 pp.ethdev.tx_burst_sz = params->burst_size;
437 pp_nodrop.ethdev.port_id = link->port_id;
438 pp_nodrop.ethdev.queue_id = params->txq.queue_id;
439 pp_nodrop.ethdev.tx_burst_sz = params->burst_size;
440 pp_nodrop.ethdev.n_retries = params->n_retries;
442 if (params->retry == 0) {
443 p.ops = &rte_port_ethdev_writer_ops;
444 p.arg_create = &pp.ethdev;
446 p.ops = &rte_port_ethdev_writer_nodrop_ops;
447 p.arg_create = &pp_nodrop.ethdev;
454 struct softnic_swq *swq;
456 swq = softnic_swq_find(softnic, params->dev_name);
460 pp.ring.ring = swq->r;
461 pp.ring.tx_burst_sz = params->burst_size;
463 pp_nodrop.ring.ring = swq->r;
464 pp_nodrop.ring.tx_burst_sz = params->burst_size;
465 pp_nodrop.ring.n_retries = params->n_retries;
467 if (params->retry == 0) {
468 p.ops = &rte_port_ring_writer_ops;
469 p.arg_create = &pp.ring;
471 p.ops = &rte_port_ring_writer_nodrop_ops;
472 p.arg_create = &pp_nodrop.ring;
479 struct softnic_tmgr_port *tmgr_port;
481 tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
482 if (tmgr_port == NULL)
485 pp.sched.sched = tmgr_port->s;
486 pp.sched.tx_burst_sz = params->burst_size;
488 p.ops = &rte_port_sched_writer_ops;
489 p.arg_create = &pp.sched;
495 struct softnic_tap *tap;
497 tap = softnic_tap_find(softnic, params->dev_name);
502 pp.fd.tx_burst_sz = params->burst_size;
504 pp_nodrop.fd.fd = tap->fd;
505 pp_nodrop.fd.tx_burst_sz = params->burst_size;
506 pp_nodrop.fd.n_retries = params->n_retries;
508 if (params->retry == 0) {
509 p.ops = &rte_port_fd_writer_ops;
510 p.arg_create = &pp.fd;
512 p.ops = &rte_port_fd_writer_nodrop_ops;
513 p.arg_create = &pp_nodrop.fd;
520 pp.sink.file_name = params->sink.file_name;
521 pp.sink.max_n_pkts = params->sink.max_n_pkts;
523 p.ops = &rte_port_sink_ops;
524 p.arg_create = &pp.sink;
535 /* Resource create */
536 status = rte_pipeline_port_out_create(pipeline->p,
544 pipeline->n_ports_out++;
549 static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
552 .type = RTE_ACL_FIELD_TYPE_BITMASK,
553 .size = sizeof(uint8_t),
556 .offset = offsetof(struct ipv4_hdr, next_proto_id),
559 /* Source IP address (IPv4) */
561 .type = RTE_ACL_FIELD_TYPE_MASK,
562 .size = sizeof(uint32_t),
565 .offset = offsetof(struct ipv4_hdr, src_addr),
568 /* Destination IP address (IPv4) */
570 .type = RTE_ACL_FIELD_TYPE_MASK,
571 .size = sizeof(uint32_t),
574 .offset = offsetof(struct ipv4_hdr, dst_addr),
579 .type = RTE_ACL_FIELD_TYPE_RANGE,
580 .size = sizeof(uint16_t),
583 .offset = sizeof(struct ipv4_hdr) +
584 offsetof(struct tcp_hdr, src_port),
587 /* Destination Port */
589 .type = RTE_ACL_FIELD_TYPE_RANGE,
590 .size = sizeof(uint16_t),
593 .offset = sizeof(struct ipv4_hdr) +
594 offsetof(struct tcp_hdr, dst_port),
598 static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
601 .type = RTE_ACL_FIELD_TYPE_BITMASK,
602 .size = sizeof(uint8_t),
605 .offset = offsetof(struct ipv6_hdr, proto),
608 /* Source IP address (IPv6) */
610 .type = RTE_ACL_FIELD_TYPE_MASK,
611 .size = sizeof(uint32_t),
614 .offset = offsetof(struct ipv6_hdr, src_addr[0]),
618 .type = RTE_ACL_FIELD_TYPE_MASK,
619 .size = sizeof(uint32_t),
622 .offset = offsetof(struct ipv6_hdr, src_addr[4]),
626 .type = RTE_ACL_FIELD_TYPE_MASK,
627 .size = sizeof(uint32_t),
630 .offset = offsetof(struct ipv6_hdr, src_addr[8]),
634 .type = RTE_ACL_FIELD_TYPE_MASK,
635 .size = sizeof(uint32_t),
638 .offset = offsetof(struct ipv6_hdr, src_addr[12]),
641 /* Destination IP address (IPv6) */
643 .type = RTE_ACL_FIELD_TYPE_MASK,
644 .size = sizeof(uint32_t),
647 .offset = offsetof(struct ipv6_hdr, dst_addr[0]),
651 .type = RTE_ACL_FIELD_TYPE_MASK,
652 .size = sizeof(uint32_t),
655 .offset = offsetof(struct ipv6_hdr, dst_addr[4]),
659 .type = RTE_ACL_FIELD_TYPE_MASK,
660 .size = sizeof(uint32_t),
663 .offset = offsetof(struct ipv6_hdr, dst_addr[8]),
667 .type = RTE_ACL_FIELD_TYPE_MASK,
668 .size = sizeof(uint32_t),
671 .offset = offsetof(struct ipv6_hdr, dst_addr[12]),
676 .type = RTE_ACL_FIELD_TYPE_RANGE,
677 .size = sizeof(uint16_t),
680 .offset = sizeof(struct ipv6_hdr) +
681 offsetof(struct tcp_hdr, src_port),
684 /* Destination Port */
686 .type = RTE_ACL_FIELD_TYPE_RANGE,
687 .size = sizeof(uint16_t),
690 .offset = sizeof(struct ipv6_hdr) +
691 offsetof(struct tcp_hdr, dst_port),
696 softnic_pipeline_table_create(struct pmd_internals *softnic,
697 const char *pipeline_name,
698 struct softnic_table_params *params)
701 struct rte_pipeline_table_params p;
704 struct rte_table_acl_params acl;
705 struct rte_table_array_params array;
706 struct rte_table_hash_params hash;
707 struct rte_table_lpm_params lpm;
708 struct rte_table_lpm_ipv6_params lpm_ipv6;
711 struct pipeline *pipeline;
712 struct softnic_table *table;
713 struct softnic_table_action_profile *ap;
714 struct rte_table_action *action;
718 memset(&p, 0, sizeof(p));
719 memset(&pp, 0, sizeof(pp));
721 /* Check input params */
722 if (pipeline_name == NULL ||
726 pipeline = softnic_pipeline_find(softnic, pipeline_name);
727 if (pipeline == NULL ||
728 pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX)
732 if (params->action_profile_name) {
733 ap = softnic_table_action_profile_find(softnic,
734 params->action_profile_name);
739 snprintf(name, NAME_MAX, "%s_%s_table%u",
740 softnic->params.name, pipeline_name, pipeline->n_tables);
742 switch (params->match_type) {
745 uint32_t ip_header_offset = params->match.acl.ip_header_offset -
746 (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
749 if (params->match.acl.n_rules == 0)
753 pp.acl.n_rules = params->match.acl.n_rules;
754 if (params->match.acl.ip_version) {
755 memcpy(&pp.acl.field_format,
756 &table_acl_field_format_ipv4,
757 sizeof(table_acl_field_format_ipv4));
758 pp.acl.n_rule_fields =
759 RTE_DIM(table_acl_field_format_ipv4);
761 memcpy(&pp.acl.field_format,
762 &table_acl_field_format_ipv6,
763 sizeof(table_acl_field_format_ipv6));
764 pp.acl.n_rule_fields =
765 RTE_DIM(table_acl_field_format_ipv6);
768 for (i = 0; i < pp.acl.n_rule_fields; i++)
769 pp.acl.field_format[i].offset += ip_header_offset;
771 p.ops = &rte_table_acl_ops;
772 p.arg_create = &pp.acl;
778 if (params->match.array.n_keys == 0)
781 pp.array.n_entries = params->match.array.n_keys;
782 pp.array.offset = params->match.array.key_offset;
784 p.ops = &rte_table_array_ops;
785 p.arg_create = &pp.array;
791 struct rte_table_ops *ops;
792 rte_table_hash_op_hash f_hash;
794 if (params->match.hash.n_keys == 0)
797 switch (params->match.hash.key_size) {
799 f_hash = rte_table_hash_crc_key8;
802 f_hash = rte_table_hash_crc_key16;
805 f_hash = rte_table_hash_crc_key24;
808 f_hash = rte_table_hash_crc_key32;
811 f_hash = rte_table_hash_crc_key40;
814 f_hash = rte_table_hash_crc_key48;
817 f_hash = rte_table_hash_crc_key56;
820 f_hash = rte_table_hash_crc_key64;
827 pp.hash.key_size = params->match.hash.key_size;
828 pp.hash.key_offset = params->match.hash.key_offset;
829 pp.hash.key_mask = params->match.hash.key_mask;
830 pp.hash.n_keys = params->match.hash.n_keys;
831 pp.hash.n_buckets = params->match.hash.n_buckets;
832 pp.hash.f_hash = f_hash;
835 if (params->match.hash.extendable_bucket)
836 switch (params->match.hash.key_size) {
838 ops = &rte_table_hash_key8_ext_ops;
841 ops = &rte_table_hash_key16_ext_ops;
844 ops = &rte_table_hash_ext_ops;
847 switch (params->match.hash.key_size) {
849 ops = &rte_table_hash_key8_lru_ops;
852 ops = &rte_table_hash_key16_lru_ops;
855 ops = &rte_table_hash_lru_ops;
859 p.arg_create = &pp.hash;
865 if (params->match.lpm.n_rules == 0)
868 switch (params->match.lpm.key_size) {
872 pp.lpm.n_rules = params->match.lpm.n_rules;
873 pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
875 pp.lpm.entry_unique_size = p.action_data_size +
876 sizeof(struct rte_pipeline_table_entry);
877 pp.lpm.offset = params->match.lpm.key_offset;
879 p.ops = &rte_table_lpm_ops;
880 p.arg_create = &pp.lpm;
886 pp.lpm_ipv6.name = name;
887 pp.lpm_ipv6.n_rules = params->match.lpm.n_rules;
888 pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
889 pp.lpm_ipv6.entry_unique_size = p.action_data_size +
890 sizeof(struct rte_pipeline_table_entry);
891 pp.lpm_ipv6.offset = params->match.lpm.key_offset;
893 p.ops = &rte_table_lpm_ipv6_ops;
894 p.arg_create = &pp.lpm_ipv6;
907 p.ops = &rte_table_stub_ops;
916 /* Resource create */
918 p.f_action_hit = NULL;
919 p.f_action_miss = NULL;
923 action = rte_table_action_create(ap->ap,
924 softnic->params.cpu_id);
928 status = rte_table_action_table_params_get(action,
931 ((p.action_data_size +
932 sizeof(struct rte_pipeline_table_entry)) >
933 TABLE_RULE_ACTION_SIZE_MAX)) {
934 rte_table_action_free(action);
939 if (params->match_type == TABLE_LPM) {
940 if (params->match.lpm.key_size == 4)
941 pp.lpm.entry_unique_size = p.action_data_size +
942 sizeof(struct rte_pipeline_table_entry);
944 if (params->match.lpm.key_size == 16)
945 pp.lpm_ipv6.entry_unique_size = p.action_data_size +
946 sizeof(struct rte_pipeline_table_entry);
949 status = rte_pipeline_table_create(pipeline->p,
953 rte_table_action_free(action);
958 table = &pipeline->table[pipeline->n_tables];
959 memcpy(&table->params, params, sizeof(*params));
962 pipeline->n_tables++;