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