Imported Upstream version 16.04
[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 #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 int
174 app_thread_headroom(struct app_params *app,
175                 uint32_t socket_id,
176                 uint32_t core_id,
177                 uint32_t hyper_th_id)
178 {
179         struct thread_headroom_read_msg_req *req;
180         struct thread_headroom_read_msg_rsp *rsp;
181         int thread_id;
182         int status;
183
184         if (app == NULL)
185                 return -1;
186
187         thread_id = cpu_core_map_get_lcore_id(app->core_map,
188                         socket_id,
189                         core_id,
190                         hyper_th_id);
191
192         if ((thread_id < 0) ||
193                 ((app->core_mask & (1LLU << thread_id)) == 0))
194                 return -1;
195
196         req = app_msg_alloc(app);
197         if (req == NULL)
198                 return -1;
199
200         req->type = THREAD_MSG_REQ_HEADROOM_READ;
201
202         rsp = thread_msg_send_recv(app,
203                 socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);
204
205         if (rsp == NULL)
206                 return -1;
207
208         status = rsp->status;
209
210         if (status != 0)
211                 return -1;
212
213         printf("%.3f%%\n", rsp->headroom_ratio * 100);
214
215
216         app_msg_free(app, rsp);
217
218         return 0;
219 }
220
221 /*
222  * pipeline enable
223  */
224
225 struct cmd_pipeline_enable_result {
226         cmdline_fixed_string_t t_string;
227         cmdline_fixed_string_t t_id_string;
228         cmdline_fixed_string_t pipeline_string;
229         uint32_t pipeline_id;
230         cmdline_fixed_string_t enable_string;
231 };
232
233 static void
234 cmd_pipeline_enable_parsed(
235         void *parsed_result,
236         __rte_unused struct cmdline *cl,
237          void *data)
238 {
239         struct cmd_pipeline_enable_result *params = parsed_result;
240         struct app_params *app = data;
241         int status;
242         uint32_t core_id, socket_id, hyper_th_id;
243
244         if (parse_pipeline_core(&socket_id,
245                         &core_id,
246                         &hyper_th_id,
247                         params->t_id_string) != 0) {
248                 printf("Command failed\n");
249                 return;
250         }
251
252         status = app_pipeline_enable(app,
253                         socket_id,
254                         core_id,
255                         hyper_th_id,
256                         params->pipeline_id);
257
258         if (status != 0)
259                 printf("Command failed\n");
260 }
261
262 cmdline_parse_token_string_t cmd_pipeline_enable_t_string =
263         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t");
264
265 cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =
266         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string,
267                 NULL);
268
269 cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =
270         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string,
271                 "pipeline");
272
273 cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =
274         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id,
275                 UINT32);
276
277 cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =
278         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string,
279                 "enable");
280
281 cmdline_parse_inst_t cmd_pipeline_enable = {
282         .f = cmd_pipeline_enable_parsed,
283         .data = NULL,
284         .help_str = "Enable pipeline on specified core",
285         .tokens = {
286                 (void *)&cmd_pipeline_enable_t_string,
287                 (void *)&cmd_pipeline_enable_t_id_string,
288                 (void *)&cmd_pipeline_enable_pipeline_string,
289                 (void *)&cmd_pipeline_enable_pipeline_id,
290                 (void *)&cmd_pipeline_enable_enable_string,
291                 NULL,
292         },
293 };
294
295 /*
296  * pipeline disable
297  */
298
299 struct cmd_pipeline_disable_result {
300         cmdline_fixed_string_t t_string;
301         cmdline_fixed_string_t t_id_string;
302         cmdline_fixed_string_t pipeline_string;
303         uint32_t pipeline_id;
304         cmdline_fixed_string_t disable_string;
305 };
306
307 static void
308 cmd_pipeline_disable_parsed(
309         void *parsed_result,
310         __rte_unused struct cmdline *cl,
311          void *data)
312 {
313         struct cmd_pipeline_disable_result *params = parsed_result;
314         struct app_params *app = data;
315         int status;
316         uint32_t core_id, socket_id, hyper_th_id;
317
318         if (parse_pipeline_core(&socket_id,
319                         &core_id,
320                         &hyper_th_id,
321                         params->t_id_string) != 0) {
322                 printf("Command failed\n");
323                 return;
324         }
325
326         status = app_pipeline_disable(app,
327                         socket_id,
328                         core_id,
329                         hyper_th_id,
330                         params->pipeline_id);
331
332         if (status != 0)
333                 printf("Command failed\n");
334 }
335
336 cmdline_parse_token_string_t cmd_pipeline_disable_t_string =
337         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t");
338
339 cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =
340         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string,
341                 NULL);
342
343 cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =
344         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result,
345                 pipeline_string, "pipeline");
346
347 cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =
348         TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id,
349                 UINT32);
350
351 cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =
352         TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string,
353                 "disable");
354
355 cmdline_parse_inst_t cmd_pipeline_disable = {
356         .f = cmd_pipeline_disable_parsed,
357         .data = NULL,
358         .help_str = "Disable pipeline on specified core",
359         .tokens = {
360                 (void *)&cmd_pipeline_disable_t_string,
361                 (void *)&cmd_pipeline_disable_t_id_string,
362                 (void *)&cmd_pipeline_disable_pipeline_string,
363                 (void *)&cmd_pipeline_disable_pipeline_id,
364                 (void *)&cmd_pipeline_disable_disable_string,
365                 NULL,
366         },
367 };
368
369
370 /*
371  * thread headroom
372  */
373
374 struct cmd_thread_headroom_result {
375         cmdline_fixed_string_t t_string;
376         cmdline_fixed_string_t t_id_string;
377         cmdline_fixed_string_t headroom_string;
378 };
379
380 static void
381 cmd_thread_headroom_parsed(
382         void *parsed_result,
383         __rte_unused struct cmdline *cl,
384          void *data)
385 {
386         struct cmd_thread_headroom_result *params = parsed_result;
387         struct app_params *app = data;
388         int status;
389         uint32_t core_id, socket_id, hyper_th_id;
390
391         if (parse_pipeline_core(&socket_id,
392                         &core_id,
393                         &hyper_th_id,
394                         params->t_id_string) != 0) {
395                 printf("Command failed\n");
396                 return;
397         }
398
399         status = app_thread_headroom(app,
400                         socket_id,
401                         core_id,
402                         hyper_th_id);
403
404         if (status != 0)
405                 printf("Command failed\n");
406 }
407
408 cmdline_parse_token_string_t cmd_thread_headroom_t_string =
409         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
410         t_string, "t");
411
412 cmdline_parse_token_string_t cmd_thread_headroom_t_id_string =
413         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
414         t_id_string, NULL);
415
416 cmdline_parse_token_string_t cmd_thread_headroom_headroom_string =
417         TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
418                 headroom_string, "headroom");
419
420 cmdline_parse_inst_t cmd_thread_headroom = {
421         .f = cmd_thread_headroom_parsed,
422         .data = NULL,
423         .help_str = "Display thread headroom",
424         .tokens = {
425                 (void *)&cmd_thread_headroom_t_string,
426                 (void *)&cmd_thread_headroom_t_id_string,
427                 (void *)&cmd_thread_headroom_headroom_string,
428                 NULL,
429         },
430 };
431
432
433 static cmdline_parse_ctx_t thread_cmds[] = {
434         (cmdline_parse_inst_t *) &cmd_pipeline_enable,
435         (cmdline_parse_inst_t *) &cmd_pipeline_disable,
436         (cmdline_parse_inst_t *) &cmd_thread_headroom,
437         NULL,
438 };
439
440 int
441 app_pipeline_thread_cmd_push(struct app_params *app)
442 {
443         uint32_t n_cmds, i;
444
445         /* Check for available slots in the application commands array */
446         n_cmds = RTE_DIM(thread_cmds) - 1;
447         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
448                 return -ENOMEM;
449
450         /* Push thread commands into the application */
451         memcpy(&app->cmds[app->n_cmds], thread_cmds,
452                 n_cmds * sizeof(cmdline_parse_ctx_t));
453
454         for (i = 0; i < n_cmds; i++)
455                 app->cmds[app->n_cmds + i]->data = app;
456
457         app->n_cmds += n_cmds;
458         app->cmds[app->n_cmds] = NULL;
459
460         return 0;
461 }