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
++;