examples/ip_pipeline: add sw queue object
[dpdk.git] / examples / ip_pipeline / cli.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <rte_common.h>
11
12 #include "cli.h"
13 #include "link.h"
14 #include "mempool.h"
15 #include "parser.h"
16 #include "swq.h"
17
18 #ifndef CMD_MAX_TOKENS
19 #define CMD_MAX_TOKENS     256
20 #endif
21
22 #define MSG_OUT_OF_MEMORY  "Not enough memory.\n"
23 #define MSG_CMD_UNKNOWN    "Unknown command \"%s\".\n"
24 #define MSG_CMD_UNIMPLEM   "Command \"%s\" not implemented.\n"
25 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
26 #define MSG_ARG_TOO_MANY   "Too many arguments for command \"%s\".\n"
27 #define MSG_ARG_MISMATCH   "Wrong number of arguments for command \"%s\".\n"
28 #define MSG_ARG_NOT_FOUND  "Argument \"%s\" not found.\n"
29 #define MSG_ARG_INVALID    "Invalid value for argument \"%s\".\n"
30 #define MSG_FILE_ERR       "Error in file \"%s\" at line %u.\n"
31 #define MSG_CMD_FAIL       "Command \"%s\" failed.\n"
32
33 static int
34 is_comment(char *in)
35 {
36         if ((strlen(in) && index("!#%;", in[0])) ||
37                 (strncmp(in, "//", 2) == 0) ||
38                 (strncmp(in, "--", 2) == 0))
39                 return 1;
40
41         return 0;
42 }
43
44 /**
45  * mempool <mempool_name>
46  *  buffer <buffer_size>
47  *  pool <pool_size>
48  *  cache <cache_size>
49  *  cpu <cpu_id>
50  */
51 static void
52 cmd_mempool(char **tokens,
53         uint32_t n_tokens,
54         char *out,
55         size_t out_size)
56 {
57         struct mempool_params p;
58         char *name;
59         struct mempool *mempool;
60
61         if (n_tokens != 10) {
62                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
63                 return;
64         }
65
66         name = tokens[1];
67
68         if (strcmp(tokens[2], "buffer") != 0) {
69                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
70                 return;
71         }
72
73         if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
74                 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
75                 return;
76         }
77
78         if (strcmp(tokens[4], "pool") != 0) {
79                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
80                 return;
81         }
82
83         if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
84                 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
85                 return;
86         }
87
88         if (strcmp(tokens[6], "cache") != 0) {
89                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
90                 return;
91         }
92
93         if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
94                 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
95                 return;
96         }
97
98         if (strcmp(tokens[8], "cpu") != 0) {
99                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
100                 return;
101         }
102
103         if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
104                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
105                 return;
106         }
107
108         mempool = mempool_create(name, &p);
109         if (mempool == NULL) {
110                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
111                 return;
112         }
113 }
114
115 /**
116  * link <link_name>
117  *  dev <device_name> | port <port_id>
118  *  rxq <n_queues> <queue_size> <mempool_name>
119  *  txq <n_queues> <queue_size>
120  *  promiscuous on | off
121  *  [rss <qid_0> ... <qid_n>]
122  */
123 static void
124 cmd_link(char **tokens,
125         uint32_t n_tokens,
126         char *out,
127         size_t out_size)
128 {
129         struct link_params p;
130         struct link_params_rss rss;
131         struct link *link;
132         char *name;
133
134         if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
135                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
136                 return;
137         }
138         name = tokens[1];
139
140         if (strcmp(tokens[2], "dev") == 0)
141                 p.dev_name = tokens[3];
142         else if (strcmp(tokens[2], "port") == 0) {
143                 p.dev_name = NULL;
144
145                 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
146                         snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
147                         return;
148                 }
149         } else {
150                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
151                 return;
152         }
153
154         if (strcmp(tokens[4], "rxq") != 0) {
155                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
156                 return;
157         }
158
159         if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
160                 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
161                 return;
162         }
163         if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
164                 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
165                 return;
166         }
167
168         p.rx.mempool_name = tokens[7];
169
170         if (strcmp(tokens[8], "txq") != 0) {
171                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
172                 return;
173         }
174
175         if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
176                 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
177                 return;
178         }
179
180         if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
181                 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
182                 return;
183         }
184
185         if (strcmp(tokens[11], "promiscuous") != 0) {
186                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
187                 return;
188         }
189
190         if (strcmp(tokens[12], "on") == 0)
191                 p.promiscuous = 1;
192         else if (strcmp(tokens[12], "off") == 0)
193                 p.promiscuous = 0;
194         else {
195                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
196                 return;
197         }
198
199         /* RSS */
200         p.rx.rss = NULL;
201         if (n_tokens > 13) {
202                 uint32_t queue_id, i;
203
204                 if (strcmp(tokens[13], "rss") != 0) {
205                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
206                         return;
207                 }
208
209                 p.rx.rss = &rss;
210
211                 rss.n_queues = 0;
212                 for (i = 14; i < n_tokens; i++) {
213                         if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
214                                 snprintf(out, out_size, MSG_ARG_INVALID,
215                                         "queue_id");
216                                 return;
217                         }
218
219                         rss.queue_id[rss.n_queues] = queue_id;
220                         rss.n_queues++;
221                 }
222         }
223
224         link = link_create(name, &p);
225         if (link == NULL) {
226                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
227                 return;
228         }
229 }
230
231 /**
232  * swq <swq_name>
233  *  size <size>
234  *  cpu <cpu_id>
235  */
236 static void
237 cmd_swq(char **tokens,
238         uint32_t n_tokens,
239         char *out,
240         size_t out_size)
241 {
242         struct swq_params p;
243         char *name;
244         struct swq *swq;
245
246         if (n_tokens != 6) {
247                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
248                 return;
249         }
250
251         name = tokens[1];
252
253         if (strcmp(tokens[2], "size") != 0) {
254                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
255                 return;
256         }
257
258         if (parser_read_uint32(&p.size, tokens[3]) != 0) {
259                 snprintf(out, out_size, MSG_ARG_INVALID, "size");
260                 return;
261         }
262
263         if (strcmp(tokens[4], "cpu") != 0) {
264                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
265                 return;
266         }
267
268         if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) {
269                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
270                 return;
271         }
272
273         swq = swq_create(name, &p);
274         if (swq == NULL) {
275                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
276                 return;
277         }
278 }
279
280 void
281 cli_process(char *in, char *out, size_t out_size)
282 {
283         char *tokens[CMD_MAX_TOKENS];
284         uint32_t n_tokens = RTE_DIM(tokens);
285         int status;
286
287         if (is_comment(in))
288                 return;
289
290         status = parse_tokenize_string(in, tokens, &n_tokens);
291         if (status) {
292                 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
293                 return;
294         }
295
296         if (n_tokens == 0)
297                 return;
298
299         if (strcmp(tokens[0], "mempool") == 0) {
300                 cmd_mempool(tokens, n_tokens, out, out_size);
301                 return;
302         }
303
304         if (strcmp(tokens[0], "link") == 0) {
305                 cmd_link(tokens, n_tokens, out, out_size);
306                 return;
307         }
308
309         if (strcmp(tokens[0], "swq") == 0) {
310                 cmd_swq(tokens, n_tokens, out, out_size);
311                 return;
312         }
313
314         snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
315 }
316
317 int
318 cli_script_process(const char *file_name,
319         size_t msg_in_len_max,
320         size_t msg_out_len_max)
321 {
322         char *msg_in = NULL, *msg_out = NULL;
323         FILE *f = NULL;
324
325         /* Check input arguments */
326         if ((file_name == NULL) ||
327                 (strlen(file_name) == 0) ||
328                 (msg_in_len_max == 0) ||
329                 (msg_out_len_max == 0))
330                 return -EINVAL;
331
332         msg_in = malloc(msg_in_len_max + 1);
333         msg_out = malloc(msg_out_len_max + 1);
334         if ((msg_in == NULL) ||
335                 (msg_out == NULL)) {
336                 free(msg_out);
337                 free(msg_in);
338                 return -ENOMEM;
339         }
340
341         /* Open input file */
342         f = fopen(file_name, "r");
343         if (f == NULL) {
344                 free(msg_out);
345                 free(msg_in);
346                 return -EIO;
347         }
348
349         /* Read file */
350         for ( ; ; ) {
351                 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
352                         break;
353
354                 printf("%s", msg_in);
355                 msg_out[0] = 0;
356
357                 cli_process(msg_in,
358                         msg_out,
359                         msg_out_len_max);
360
361                 if (strlen(msg_out))
362                         printf("%s", msg_out);
363         }
364
365         /* Close file */
366         fclose(f);
367         free(msg_out);
368         free(msg_in);
369         return 0;
370 }