xref: /f-stack/dpdk/examples/pipeline/thread.c (revision 2d9fd380)
1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606  * Copyright(c) 2020 Intel Corporation
3*2d9fd380Sjfb8856606  */
4*2d9fd380Sjfb8856606 
5*2d9fd380Sjfb8856606 #include <stdlib.h>
6*2d9fd380Sjfb8856606 
7*2d9fd380Sjfb8856606 #include <rte_common.h>
8*2d9fd380Sjfb8856606 #include <rte_cycles.h>
9*2d9fd380Sjfb8856606 #include <rte_lcore.h>
10*2d9fd380Sjfb8856606 #include <rte_ring.h>
11*2d9fd380Sjfb8856606 
12*2d9fd380Sjfb8856606 #include <rte_table_acl.h>
13*2d9fd380Sjfb8856606 #include <rte_table_array.h>
14*2d9fd380Sjfb8856606 #include <rte_table_hash.h>
15*2d9fd380Sjfb8856606 #include <rte_table_lpm.h>
16*2d9fd380Sjfb8856606 #include <rte_table_lpm_ipv6.h>
17*2d9fd380Sjfb8856606 
18*2d9fd380Sjfb8856606 #include "obj.h"
19*2d9fd380Sjfb8856606 #include "thread.h"
20*2d9fd380Sjfb8856606 
21*2d9fd380Sjfb8856606 #ifndef THREAD_PIPELINES_MAX
22*2d9fd380Sjfb8856606 #define THREAD_PIPELINES_MAX                               256
23*2d9fd380Sjfb8856606 #endif
24*2d9fd380Sjfb8856606 
25*2d9fd380Sjfb8856606 #ifndef THREAD_MSGQ_SIZE
26*2d9fd380Sjfb8856606 #define THREAD_MSGQ_SIZE                                   64
27*2d9fd380Sjfb8856606 #endif
28*2d9fd380Sjfb8856606 
29*2d9fd380Sjfb8856606 #ifndef THREAD_TIMER_PERIOD_MS
30*2d9fd380Sjfb8856606 #define THREAD_TIMER_PERIOD_MS                             100
31*2d9fd380Sjfb8856606 #endif
32*2d9fd380Sjfb8856606 
33*2d9fd380Sjfb8856606 /**
34*2d9fd380Sjfb8856606  * Control thread: data plane thread context
35*2d9fd380Sjfb8856606  */
36*2d9fd380Sjfb8856606 struct thread {
37*2d9fd380Sjfb8856606 	struct rte_ring *msgq_req;
38*2d9fd380Sjfb8856606 	struct rte_ring *msgq_rsp;
39*2d9fd380Sjfb8856606 
40*2d9fd380Sjfb8856606 	uint32_t enabled;
41*2d9fd380Sjfb8856606 };
42*2d9fd380Sjfb8856606 
43*2d9fd380Sjfb8856606 static struct thread thread[RTE_MAX_LCORE];
44*2d9fd380Sjfb8856606 
45*2d9fd380Sjfb8856606 /**
46*2d9fd380Sjfb8856606  * Data plane threads: context
47*2d9fd380Sjfb8856606  */
48*2d9fd380Sjfb8856606 struct pipeline_data {
49*2d9fd380Sjfb8856606 	struct rte_swx_pipeline *p;
50*2d9fd380Sjfb8856606 	uint64_t timer_period; /* Measured in CPU cycles. */
51*2d9fd380Sjfb8856606 	uint64_t time_next;
52*2d9fd380Sjfb8856606 };
53*2d9fd380Sjfb8856606 
54*2d9fd380Sjfb8856606 struct thread_data {
55*2d9fd380Sjfb8856606 	struct rte_swx_pipeline *p[THREAD_PIPELINES_MAX];
56*2d9fd380Sjfb8856606 	uint32_t n_pipelines;
57*2d9fd380Sjfb8856606 
58*2d9fd380Sjfb8856606 	struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX];
59*2d9fd380Sjfb8856606 	struct rte_ring *msgq_req;
60*2d9fd380Sjfb8856606 	struct rte_ring *msgq_rsp;
61*2d9fd380Sjfb8856606 	uint64_t timer_period; /* Measured in CPU cycles. */
62*2d9fd380Sjfb8856606 	uint64_t time_next;
63*2d9fd380Sjfb8856606 	uint64_t time_next_min;
64*2d9fd380Sjfb8856606 } __rte_cache_aligned;
65*2d9fd380Sjfb8856606 
66*2d9fd380Sjfb8856606 static struct thread_data thread_data[RTE_MAX_LCORE];
67*2d9fd380Sjfb8856606 
68*2d9fd380Sjfb8856606 /**
69*2d9fd380Sjfb8856606  * Control thread: data plane thread init
70*2d9fd380Sjfb8856606  */
71*2d9fd380Sjfb8856606 static void
thread_free(void)72*2d9fd380Sjfb8856606 thread_free(void)
73*2d9fd380Sjfb8856606 {
74*2d9fd380Sjfb8856606 	uint32_t i;
75*2d9fd380Sjfb8856606 
76*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_MAX_LCORE; i++) {
77*2d9fd380Sjfb8856606 		struct thread *t = &thread[i];
78*2d9fd380Sjfb8856606 
79*2d9fd380Sjfb8856606 		if (!rte_lcore_is_enabled(i))
80*2d9fd380Sjfb8856606 			continue;
81*2d9fd380Sjfb8856606 
82*2d9fd380Sjfb8856606 		/* MSGQs */
83*2d9fd380Sjfb8856606 		if (t->msgq_req)
84*2d9fd380Sjfb8856606 			rte_ring_free(t->msgq_req);
85*2d9fd380Sjfb8856606 
86*2d9fd380Sjfb8856606 		if (t->msgq_rsp)
87*2d9fd380Sjfb8856606 			rte_ring_free(t->msgq_rsp);
88*2d9fd380Sjfb8856606 	}
89*2d9fd380Sjfb8856606 }
90*2d9fd380Sjfb8856606 
91*2d9fd380Sjfb8856606 int
thread_init(void)92*2d9fd380Sjfb8856606 thread_init(void)
93*2d9fd380Sjfb8856606 {
94*2d9fd380Sjfb8856606 	uint32_t i;
95*2d9fd380Sjfb8856606 
96*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(i) {
97*2d9fd380Sjfb8856606 		char name[NAME_MAX];
98*2d9fd380Sjfb8856606 		struct rte_ring *msgq_req, *msgq_rsp;
99*2d9fd380Sjfb8856606 		struct thread *t = &thread[i];
100*2d9fd380Sjfb8856606 		struct thread_data *t_data = &thread_data[i];
101*2d9fd380Sjfb8856606 		uint32_t cpu_id = rte_lcore_to_socket_id(i);
102*2d9fd380Sjfb8856606 
103*2d9fd380Sjfb8856606 		/* MSGQs */
104*2d9fd380Sjfb8856606 		snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i);
105*2d9fd380Sjfb8856606 
106*2d9fd380Sjfb8856606 		msgq_req = rte_ring_create(name,
107*2d9fd380Sjfb8856606 			THREAD_MSGQ_SIZE,
108*2d9fd380Sjfb8856606 			cpu_id,
109*2d9fd380Sjfb8856606 			RING_F_SP_ENQ | RING_F_SC_DEQ);
110*2d9fd380Sjfb8856606 
111*2d9fd380Sjfb8856606 		if (msgq_req == NULL) {
112*2d9fd380Sjfb8856606 			thread_free();
113*2d9fd380Sjfb8856606 			return -1;
114*2d9fd380Sjfb8856606 		}
115*2d9fd380Sjfb8856606 
116*2d9fd380Sjfb8856606 		snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i);
117*2d9fd380Sjfb8856606 
118*2d9fd380Sjfb8856606 		msgq_rsp = rte_ring_create(name,
119*2d9fd380Sjfb8856606 			THREAD_MSGQ_SIZE,
120*2d9fd380Sjfb8856606 			cpu_id,
121*2d9fd380Sjfb8856606 			RING_F_SP_ENQ | RING_F_SC_DEQ);
122*2d9fd380Sjfb8856606 
123*2d9fd380Sjfb8856606 		if (msgq_rsp == NULL) {
124*2d9fd380Sjfb8856606 			thread_free();
125*2d9fd380Sjfb8856606 			return -1;
126*2d9fd380Sjfb8856606 		}
127*2d9fd380Sjfb8856606 
128*2d9fd380Sjfb8856606 		/* Control thread records */
129*2d9fd380Sjfb8856606 		t->msgq_req = msgq_req;
130*2d9fd380Sjfb8856606 		t->msgq_rsp = msgq_rsp;
131*2d9fd380Sjfb8856606 		t->enabled = 1;
132*2d9fd380Sjfb8856606 
133*2d9fd380Sjfb8856606 		/* Data plane thread records */
134*2d9fd380Sjfb8856606 		t_data->n_pipelines = 0;
135*2d9fd380Sjfb8856606 		t_data->msgq_req = msgq_req;
136*2d9fd380Sjfb8856606 		t_data->msgq_rsp = msgq_rsp;
137*2d9fd380Sjfb8856606 		t_data->timer_period =
138*2d9fd380Sjfb8856606 			(rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
139*2d9fd380Sjfb8856606 		t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
140*2d9fd380Sjfb8856606 		t_data->time_next_min = t_data->time_next;
141*2d9fd380Sjfb8856606 	}
142*2d9fd380Sjfb8856606 
143*2d9fd380Sjfb8856606 	return 0;
144*2d9fd380Sjfb8856606 }
145*2d9fd380Sjfb8856606 
146*2d9fd380Sjfb8856606 static inline int
thread_is_running(uint32_t thread_id)147*2d9fd380Sjfb8856606 thread_is_running(uint32_t thread_id)
148*2d9fd380Sjfb8856606 {
149*2d9fd380Sjfb8856606 	enum rte_lcore_state_t thread_state;
150*2d9fd380Sjfb8856606 
151*2d9fd380Sjfb8856606 	thread_state = rte_eal_get_lcore_state(thread_id);
152*2d9fd380Sjfb8856606 	return (thread_state == RUNNING) ? 1 : 0;
153*2d9fd380Sjfb8856606 }
154*2d9fd380Sjfb8856606 
155*2d9fd380Sjfb8856606 /**
156*2d9fd380Sjfb8856606  * Control thread & data plane threads: message passing
157*2d9fd380Sjfb8856606  */
158*2d9fd380Sjfb8856606 enum thread_req_type {
159*2d9fd380Sjfb8856606 	THREAD_REQ_PIPELINE_ENABLE = 0,
160*2d9fd380Sjfb8856606 	THREAD_REQ_PIPELINE_DISABLE,
161*2d9fd380Sjfb8856606 	THREAD_REQ_MAX
162*2d9fd380Sjfb8856606 };
163*2d9fd380Sjfb8856606 
164*2d9fd380Sjfb8856606 struct thread_msg_req {
165*2d9fd380Sjfb8856606 	enum thread_req_type type;
166*2d9fd380Sjfb8856606 
167*2d9fd380Sjfb8856606 	union {
168*2d9fd380Sjfb8856606 		struct {
169*2d9fd380Sjfb8856606 			struct rte_swx_pipeline *p;
170*2d9fd380Sjfb8856606 			uint32_t timer_period_ms;
171*2d9fd380Sjfb8856606 		} pipeline_enable;
172*2d9fd380Sjfb8856606 
173*2d9fd380Sjfb8856606 		struct {
174*2d9fd380Sjfb8856606 			struct rte_swx_pipeline *p;
175*2d9fd380Sjfb8856606 		} pipeline_disable;
176*2d9fd380Sjfb8856606 	};
177*2d9fd380Sjfb8856606 };
178*2d9fd380Sjfb8856606 
179*2d9fd380Sjfb8856606 struct thread_msg_rsp {
180*2d9fd380Sjfb8856606 	int status;
181*2d9fd380Sjfb8856606 };
182*2d9fd380Sjfb8856606 
183*2d9fd380Sjfb8856606 /**
184*2d9fd380Sjfb8856606  * Control thread
185*2d9fd380Sjfb8856606  */
186*2d9fd380Sjfb8856606 static struct thread_msg_req *
thread_msg_alloc(void)187*2d9fd380Sjfb8856606 thread_msg_alloc(void)
188*2d9fd380Sjfb8856606 {
189*2d9fd380Sjfb8856606 	size_t size = RTE_MAX(sizeof(struct thread_msg_req),
190*2d9fd380Sjfb8856606 		sizeof(struct thread_msg_rsp));
191*2d9fd380Sjfb8856606 
192*2d9fd380Sjfb8856606 	return calloc(1, size);
193*2d9fd380Sjfb8856606 }
194*2d9fd380Sjfb8856606 
195*2d9fd380Sjfb8856606 static void
thread_msg_free(struct thread_msg_rsp * rsp)196*2d9fd380Sjfb8856606 thread_msg_free(struct thread_msg_rsp *rsp)
197*2d9fd380Sjfb8856606 {
198*2d9fd380Sjfb8856606 	free(rsp);
199*2d9fd380Sjfb8856606 }
200*2d9fd380Sjfb8856606 
201*2d9fd380Sjfb8856606 static struct thread_msg_rsp *
thread_msg_send_recv(uint32_t thread_id,struct thread_msg_req * req)202*2d9fd380Sjfb8856606 thread_msg_send_recv(uint32_t thread_id,
203*2d9fd380Sjfb8856606 	struct thread_msg_req *req)
204*2d9fd380Sjfb8856606 {
205*2d9fd380Sjfb8856606 	struct thread *t = &thread[thread_id];
206*2d9fd380Sjfb8856606 	struct rte_ring *msgq_req = t->msgq_req;
207*2d9fd380Sjfb8856606 	struct rte_ring *msgq_rsp = t->msgq_rsp;
208*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp;
209*2d9fd380Sjfb8856606 	int status;
210*2d9fd380Sjfb8856606 
211*2d9fd380Sjfb8856606 	/* send */
212*2d9fd380Sjfb8856606 	do {
213*2d9fd380Sjfb8856606 		status = rte_ring_sp_enqueue(msgq_req, req);
214*2d9fd380Sjfb8856606 	} while (status == -ENOBUFS);
215*2d9fd380Sjfb8856606 
216*2d9fd380Sjfb8856606 	/* recv */
217*2d9fd380Sjfb8856606 	do {
218*2d9fd380Sjfb8856606 		status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp);
219*2d9fd380Sjfb8856606 	} while (status != 0);
220*2d9fd380Sjfb8856606 
221*2d9fd380Sjfb8856606 	return rsp;
222*2d9fd380Sjfb8856606 }
223*2d9fd380Sjfb8856606 
224*2d9fd380Sjfb8856606 int
thread_pipeline_enable(uint32_t thread_id,struct obj * obj,const char * pipeline_name)225*2d9fd380Sjfb8856606 thread_pipeline_enable(uint32_t thread_id,
226*2d9fd380Sjfb8856606 	struct obj *obj,
227*2d9fd380Sjfb8856606 	const char *pipeline_name)
228*2d9fd380Sjfb8856606 {
229*2d9fd380Sjfb8856606 	struct pipeline *p = pipeline_find(obj, pipeline_name);
230*2d9fd380Sjfb8856606 	struct thread *t;
231*2d9fd380Sjfb8856606 	struct thread_msg_req *req;
232*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp;
233*2d9fd380Sjfb8856606 	int status;
234*2d9fd380Sjfb8856606 
235*2d9fd380Sjfb8856606 	/* Check input params */
236*2d9fd380Sjfb8856606 	if ((thread_id >= RTE_MAX_LCORE) ||
237*2d9fd380Sjfb8856606 		(p == NULL))
238*2d9fd380Sjfb8856606 		return -1;
239*2d9fd380Sjfb8856606 
240*2d9fd380Sjfb8856606 	t = &thread[thread_id];
241*2d9fd380Sjfb8856606 	if (t->enabled == 0)
242*2d9fd380Sjfb8856606 		return -1;
243*2d9fd380Sjfb8856606 
244*2d9fd380Sjfb8856606 	if (!thread_is_running(thread_id)) {
245*2d9fd380Sjfb8856606 		struct thread_data *td = &thread_data[thread_id];
246*2d9fd380Sjfb8856606 		struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
247*2d9fd380Sjfb8856606 
248*2d9fd380Sjfb8856606 		if (td->n_pipelines >= THREAD_PIPELINES_MAX)
249*2d9fd380Sjfb8856606 			return -1;
250*2d9fd380Sjfb8856606 
251*2d9fd380Sjfb8856606 		/* Data plane thread */
252*2d9fd380Sjfb8856606 		td->p[td->n_pipelines] = p->p;
253*2d9fd380Sjfb8856606 
254*2d9fd380Sjfb8856606 		tdp->p = p->p;
255*2d9fd380Sjfb8856606 		tdp->timer_period =
256*2d9fd380Sjfb8856606 			(rte_get_tsc_hz() * p->timer_period_ms) / 1000;
257*2d9fd380Sjfb8856606 		tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
258*2d9fd380Sjfb8856606 
259*2d9fd380Sjfb8856606 		td->n_pipelines++;
260*2d9fd380Sjfb8856606 
261*2d9fd380Sjfb8856606 		/* Pipeline */
262*2d9fd380Sjfb8856606 		p->thread_id = thread_id;
263*2d9fd380Sjfb8856606 		p->enabled = 1;
264*2d9fd380Sjfb8856606 
265*2d9fd380Sjfb8856606 		return 0;
266*2d9fd380Sjfb8856606 	}
267*2d9fd380Sjfb8856606 
268*2d9fd380Sjfb8856606 	/* Allocate request */
269*2d9fd380Sjfb8856606 	req = thread_msg_alloc();
270*2d9fd380Sjfb8856606 	if (req == NULL)
271*2d9fd380Sjfb8856606 		return -1;
272*2d9fd380Sjfb8856606 
273*2d9fd380Sjfb8856606 	/* Write request */
274*2d9fd380Sjfb8856606 	req->type = THREAD_REQ_PIPELINE_ENABLE;
275*2d9fd380Sjfb8856606 	req->pipeline_enable.p = p->p;
276*2d9fd380Sjfb8856606 	req->pipeline_enable.timer_period_ms = p->timer_period_ms;
277*2d9fd380Sjfb8856606 
278*2d9fd380Sjfb8856606 	/* Send request and wait for response */
279*2d9fd380Sjfb8856606 	rsp = thread_msg_send_recv(thread_id, req);
280*2d9fd380Sjfb8856606 
281*2d9fd380Sjfb8856606 	/* Read response */
282*2d9fd380Sjfb8856606 	status = rsp->status;
283*2d9fd380Sjfb8856606 
284*2d9fd380Sjfb8856606 	/* Free response */
285*2d9fd380Sjfb8856606 	thread_msg_free(rsp);
286*2d9fd380Sjfb8856606 
287*2d9fd380Sjfb8856606 	/* Request completion */
288*2d9fd380Sjfb8856606 	if (status)
289*2d9fd380Sjfb8856606 		return status;
290*2d9fd380Sjfb8856606 
291*2d9fd380Sjfb8856606 	p->thread_id = thread_id;
292*2d9fd380Sjfb8856606 	p->enabled = 1;
293*2d9fd380Sjfb8856606 
294*2d9fd380Sjfb8856606 	return 0;
295*2d9fd380Sjfb8856606 }
296*2d9fd380Sjfb8856606 
297*2d9fd380Sjfb8856606 int
thread_pipeline_disable(uint32_t thread_id,struct obj * obj,const char * pipeline_name)298*2d9fd380Sjfb8856606 thread_pipeline_disable(uint32_t thread_id,
299*2d9fd380Sjfb8856606 	struct obj *obj,
300*2d9fd380Sjfb8856606 	const char *pipeline_name)
301*2d9fd380Sjfb8856606 {
302*2d9fd380Sjfb8856606 	struct pipeline *p = pipeline_find(obj, pipeline_name);
303*2d9fd380Sjfb8856606 	struct thread *t;
304*2d9fd380Sjfb8856606 	struct thread_msg_req *req;
305*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp;
306*2d9fd380Sjfb8856606 	int status;
307*2d9fd380Sjfb8856606 
308*2d9fd380Sjfb8856606 	/* Check input params */
309*2d9fd380Sjfb8856606 	if ((thread_id >= RTE_MAX_LCORE) ||
310*2d9fd380Sjfb8856606 		(p == NULL))
311*2d9fd380Sjfb8856606 		return -1;
312*2d9fd380Sjfb8856606 
313*2d9fd380Sjfb8856606 	t = &thread[thread_id];
314*2d9fd380Sjfb8856606 	if (t->enabled == 0)
315*2d9fd380Sjfb8856606 		return -1;
316*2d9fd380Sjfb8856606 
317*2d9fd380Sjfb8856606 	if (p->enabled == 0)
318*2d9fd380Sjfb8856606 		return 0;
319*2d9fd380Sjfb8856606 
320*2d9fd380Sjfb8856606 	if (p->thread_id != thread_id)
321*2d9fd380Sjfb8856606 		return -1;
322*2d9fd380Sjfb8856606 
323*2d9fd380Sjfb8856606 	if (!thread_is_running(thread_id)) {
324*2d9fd380Sjfb8856606 		struct thread_data *td = &thread_data[thread_id];
325*2d9fd380Sjfb8856606 		uint32_t i;
326*2d9fd380Sjfb8856606 
327*2d9fd380Sjfb8856606 		for (i = 0; i < td->n_pipelines; i++) {
328*2d9fd380Sjfb8856606 			struct pipeline_data *tdp = &td->pipeline_data[i];
329*2d9fd380Sjfb8856606 
330*2d9fd380Sjfb8856606 			if (tdp->p != p->p)
331*2d9fd380Sjfb8856606 				continue;
332*2d9fd380Sjfb8856606 
333*2d9fd380Sjfb8856606 			/* Data plane thread */
334*2d9fd380Sjfb8856606 			if (i < td->n_pipelines - 1) {
335*2d9fd380Sjfb8856606 				struct rte_swx_pipeline *pipeline_last =
336*2d9fd380Sjfb8856606 					td->p[td->n_pipelines - 1];
337*2d9fd380Sjfb8856606 				struct pipeline_data *tdp_last =
338*2d9fd380Sjfb8856606 					&td->pipeline_data[td->n_pipelines - 1];
339*2d9fd380Sjfb8856606 
340*2d9fd380Sjfb8856606 				td->p[i] = pipeline_last;
341*2d9fd380Sjfb8856606 				memcpy(tdp, tdp_last, sizeof(*tdp));
342*2d9fd380Sjfb8856606 			}
343*2d9fd380Sjfb8856606 
344*2d9fd380Sjfb8856606 			td->n_pipelines--;
345*2d9fd380Sjfb8856606 
346*2d9fd380Sjfb8856606 			/* Pipeline */
347*2d9fd380Sjfb8856606 			p->enabled = 0;
348*2d9fd380Sjfb8856606 
349*2d9fd380Sjfb8856606 			break;
350*2d9fd380Sjfb8856606 		}
351*2d9fd380Sjfb8856606 
352*2d9fd380Sjfb8856606 		return 0;
353*2d9fd380Sjfb8856606 	}
354*2d9fd380Sjfb8856606 
355*2d9fd380Sjfb8856606 	/* Allocate request */
356*2d9fd380Sjfb8856606 	req = thread_msg_alloc();
357*2d9fd380Sjfb8856606 	if (req == NULL)
358*2d9fd380Sjfb8856606 		return -1;
359*2d9fd380Sjfb8856606 
360*2d9fd380Sjfb8856606 	/* Write request */
361*2d9fd380Sjfb8856606 	req->type = THREAD_REQ_PIPELINE_DISABLE;
362*2d9fd380Sjfb8856606 	req->pipeline_disable.p = p->p;
363*2d9fd380Sjfb8856606 
364*2d9fd380Sjfb8856606 	/* Send request and wait for response */
365*2d9fd380Sjfb8856606 	rsp = thread_msg_send_recv(thread_id, req);
366*2d9fd380Sjfb8856606 
367*2d9fd380Sjfb8856606 	/* Read response */
368*2d9fd380Sjfb8856606 	status = rsp->status;
369*2d9fd380Sjfb8856606 
370*2d9fd380Sjfb8856606 	/* Free response */
371*2d9fd380Sjfb8856606 	thread_msg_free(rsp);
372*2d9fd380Sjfb8856606 
373*2d9fd380Sjfb8856606 	/* Request completion */
374*2d9fd380Sjfb8856606 	if (status)
375*2d9fd380Sjfb8856606 		return status;
376*2d9fd380Sjfb8856606 
377*2d9fd380Sjfb8856606 	p->enabled = 0;
378*2d9fd380Sjfb8856606 
379*2d9fd380Sjfb8856606 	return 0;
380*2d9fd380Sjfb8856606 }
381*2d9fd380Sjfb8856606 
382*2d9fd380Sjfb8856606 /**
383*2d9fd380Sjfb8856606  * Data plane threads: message handling
384*2d9fd380Sjfb8856606  */
385*2d9fd380Sjfb8856606 static inline struct thread_msg_req *
thread_msg_recv(struct rte_ring * msgq_req)386*2d9fd380Sjfb8856606 thread_msg_recv(struct rte_ring *msgq_req)
387*2d9fd380Sjfb8856606 {
388*2d9fd380Sjfb8856606 	struct thread_msg_req *req;
389*2d9fd380Sjfb8856606 
390*2d9fd380Sjfb8856606 	int status = rte_ring_sc_dequeue(msgq_req, (void **) &req);
391*2d9fd380Sjfb8856606 
392*2d9fd380Sjfb8856606 	if (status != 0)
393*2d9fd380Sjfb8856606 		return NULL;
394*2d9fd380Sjfb8856606 
395*2d9fd380Sjfb8856606 	return req;
396*2d9fd380Sjfb8856606 }
397*2d9fd380Sjfb8856606 
398*2d9fd380Sjfb8856606 static inline void
thread_msg_send(struct rte_ring * msgq_rsp,struct thread_msg_rsp * rsp)399*2d9fd380Sjfb8856606 thread_msg_send(struct rte_ring *msgq_rsp,
400*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp)
401*2d9fd380Sjfb8856606 {
402*2d9fd380Sjfb8856606 	int status;
403*2d9fd380Sjfb8856606 
404*2d9fd380Sjfb8856606 	do {
405*2d9fd380Sjfb8856606 		status = rte_ring_sp_enqueue(msgq_rsp, rsp);
406*2d9fd380Sjfb8856606 	} while (status == -ENOBUFS);
407*2d9fd380Sjfb8856606 }
408*2d9fd380Sjfb8856606 
409*2d9fd380Sjfb8856606 static struct thread_msg_rsp *
thread_msg_handle_pipeline_enable(struct thread_data * t,struct thread_msg_req * req)410*2d9fd380Sjfb8856606 thread_msg_handle_pipeline_enable(struct thread_data *t,
411*2d9fd380Sjfb8856606 	struct thread_msg_req *req)
412*2d9fd380Sjfb8856606 {
413*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req;
414*2d9fd380Sjfb8856606 	struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
415*2d9fd380Sjfb8856606 
416*2d9fd380Sjfb8856606 	/* Request */
417*2d9fd380Sjfb8856606 	if (t->n_pipelines >= THREAD_PIPELINES_MAX) {
418*2d9fd380Sjfb8856606 		rsp->status = -1;
419*2d9fd380Sjfb8856606 		return rsp;
420*2d9fd380Sjfb8856606 	}
421*2d9fd380Sjfb8856606 
422*2d9fd380Sjfb8856606 	t->p[t->n_pipelines] = req->pipeline_enable.p;
423*2d9fd380Sjfb8856606 
424*2d9fd380Sjfb8856606 	p->p = req->pipeline_enable.p;
425*2d9fd380Sjfb8856606 	p->timer_period = (rte_get_tsc_hz() *
426*2d9fd380Sjfb8856606 		req->pipeline_enable.timer_period_ms) / 1000;
427*2d9fd380Sjfb8856606 	p->time_next = rte_get_tsc_cycles() + p->timer_period;
428*2d9fd380Sjfb8856606 
429*2d9fd380Sjfb8856606 	t->n_pipelines++;
430*2d9fd380Sjfb8856606 
431*2d9fd380Sjfb8856606 	/* Response */
432*2d9fd380Sjfb8856606 	rsp->status = 0;
433*2d9fd380Sjfb8856606 	return rsp;
434*2d9fd380Sjfb8856606 }
435*2d9fd380Sjfb8856606 
436*2d9fd380Sjfb8856606 static struct thread_msg_rsp *
thread_msg_handle_pipeline_disable(struct thread_data * t,struct thread_msg_req * req)437*2d9fd380Sjfb8856606 thread_msg_handle_pipeline_disable(struct thread_data *t,
438*2d9fd380Sjfb8856606 	struct thread_msg_req *req)
439*2d9fd380Sjfb8856606 {
440*2d9fd380Sjfb8856606 	struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req;
441*2d9fd380Sjfb8856606 	uint32_t n_pipelines = t->n_pipelines;
442*2d9fd380Sjfb8856606 	struct rte_swx_pipeline *pipeline = req->pipeline_disable.p;
443*2d9fd380Sjfb8856606 	uint32_t i;
444*2d9fd380Sjfb8856606 
445*2d9fd380Sjfb8856606 	/* find pipeline */
446*2d9fd380Sjfb8856606 	for (i = 0; i < n_pipelines; i++) {
447*2d9fd380Sjfb8856606 		struct pipeline_data *p = &t->pipeline_data[i];
448*2d9fd380Sjfb8856606 
449*2d9fd380Sjfb8856606 		if (p->p != pipeline)
450*2d9fd380Sjfb8856606 			continue;
451*2d9fd380Sjfb8856606 
452*2d9fd380Sjfb8856606 		if (i < n_pipelines - 1) {
453*2d9fd380Sjfb8856606 			struct rte_swx_pipeline *pipeline_last =
454*2d9fd380Sjfb8856606 				t->p[n_pipelines - 1];
455*2d9fd380Sjfb8856606 			struct pipeline_data *p_last =
456*2d9fd380Sjfb8856606 				&t->pipeline_data[n_pipelines - 1];
457*2d9fd380Sjfb8856606 
458*2d9fd380Sjfb8856606 			t->p[i] = pipeline_last;
459*2d9fd380Sjfb8856606 			memcpy(p, p_last, sizeof(*p));
460*2d9fd380Sjfb8856606 		}
461*2d9fd380Sjfb8856606 
462*2d9fd380Sjfb8856606 		t->n_pipelines--;
463*2d9fd380Sjfb8856606 
464*2d9fd380Sjfb8856606 		rsp->status = 0;
465*2d9fd380Sjfb8856606 		return rsp;
466*2d9fd380Sjfb8856606 	}
467*2d9fd380Sjfb8856606 
468*2d9fd380Sjfb8856606 	/* should not get here */
469*2d9fd380Sjfb8856606 	rsp->status = 0;
470*2d9fd380Sjfb8856606 	return rsp;
471*2d9fd380Sjfb8856606 }
472*2d9fd380Sjfb8856606 
473*2d9fd380Sjfb8856606 static void
thread_msg_handle(struct thread_data * t)474*2d9fd380Sjfb8856606 thread_msg_handle(struct thread_data *t)
475*2d9fd380Sjfb8856606 {
476*2d9fd380Sjfb8856606 	for ( ; ; ) {
477*2d9fd380Sjfb8856606 		struct thread_msg_req *req;
478*2d9fd380Sjfb8856606 		struct thread_msg_rsp *rsp;
479*2d9fd380Sjfb8856606 
480*2d9fd380Sjfb8856606 		req = thread_msg_recv(t->msgq_req);
481*2d9fd380Sjfb8856606 		if (req == NULL)
482*2d9fd380Sjfb8856606 			break;
483*2d9fd380Sjfb8856606 
484*2d9fd380Sjfb8856606 		switch (req->type) {
485*2d9fd380Sjfb8856606 		case THREAD_REQ_PIPELINE_ENABLE:
486*2d9fd380Sjfb8856606 			rsp = thread_msg_handle_pipeline_enable(t, req);
487*2d9fd380Sjfb8856606 			break;
488*2d9fd380Sjfb8856606 
489*2d9fd380Sjfb8856606 		case THREAD_REQ_PIPELINE_DISABLE:
490*2d9fd380Sjfb8856606 			rsp = thread_msg_handle_pipeline_disable(t, req);
491*2d9fd380Sjfb8856606 			break;
492*2d9fd380Sjfb8856606 
493*2d9fd380Sjfb8856606 		default:
494*2d9fd380Sjfb8856606 			rsp = (struct thread_msg_rsp *) req;
495*2d9fd380Sjfb8856606 			rsp->status = -1;
496*2d9fd380Sjfb8856606 		}
497*2d9fd380Sjfb8856606 
498*2d9fd380Sjfb8856606 		thread_msg_send(t->msgq_rsp, rsp);
499*2d9fd380Sjfb8856606 	}
500*2d9fd380Sjfb8856606 }
501*2d9fd380Sjfb8856606 
502*2d9fd380Sjfb8856606 /**
503*2d9fd380Sjfb8856606  * Data plane threads: main
504*2d9fd380Sjfb8856606  */
505*2d9fd380Sjfb8856606 int
thread_main(void * arg __rte_unused)506*2d9fd380Sjfb8856606 thread_main(void *arg __rte_unused)
507*2d9fd380Sjfb8856606 {
508*2d9fd380Sjfb8856606 	struct thread_data *t;
509*2d9fd380Sjfb8856606 	uint32_t thread_id, i;
510*2d9fd380Sjfb8856606 
511*2d9fd380Sjfb8856606 	thread_id = rte_lcore_id();
512*2d9fd380Sjfb8856606 	t = &thread_data[thread_id];
513*2d9fd380Sjfb8856606 
514*2d9fd380Sjfb8856606 	/* Dispatch loop */
515*2d9fd380Sjfb8856606 	for (i = 0; ; i++) {
516*2d9fd380Sjfb8856606 		uint32_t j;
517*2d9fd380Sjfb8856606 
518*2d9fd380Sjfb8856606 		/* Data Plane */
519*2d9fd380Sjfb8856606 		for (j = 0; j < t->n_pipelines; j++)
520*2d9fd380Sjfb8856606 			rte_swx_pipeline_run(t->p[j], 1000000);
521*2d9fd380Sjfb8856606 
522*2d9fd380Sjfb8856606 		/* Control Plane */
523*2d9fd380Sjfb8856606 		if ((i & 0xF) == 0) {
524*2d9fd380Sjfb8856606 			uint64_t time = rte_get_tsc_cycles();
525*2d9fd380Sjfb8856606 			uint64_t time_next_min = UINT64_MAX;
526*2d9fd380Sjfb8856606 
527*2d9fd380Sjfb8856606 			if (time < t->time_next_min)
528*2d9fd380Sjfb8856606 				continue;
529*2d9fd380Sjfb8856606 
530*2d9fd380Sjfb8856606 			/* Thread message queues */
531*2d9fd380Sjfb8856606 			{
532*2d9fd380Sjfb8856606 				uint64_t time_next = t->time_next;
533*2d9fd380Sjfb8856606 
534*2d9fd380Sjfb8856606 				if (time_next <= time) {
535*2d9fd380Sjfb8856606 					thread_msg_handle(t);
536*2d9fd380Sjfb8856606 					time_next = time + t->timer_period;
537*2d9fd380Sjfb8856606 					t->time_next = time_next;
538*2d9fd380Sjfb8856606 				}
539*2d9fd380Sjfb8856606 
540*2d9fd380Sjfb8856606 				if (time_next < time_next_min)
541*2d9fd380Sjfb8856606 					time_next_min = time_next;
542*2d9fd380Sjfb8856606 			}
543*2d9fd380Sjfb8856606 
544*2d9fd380Sjfb8856606 			t->time_next_min = time_next_min;
545*2d9fd380Sjfb8856606 		}
546*2d9fd380Sjfb8856606 	}
547*2d9fd380Sjfb8856606 
548*2d9fd380Sjfb8856606 	return 0;
549*2d9fd380Sjfb8856606 }
550