6c547ca5bc228dd97adf17b5d2b2787a86242ae1
[deb_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
9 #include "thread.h"
10 #include "thread_fe.h"
11 #include "pipeline.h"
12 #include "pipeline_common_fe.h"
13 #include "app.h"
14
15 static inline void *
16 thread_msg_send_recv(struct app_params *app,
17         uint32_t socket_id, uint32_t core_id, uint32_t ht_id,
18         void *msg,
19         uint32_t timeout_ms)
20 {
21         struct rte_ring *r_req = app_thread_msgq_in_get(app,
22                 socket_id, core_id, ht_id);
23         struct rte_ring *r_rsp = app_thread_msgq_out_get(app,
24                 socket_id, core_id, ht_id);
25         uint64_t hz = rte_get_tsc_hz();
26         void *msg_recv;
27         uint64_t deadline;
28         int status;
29
30         /* send */
31         do {
32                 status = rte_ring_sp_enqueue(r_req, (void *) msg);
33         } while (status == -ENOBUFS);
34
35         /* recv */
36         deadline = (timeout_ms) ?
37                 (rte_rdtsc() + ((hz * timeout_ms) / 1000)) :
38                 UINT64_MAX;
39
40         do {
41                 if (rte_rdtsc() > deadline)
42                         return NULL;
43
44                 status = rte_ring_sc_dequeue(r_rsp, &msg_recv);
45         } while (status != 0);
46
47         return msg_recv;
48 }
49
50 int
51 app_pipeline_enable(struct app_params *app,
52                 uint32_t socket_id,
53                 uint32_t core_id,
54                 uint32_t hyper_th_id,
55                 uint32_t pipeline_id)
56 {
57         struct thread_pipeline_enable_msg_req *req;
58         struct thread_pipeline_enable_msg_rsp *rsp;
59         int thread_id;
60         struct app_pipeline_data *p;
61         struct app_pipeline_params *p_params;
62         struct pipeline_type *p_type;
63         int status;
64
65         if (app == NULL)
66                 return -1;
67
68         thread_id = cpu_core_map_get_lcore_id(app->core_map,
69                         socket_id,
70                         core_id,
71                         hyper_th_id);
72
73         if ((thread_id < 0) ||
74                 ((app->core_mask & (1LLU << thread_id)) == 0))
75                 return -1;
76
77         if (app_pipeline_data(app, pipeline_id) == NULL)
78                 return -1;
79
80         p = &app->pipeline_data[pipeline_id];
81         p_params = &app->pipeline_params[pipeline_id];
82         p_type = app_pipeline_type_find(app, p_params->type);
83
84         if (p_type == NULL)
85                 return -1;
86
87         if (p->enabled == 1)
88                 return -1;
89
90         req = app_msg_alloc(app);
91         if (req == NULL)
92                 return -1;
93
94         req->type = THREAD_MSG_REQ_PIPELINE_ENABLE;
95         req->pipeline_id = pipeline_id;
96         req->be = p->be;
97         req->f_run = p_type->be_ops->f_run;
98         req->f_timer = p_type->be_ops->f_timer;
99         req->timer_period = p->timer_period;
100
101         rsp = thread_msg_send_recv(app,
102                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
103         if (rsp == NULL)
104                 return -1;
105
106         status = rsp->status;
107         app_msg_free(app, rsp);
108
109         if (status != 0)
110                 return -1;
111
112         p->enabled = 1;
113         return 0;
114 }
115
116 int
117 app_pipeline_disable(struct app_params *app,
118                 uint32_t socket_id,
119                 uint32_t core_id,
120                 uint32_t hyper_th_id,
121                 uint32_t pipeline_id)
122 {
123         struct thread_pipeline_disable_msg_req *req;
124         struct thread_pipeline_disable_msg_rsp *rsp;
125         int thread_id;
126         struct app_pipeline_data *p;
127         int status;
128
129         if (app == NULL)
130                 return -1;
131
132         thread_id = cpu_core_map_get_lcore_id(app->core_map,
133                         socket_id,
134                         core_id,
135                         hyper_th_id);
136
137         if ((thread_id < 0) ||
138                 ((app->core_mask & (1LLU << thread_id)) == 0))
139                 return -1;
140
141         if (app_pipeline_data(app, pipeline_id) == NULL)
142                 return -1;
143
144         p = &app->pipeline_data[pipeline_id];
145
146         if (p->enabled == 0)
147                 return -1;
148
149         req = app_msg_alloc(app);
150         if (req == NULL)
151                 return -1;
152
153         req->type = THREAD_MSG_REQ_PIPELINE_DISABLE;
154         req->pipeline_id = pipeline_id;
155
156         rsp = thread_msg_send_recv(app,
157                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
158
159         if (rsp == NULL)
160                 return -1;
161
162         status = rsp->status;
163         app_msg_free(app, rsp);
164
165         if (status != 0)
166                 return -1;
167
168         p->enabled = 0;
169         return 0;
170 }
171
172 int
173 app_thread_headroom(struct app_params *app,
174                 uint32_t socket_id,
175                 uint32_t core_id,
176                 uint32_t hyper_th_id)
177 {
178         struct thread_headroom_read_msg_req *req;
179         struct thread_headroom_read_msg_rsp *rsp;
180         int thread_id;
181         int status;
182
183         if (app == NULL)
184                 return -1;
185
186         thread_id = cpu_core_map_get_lcore_id(app->core_map,
187                         socket_id,
188                         core_id,
189                         hyper_th_id);
190
191         if ((thread_id < 0) ||
192                 ((app->core_mask & (1LLU << thread_id)) == 0))
193                 return -1;
194
195         req = app_msg_alloc(app);
196         if (req == NULL)
197                 return -1;
198
199         req->type = THREAD_MSG_REQ_HEADROOM_READ;
200
201         rsp = thread_msg_send_recv(app,
202                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
203
204         if (rsp == NULL)
205                 return -1;
206
207         status = rsp->status;
208
209         if (status != 0)
210                 return -1;
211
212         printf("%.3f%%\n", rsp->headroom_ratio * 100);
213
214
215         app_msg_free(app, rsp);
216
217         return 0;
218 }
219
220 /*
221  * pipeline enable
222  */
223
224 struct cmd_pipeline_enable_result {
225         cmdline_fixed_string_t t_string;
226         cmdline_fixed_string_t t_id_string;
227         cmdline_fixed_string_t pipeline_string;
228         uint32_t pipeline_id;
229         cmdline_fixed_string_t enable_string;
230 };
231
232 static void
233 cmd_pipeline_enable_parsed(
234         void *parsed_result,
235         __rte_unused struct cmdline *cl,
236          void *data)
237 {
238         struct cmd_pipeline_enable_result *params = parsed_result;
239         struct app_params *app = data;
240         int status;
241         uint32_t core_id, socket_id, hyper_th_id;
242
243         if (parse_pipeline_core(&socket_id,
244                         &core_id,
245                         &hyper_th_id,
246                         params->t_id_string) != 0) {
247                 printf("Command failed\n");
248                 return;
249         }
250
251         status = app_pipeline_enable(app,
252                         socket_id,
253                         core_id,
254                         hyper_th_id,
255                         params->pipeline_id);
256
257         if (status != 0)
258                 printf("Command failed\n");
259 }
260
261 static cmdline_parse_token_string_t cmd_pipeline_enable_t_string =
262         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t");
263
264 static cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =
265         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string,
266                 NULL);
267
268 static cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =
269         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string,
270                 "pipeline");
271
272 static cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =
273         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id,
274                 UINT32);
275
276 static cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =
277         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string,
278                 "enable");
279
280 static cmdline_parse_inst_t cmd_pipeline_enable = {
281         .f = cmd_pipeline_enable_parsed,
282         .data = NULL,
283         .help_str = "Enable pipeline on specified core",
284         .tokens = {
285                 (void *)&cmd_pipeline_enable_t_string,
286                 (void *)&cmd_pipeline_enable_t_id_string,
287                 (void *)&cmd_pipeline_enable_pipeline_string,
288                 (void *)&cmd_pipeline_enable_pipeline_id,
289                 (void *)&cmd_pipeline_enable_enable_string,
290                 NULL,
291         },
292 };
293
294 /*
295  * pipeline disable
296  */
297
298 struct cmd_pipeline_disable_result {
299         cmdline_fixed_string_t t_string;
300         cmdline_fixed_string_t t_id_string;
301         cmdline_fixed_string_t pipeline_string;
302         uint32_t pipeline_id;
303         cmdline_fixed_string_t disable_string;
304 };
305
306 static void
307 cmd_pipeline_disable_parsed(
308         void *parsed_result,
309         __rte_unused struct cmdline *cl,
310          void *data)
311 {
312         struct cmd_pipeline_disable_result *params = parsed_result;
313         struct app_params *app = data;
314         int status;
315         uint32_t core_id, socket_id, hyper_th_id;
316
317         if (parse_pipeline_core(&socket_id,
318                         &core_id,
319                         &hyper_th_id,
320                         params->t_id_string) != 0) {
321                 printf("Command failed\n");
322                 return;
323         }
324
325         status = app_pipeline_disable(app,
326                         socket_id,
327                         core_id,
328                         hyper_th_id,
329                         params->pipeline_id);
330
331         if (status != 0)
332                 printf("Command failed\n");
333 }
334
335 static cmdline_parse_token_string_t cmd_pipeline_disable_t_string =
336         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t");
337
338 static cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =
339         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string,
340                 NULL);
341
342 static cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =
343         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result,
344                 pipeline_string, "pipeline");
345
346 static cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =
347         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id,
348                 UINT32);
349
350 static cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =
351         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string,
352                 "disable");
353
354 static cmdline_parse_inst_t cmd_pipeline_disable = {
355         .f = cmd_pipeline_disable_parsed,
356         .data = NULL,
357         .help_str = "Disable pipeline on specified core",
358         .tokens = {
359                 (void *)&cmd_pipeline_disable_t_string,
360                 (void *)&cmd_pipeline_disable_t_id_string,
361                 (void *)&cmd_pipeline_disable_pipeline_string,
362                 (void *)&cmd_pipeline_disable_pipeline_id,
363                 (void *)&cmd_pipeline_disable_disable_string,
364                 NULL,
365         },
366 };
367
368
369 /*
370  * thread headroom
371  */
372
373 struct cmd_thread_headroom_result {
374         cmdline_fixed_string_t t_string;
375         cmdline_fixed_string_t t_id_string;
376         cmdline_fixed_string_t headroom_string;
377 };
378
379 static void
380 cmd_thread_headroom_parsed(
381         void *parsed_result,
382         __rte_unused struct cmdline *cl,
383          void *data)
384 {
385         struct cmd_thread_headroom_result *params = parsed_result;
386         struct app_params *app = data;
387         int status;
388         uint32_t core_id, socket_id, hyper_th_id;
389
390         if (parse_pipeline_core(&socket_id,
391                         &core_id,
392                         &hyper_th_id,
393                         params->t_id_string) != 0) {
394                 printf("Command failed\n");
395                 return;
396         }
397
398         status = app_thread_headroom(app,
399                         socket_id,
400                         core_id,
401                         hyper_th_id);
402
403         if (status != 0)
404                 printf("Command failed\n");
405 }
406
407 static cmdline_parse_token_string_t cmd_thread_headroom_t_string =
408         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
409         t_string, "t");
410
411 static cmdline_parse_token_string_t cmd_thread_headroom_t_id_string =
412         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
413         t_id_string, NULL);
414
415 static cmdline_parse_token_string_t cmd_thread_headroom_headroom_string =
416         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
417                 headroom_string, "headroom");
418
419 static cmdline_parse_inst_t cmd_thread_headroom = {
420         .f = cmd_thread_headroom_parsed,
421         .data = NULL,
422         .help_str = "Display thread headroom",
423         .tokens = {
424                 (void *)&cmd_thread_headroom_t_string,
425                 (void *)&cmd_thread_headroom_t_id_string,
426                 (void *)&cmd_thread_headroom_headroom_string,
427                 NULL,
428         },
429 };
430
431
432 static cmdline_parse_ctx_t thread_cmds[] = {
433         (cmdline_parse_inst_t *) &cmd_pipeline_enable,
434         (cmdline_parse_inst_t *) &cmd_pipeline_disable,
435         (cmdline_parse_inst_t *) &cmd_thread_headroom,
436         NULL,
437 };
438
439 int
440 app_pipeline_thread_cmd_push(struct app_params *app)
441 {
442         uint32_t n_cmds, i;
443
444         /* Check for available slots in the application commands array */
445         n_cmds = RTE_DIM(thread_cmds) - 1;
446         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
447                 return -ENOMEM;
448
449         /* Push thread commands into the application */
450         memcpy(&app->cmds[app->n_cmds], thread_cmds,
451                 n_cmds * sizeof(cmdline_parse_ctx_t));
452
453         for (i = 0; i < n_cmds; i++)
454                 app->cmds[app->n_cmds + i]->data = app;
455
456         app->n_cmds += n_cmds;
457         app->cmds[app->n_cmds] = NULL;
458
459         return 0;
460 }