1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_cycles.h>
11 #include "rte_eth_softnic_internals.h"
14 * Master thread: data plane thread init
17 softnic_thread_free(struct pmd_internals *softnic)
21 RTE_LCORE_FOREACH_SLAVE(i) {
22 struct softnic_thread *t = &softnic->thread[i];
26 rte_ring_free(t->msgq_req);
29 rte_ring_free(t->msgq_rsp);
34 softnic_thread_init(struct pmd_internals *softnic)
38 RTE_LCORE_FOREACH_SLAVE(i) {
39 char ring_name[NAME_MAX];
40 struct rte_ring *msgq_req, *msgq_rsp;
41 struct softnic_thread *t = &softnic->thread[i];
42 struct softnic_thread_data *t_data = &softnic->thread_data[i];
43 uint32_t cpu_id = rte_lcore_to_socket_id(i);
46 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
50 msgq_req = rte_ring_create(ring_name,
53 RING_F_SP_ENQ | RING_F_SC_DEQ);
55 if (msgq_req == NULL) {
56 softnic_thread_free(softnic);
60 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
64 msgq_rsp = rte_ring_create(ring_name,
67 RING_F_SP_ENQ | RING_F_SC_DEQ);
69 if (msgq_rsp == NULL) {
70 softnic_thread_free(softnic);
74 /* Master thread records */
75 t->msgq_req = msgq_req;
76 t->msgq_rsp = msgq_rsp;
79 /* Data plane thread records */
80 t_data->n_pipelines = 0;
81 t_data->msgq_req = msgq_req;
82 t_data->msgq_rsp = msgq_rsp;
83 t_data->timer_period =
84 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
85 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
86 t_data->time_next_min = t_data->time_next;
93 * Master thread & data plane threads: message passing
95 enum thread_req_type {
99 struct thread_msg_req {
100 enum thread_req_type type;
103 struct thread_msg_rsp {
108 * Data plane threads: message handling
110 static inline struct thread_msg_req *
111 thread_msg_recv(struct rte_ring *msgq_req)
113 struct thread_msg_req *req;
115 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
124 thread_msg_send(struct rte_ring *msgq_rsp,
125 struct thread_msg_rsp *rsp)
130 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
131 } while (status == -ENOBUFS);
135 thread_msg_handle(struct softnic_thread_data *t)
138 struct thread_msg_req *req;
139 struct thread_msg_rsp *rsp;
141 req = thread_msg_recv(t->msgq_req);
147 rsp = (struct thread_msg_rsp *)req;
151 thread_msg_send(t->msgq_rsp, rsp);
156 * Master thread & data plane threads: message passing
158 enum pipeline_req_type {
162 struct pipeline_msg_req {
163 enum pipeline_req_type type;
166 struct pipeline_msg_rsp {
171 * Data plane threads: message handling
173 static inline struct pipeline_msg_req *
174 pipeline_msg_recv(struct rte_ring *msgq_req)
176 struct pipeline_msg_req *req;
178 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
187 pipeline_msg_send(struct rte_ring *msgq_rsp,
188 struct pipeline_msg_rsp *rsp)
193 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
194 } while (status == -ENOBUFS);
198 pipeline_msg_handle(struct pipeline_data *p)
201 struct pipeline_msg_req *req;
202 struct pipeline_msg_rsp *rsp;
204 req = pipeline_msg_recv(p->msgq_req);
210 rsp = (struct pipeline_msg_rsp *)req;
214 pipeline_msg_send(p->msgq_rsp, rsp);
219 * Data plane threads: main
222 rte_pmd_softnic_run(uint16_t port_id)
224 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
225 struct pmd_internals *softnic;
226 struct softnic_thread_data *t;
227 uint32_t thread_id, j;
229 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
230 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
233 softnic = dev->data->dev_private;
234 thread_id = rte_lcore_id();
235 t = &softnic->thread_data[thread_id];
239 for (j = 0; j < t->n_pipelines; j++)
240 rte_pipeline_run(t->p[j]);
243 if ((t->iter & 0xFLLU) == 0) {
244 uint64_t time = rte_get_tsc_cycles();
245 uint64_t time_next_min = UINT64_MAX;
247 if (time < t->time_next_min)
250 /* Pipeline message queues */
251 for (j = 0; j < t->n_pipelines; j++) {
252 struct pipeline_data *p =
253 &t->pipeline_data[j];
254 uint64_t time_next = p->time_next;
256 if (time_next <= time) {
257 pipeline_msg_handle(p);
258 rte_pipeline_flush(p->p);
259 time_next = time + p->timer_period;
260 p->time_next = time_next;
263 if (time_next < time_next_min)
264 time_next_min = time_next;
267 /* Thread message queues */
269 uint64_t time_next = t->time_next;
271 if (time_next <= time) {
272 thread_msg_handle(t);
273 time_next = time + t->timer_period;
274 t->time_next = time_next;
277 if (time_next < time_next_min)
278 time_next_min = time_next;
281 t->time_next_min = time_next_min;