7a3bbf86b3ddd0c9e7c7b803d7bbc0d3a56843f5
[dpdk.git] / examples / ip_pipeline / thread_fe.c
1 #include <rte_common.h>
2 #include <rte_ring.h>
3 #include <rte_malloc.h>
4 #include <cmdline_rdline.h>
5 #include <cmdline_parse.h>
6 #include <cmdline_parse_num.h>
7 #include <cmdline_parse_string.h>
8 #include <cmdline_parse_ipaddr.h>
9 #include <cmdline_parse_etheraddr.h>
10 #include <cmdline_socket.h>
11 #include <cmdline.h>
12
13 #include "thread.h"
14 #include "thread_fe.h"
15 #include "pipeline.h"
16 #include "pipeline_common_fe.h"
17 #include "app.h"
18
19 static inline void *
20 thread_msg_send_recv(struct app_params *app,
21         uint32_t socket_id, uint32_t core_id, uint32_t ht_id,
22         void *msg,
23         uint32_t timeout_ms)
24 {
25         struct rte_ring *r_req = app_thread_msgq_in_get(app,
26                 socket_id, core_id, ht_id);
27         struct rte_ring *r_rsp = app_thread_msgq_out_get(app,
28                 socket_id, core_id, ht_id);
29         uint64_t hz = rte_get_tsc_hz();
30         void *msg_recv;
31         uint64_t deadline;
32         int status;
33
34         /* send */
35         do {
36                 status = rte_ring_sp_enqueue(r_req, (void *) msg);
37         } while (status == -ENOBUFS);
38
39         /* recv */
40         deadline = (timeout_ms) ?
41                 (rte_rdtsc() + ((hz * timeout_ms) / 1000)) :
42                 UINT64_MAX;
43
44         do {
45                 if (rte_rdtsc() > deadline)
46                         return NULL;
47
48                 status = rte_ring_sc_dequeue(r_rsp, &msg_recv);
49         } while (status != 0);
50
51         return msg_recv;
52 }
53
54 int
55 app_pipeline_enable(struct app_params *app,
56                 uint32_t socket_id,
57                 uint32_t core_id,
58                 uint32_t hyper_th_id,
59                 uint32_t pipeline_id)
60 {
61         struct thread_pipeline_enable_msg_req *req;
62         struct thread_pipeline_enable_msg_rsp *rsp;
63         int thread_id;
64         struct app_pipeline_data *p;
65         struct app_pipeline_params *p_params;
66         struct pipeline_type *p_type;
67         int status;
68
69         if (app == NULL)
70                 return -1;
71
72         thread_id = cpu_core_map_get_lcore_id(app->core_map,
73                         socket_id,
74                         core_id,
75                         hyper_th_id);
76
77         if ((thread_id < 0) ||
78                 ((app->core_mask & (1LLU << thread_id)) == 0))
79                 return -1;
80
81         if (app_pipeline_data(app, pipeline_id) == NULL)
82                 return -1;
83
84         p = &app->pipeline_data[pipeline_id];
85         p_params = &app->pipeline_params[pipeline_id];
86         p_type = app_pipeline_type_find(app, p_params->type);
87
88         if (p->enabled == 1)
89                 return -1;
90
91         req = app_msg_alloc(app);
92         if (req == NULL)
93                 return -1;
94
95         req->type = THREAD_MSG_REQ_PIPELINE_ENABLE;
96         req->pipeline_id = pipeline_id;
97         req->be = p->be;
98         req->f_run = p_type->be_ops->f_run;
99         req->f_timer = p_type->be_ops->f_timer;
100         req->timer_period = p->timer_period;
101
102         rsp = thread_msg_send_recv(app,
103                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
104         if (rsp == NULL)
105                 return -1;
106
107         status = rsp->status;
108         app_msg_free(app, rsp);
109
110         if (status != 0)
111                 return -1;
112
113         p->enabled = 1;
114         return 0;
115 }
116
117 int
118 app_pipeline_disable(struct app_params *app,
119                 uint32_t socket_id,
120                 uint32_t core_id,
121                 uint32_t hyper_th_id,
122                 uint32_t pipeline_id)
123 {
124         struct thread_pipeline_disable_msg_req *req;
125         struct thread_pipeline_disable_msg_rsp *rsp;
126         int thread_id;
127         struct app_pipeline_data *p;
128         int status;
129
130         if (app == NULL)
131                 return -1;
132
133         thread_id = cpu_core_map_get_lcore_id(app->core_map,
134                         socket_id,
135                         core_id,
136                         hyper_th_id);
137
138         if ((thread_id < 0) ||
139                 ((app->core_mask & (1LLU << thread_id)) == 0))
140                 return -1;
141
142         if (app_pipeline_data(app, pipeline_id) == NULL)
143                 return -1;
144
145         p = &app->pipeline_data[pipeline_id];
146
147         if (p->enabled == 0)
148                 return -1;
149
150         req = app_msg_alloc(app);
151         if (req == NULL)
152                 return -1;
153
154         req->type = THREAD_MSG_REQ_PIPELINE_DISABLE;
155         req->pipeline_id = pipeline_id;
156
157         rsp = thread_msg_send_recv(app,
158                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
159
160         if (rsp == NULL)
161                 return -1;
162
163         status = rsp->status;
164         app_msg_free(app, rsp);
165
166         if (status != 0)
167                 return -1;
168
169         p->enabled = 0;
170         return 0;
171 }
172
173 /*
174  * pipeline enable
175  */
176
177 struct cmd_pipeline_enable_result {
178         cmdline_fixed_string_t t_string;
179         cmdline_fixed_string_t t_id_string;
180         cmdline_fixed_string_t pipeline_string;
181         uint32_t pipeline_id;
182         cmdline_fixed_string_t enable_string;
183 };
184
185 static void
186 cmd_pipeline_enable_parsed(
187         void *parsed_result,
188         __rte_unused struct cmdline *cl,
189          void *data)
190 {
191         struct cmd_pipeline_enable_result *params = parsed_result;
192         struct app_params *app = data;
193         int status;
194         uint32_t core_id, socket_id, hyper_th_id;
195
196         if (parse_pipeline_core(&socket_id,
197                         &core_id,
198                         &hyper_th_id,
199                         params->t_id_string) != 0) {
200                 printf("Command failed\n");
201                 return;
202         }
203
204         status = app_pipeline_enable(app,
205                         socket_id,
206                         core_id,
207                         hyper_th_id,
208                         params->pipeline_id);
209
210         if (status != 0)
211                 printf("Command failed\n");
212 }
213
214 cmdline_parse_token_string_t cmd_pipeline_enable_t_string =
215         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t");
216
217 cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =
218         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string,
219                 NULL);
220
221 cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =
222         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string,
223                 "pipeline");
224
225 cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =
226         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id,
227                 UINT32);
228
229 cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =
230         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string,
231                 "enable");
232
233 cmdline_parse_inst_t cmd_pipeline_enable = {
234         .f = cmd_pipeline_enable_parsed,
235         .data = NULL,
236         .help_str = "Enable pipeline on specified core",
237         .tokens = {
238                 (void *)&cmd_pipeline_enable_t_string,
239                 (void *)&cmd_pipeline_enable_t_id_string,
240                 (void *)&cmd_pipeline_enable_pipeline_string,
241                 (void *)&cmd_pipeline_enable_pipeline_id,
242                 (void *)&cmd_pipeline_enable_enable_string,
243                 NULL,
244         },
245 };
246
247 /*
248  * pipeline disable
249  */
250
251 struct cmd_pipeline_disable_result {
252         cmdline_fixed_string_t t_string;
253         cmdline_fixed_string_t t_id_string;
254         cmdline_fixed_string_t pipeline_string;
255         uint32_t pipeline_id;
256         cmdline_fixed_string_t disable_string;
257 };
258
259 static void
260 cmd_pipeline_disable_parsed(
261         void *parsed_result,
262         __rte_unused struct cmdline *cl,
263          void *data)
264 {
265         struct cmd_pipeline_disable_result *params = parsed_result;
266         struct app_params *app = data;
267         int status;
268         uint32_t core_id, socket_id, hyper_th_id;
269
270         if (parse_pipeline_core(&socket_id,
271                         &core_id,
272                         &hyper_th_id,
273                         params->t_id_string) != 0) {
274                 printf("Command failed\n");
275                 return;
276         }
277
278         status = app_pipeline_disable(app,
279                         socket_id,
280                         core_id,
281                         hyper_th_id,
282                         params->pipeline_id);
283
284         if (status != 0)
285                 printf("Command failed\n");
286 }
287
288 cmdline_parse_token_string_t cmd_pipeline_disable_t_string =
289         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t");
290
291 cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =
292         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string,
293                 NULL);
294
295 cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =
296         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result,
297                 pipeline_string, "pipeline");
298
299 cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =
300         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id,
301                 UINT32);
302
303 cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =
304         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string,
305                 "disable");
306
307 cmdline_parse_inst_t cmd_pipeline_disable = {
308         .f = cmd_pipeline_disable_parsed,
309         .data = NULL,
310         .help_str = "Disable pipeline on specified core",
311         .tokens = {
312                 (void *)&cmd_pipeline_disable_t_string,
313                 (void *)&cmd_pipeline_disable_t_id_string,
314                 (void *)&cmd_pipeline_disable_pipeline_string,
315                 (void *)&cmd_pipeline_disable_pipeline_id,
316                 (void *)&cmd_pipeline_disable_disable_string,
317                 NULL,
318         },
319 };
320
321 static cmdline_parse_ctx_t thread_cmds[] = {
322         (cmdline_parse_inst_t *) &cmd_pipeline_enable,
323         (cmdline_parse_inst_t *) &cmd_pipeline_disable,
324         NULL,
325 };
326
327 int
328 app_pipeline_thread_cmd_push(struct app_params *app)
329 {
330         uint32_t n_cmds, i;
331
332         /* Check for available slots in the application commands array */
333         n_cmds = RTE_DIM(thread_cmds) - 1;
334         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
335                 return -ENOMEM;
336
337         /* Push thread commands into the application */
338         memcpy(&app->cmds[app->n_cmds],
339                         thread_cmds,
340                 n_cmds * sizeof(cmdline_parse_ctx_t *));
341
342         for (i = 0; i < n_cmds; i++)
343                 app->cmds[app->n_cmds + i]->data = app;
344
345         app->n_cmds += n_cmds;
346         app->cmds[app->n_cmds] = NULL;
347
348         return 0;
349 }