1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2022 Marvell International Ltd.
3 */
4
5 #include <stdlib.h>
6
7 #include <cmdline_parse.h>
8 #include <cmdline_parse_num.h>
9 #include <cmdline_parse_string.h>
10
11 #include <rte_ethdev.h>
12
13 #include "testpmd.h"
14
15 #define PARSE_DELIMITER " \f\n\r\t\v"
16
17 static int
parse_uint(uint64_t * value,const char * str)18 parse_uint(uint64_t *value, const char *str)
19 {
20 char *next = NULL;
21 uint64_t n;
22
23 errno = 0;
24 /* Parse number string */
25 n = strtol(str, &next, 10);
26 if (errno != 0 || str == next || *next != '\0')
27 return -1;
28
29 *value = n;
30
31 return 0;
32 }
33
34 static int
parse_cman_obj_str(char * str,uint64_t * obj)35 parse_cman_obj_str(char *str, uint64_t *obj)
36 {
37 char *token;
38
39 token = strtok_r(str, PARSE_DELIMITER, &str);
40 if (token == NULL)
41 return 0;
42
43 if (strcasecmp(token, "queue") == 0)
44 *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE;
45 else if (strcasecmp(token, "queue_mempool") == 0)
46 *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE_MEMPOOL;
47 else
48 return -1;
49
50 return 0;
51 }
52
53 static int
parse_cman_mode_str(char * str,uint64_t * mode)54 parse_cman_mode_str(char *str, uint64_t *mode)
55 {
56 char *token;
57
58 token = strtok_r(str, PARSE_DELIMITER, &str);
59 if (token == NULL)
60 return 0;
61
62 if (strcasecmp(token, "red") == 0)
63 *mode = RTE_CMAN_RED;
64 else
65 return -1;
66
67 return 0;
68 }
69
70 static int
parse_cman_params_str(uint16_t port_id,char * str,struct rte_eth_cman_config * cfg)71 parse_cman_params_str(uint16_t port_id, char *str,
72 struct rte_eth_cman_config *cfg)
73 {
74 uint64_t obj = 0, mode = 0, min_th = 0, max_th = 0, maxp_inv = 0;
75 struct rte_eth_cman_info info;
76 char *token;
77 int ret;
78
79 token = strtok_r(str, PARSE_DELIMITER, &str);
80 if (!strcasecmp(token, "default")) {
81 ret = rte_eth_cman_config_init(port_id, cfg);
82 if (ret) {
83 fprintf(stderr, "error in default initialization\n");
84 return ret;
85 }
86 return 0;
87 }
88
89 /* First token: obj name */
90 token = strtok_r(str, PARSE_DELIMITER, &str);
91 if (token == NULL) {
92 fprintf(stderr, "Object param parse error\n");
93 goto error;
94 }
95
96 ret = parse_cman_obj_str(token, &obj);
97 if (ret) {
98 fprintf(stderr, "Object value is invalid\n");
99 goto error;
100 }
101
102 /* Second token: mode name */
103 token = strtok_r(str, PARSE_DELIMITER, &str);
104 if (token == NULL) {
105 fprintf(stderr, " Mode param is invalid\n");
106 goto error;
107 }
108
109 token = strtok_r(str, PARSE_DELIMITER, &str);
110 if (token == NULL) {
111 fprintf(stderr, " Mode value is invalid\n");
112 goto error;
113 }
114
115 ret = parse_cman_mode_str(token, &mode);
116 if (ret) {
117 fprintf(stderr, "mode string parse error\n");
118 goto error;
119 }
120
121 /* Third token: minimum threshold */
122 token = strtok_r(str, PARSE_DELIMITER, &str);
123 if (token == NULL) {
124 fprintf(stderr, "Minimum threshold parse error\n");
125 goto error;
126 }
127
128 ret = parse_uint(&min_th, token);
129 if (ret != 0 || min_th > UINT8_MAX) {
130 fprintf(stderr, "Minimum threshold is invalid\n");
131 goto error;
132 }
133
134 /* Fourth token: maximum threshold */
135 token = strtok_r(str, PARSE_DELIMITER, &str);
136 if (token == NULL) {
137 fprintf(stderr, "Maximum threshold parse error\n");
138 goto error;
139 }
140
141 ret = parse_uint(&max_th, token);
142 if (ret != 0 || max_th > UINT8_MAX) {
143 fprintf(stderr, "Maximum threshold is invalid\n");
144 goto error;
145 }
146
147 /* Fifth token: probability inversion */
148 token = strtok_r(str, PARSE_DELIMITER, &str);
149 if (token == NULL) {
150 fprintf(stderr, "Maximum probability inversion parse error\n");
151 goto error;
152 }
153
154 ret = parse_uint(&maxp_inv, token);
155 if (ret != 0 || maxp_inv == 0 || maxp_inv > UINT16_MAX) {
156 fprintf(stderr, "Maximum probability inversion is invalid\n");
157 goto error;
158 }
159
160 memset(&info, 0, sizeof(struct rte_eth_cman_info));
161 ret = rte_eth_cman_info_get(port_id, &info);
162 if (ret) {
163 fprintf(stderr, "Congestion management capa get error\n");
164 goto error;
165 }
166
167 if (!(info.objs_supported & obj)) {
168 fprintf(stderr, "Object type is not supported by driver\n");
169 goto error;
170 }
171
172 if (!(info.modes_supported & mode)) {
173 fprintf(stderr, "Mode is not supported by driver\n");
174 goto error;
175 }
176
177 cfg->obj = obj;
178 cfg->mode = mode;
179 cfg->mode_param.red.min_th = min_th;
180 cfg->mode_param.red.max_th = max_th;
181 cfg->mode_param.red.maxp_inv = maxp_inv;
182
183 return 0;
184
185 error:
186 return -EINVAL;
187 }
188
189 /* *** Show Port Congestion Management Capabilities *** */
190 struct cmd_show_port_cman_capa_result {
191 cmdline_fixed_string_t show;
192 cmdline_fixed_string_t port;
193 cmdline_fixed_string_t cman;
194 cmdline_fixed_string_t capa;
195 uint16_t port_id;
196 };
197
198 static cmdline_parse_token_string_t cmd_show_port_cman_capa_show =
199 TOKEN_STRING_INITIALIZER(
200 struct cmd_show_port_cman_capa_result, show, "show");
201
202 static cmdline_parse_token_string_t cmd_show_port_cman_capa_port =
203 TOKEN_STRING_INITIALIZER(
204 struct cmd_show_port_cman_capa_result, port, "port");
205
206 static cmdline_parse_token_string_t cmd_show_port_cman_capa_cman =
207 TOKEN_STRING_INITIALIZER(
208 struct cmd_show_port_cman_capa_result, cman, "cman");
209
210 static cmdline_parse_token_string_t cmd_show_port_cman_capa_capa =
211 TOKEN_STRING_INITIALIZER(
212 struct cmd_show_port_cman_capa_result, capa, "capa");
213
214 static cmdline_parse_token_num_t cmd_show_port_cman_capa_port_id =
215 TOKEN_NUM_INITIALIZER(
216 struct cmd_show_port_cman_capa_result, port_id, RTE_UINT16);
217
cmd_show_port_cman_capa_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)218 static void cmd_show_port_cman_capa_parsed(void *parsed_result,
219 __rte_unused struct cmdline *cl,
220 __rte_unused void *data)
221 {
222 struct cmd_show_port_cman_capa_result *res = parsed_result;
223 uint16_t port_id = res->port_id;
224 struct rte_eth_cman_info info;
225 int ret;
226
227 memset(&info, 0, sizeof(struct rte_eth_cman_info));
228 ret = rte_eth_cman_info_get(port_id, &info);
229 if (ret)
230 return;
231
232 printf("\n**** Port Congestion Management Capabilities ****\n\n");
233 printf("modes_supported 0x%" PRIx64 "\n", info.modes_supported);
234 printf("objs_supported 0x%" PRIx64 "\n", info.objs_supported);
235 }
236
237 cmdline_parse_inst_t cmd_show_port_cman_capa = {
238 .f = cmd_show_port_cman_capa_parsed,
239 .data = NULL,
240 .help_str = "show port cman capa <port_id>",
241 .tokens = {
242 (void *)&cmd_show_port_cman_capa_show,
243 (void *)&cmd_show_port_cman_capa_port,
244 (void *)&cmd_show_port_cman_capa_cman,
245 (void *)&cmd_show_port_cman_capa_capa,
246 (void *)&cmd_show_port_cman_capa_port_id,
247 NULL,
248 },
249 };
250
251 /* *** Show Port Congestion Management configuration *** */
252 struct cmd_show_port_cman_cfg_result {
253 cmdline_fixed_string_t show;
254 cmdline_fixed_string_t port;
255 cmdline_fixed_string_t cman;
256 cmdline_fixed_string_t cfg;
257 uint16_t port_id;
258 };
259
260 static cmdline_parse_token_string_t cmd_show_port_cman_cfg_show =
261 TOKEN_STRING_INITIALIZER(
262 struct cmd_show_port_cman_cfg_result, show, "show");
263
264 static cmdline_parse_token_string_t cmd_show_port_cman_cfg_port =
265 TOKEN_STRING_INITIALIZER(
266 struct cmd_show_port_cman_cfg_result, port, "port");
267
268 static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cman =
269 TOKEN_STRING_INITIALIZER(
270 struct cmd_show_port_cman_cfg_result, cman, "cman");
271
272 static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cfg =
273 TOKEN_STRING_INITIALIZER(
274 struct cmd_show_port_cman_cfg_result, cfg, "config");
275
276 static cmdline_parse_token_num_t cmd_show_port_cman_cfg_port_id =
277 TOKEN_NUM_INITIALIZER(
278 struct cmd_show_port_cman_cfg_result, port_id, RTE_UINT16);
279
cmd_show_port_cman_cfg_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)280 static void cmd_show_port_cman_cfg_parsed(void *parsed_result,
281 __rte_unused struct cmdline *cl,
282 __rte_unused void *data)
283 {
284 struct cmd_show_port_cman_cfg_result *res = parsed_result;
285 uint16_t port_id = res->port_id;
286 struct rte_eth_cman_config cfg;
287 int ret;
288
289 memset(&cfg, 0, sizeof(struct rte_eth_cman_config));
290 ret = rte_eth_cman_config_get(port_id, &cfg);
291 if (ret)
292 return;
293
294 printf("\n**** Port Congestion Management Configuration ****\n\n");
295 printf("cman object 0x%" PRIx32 "\n", cfg.obj);
296 printf("cman Rx queue %" PRIx16 "\n", cfg.obj_param.rx_queue);
297 printf("cman mode 0x%" PRIx32 "\n", cfg.mode);
298 printf("cman RED min thresh %" PRIx8 "\n", cfg.mode_param.red.min_th);
299 printf("cman RED max thresh %" PRIx8 "\n", cfg.mode_param.red.max_th);
300 printf("cman RED Prob inversion %" PRIx16 "\n",
301 cfg.mode_param.red.maxp_inv);
302 }
303
304 cmdline_parse_inst_t cmd_show_port_cman_config = {
305 .f = cmd_show_port_cman_cfg_parsed,
306 .data = NULL,
307 .help_str = "show port cman config <port_id>",
308 .tokens = {
309 (void *)&cmd_show_port_cman_cfg_show,
310 (void *)&cmd_show_port_cman_cfg_port,
311 (void *)&cmd_show_port_cman_cfg_cman,
312 (void *)&cmd_show_port_cman_cfg_cfg,
313 (void *)&cmd_show_port_cman_cfg_port_id,
314 NULL,
315 },
316 };
317
318 /* *** Set Port Congestion Management configuration *** */
319 struct cmd_set_port_cman_cfg_result {
320 cmdline_fixed_string_t set;
321 cmdline_fixed_string_t port;
322 cmdline_fixed_string_t cman;
323 cmdline_fixed_string_t cfg;
324 uint16_t port_id;
325 uint16_t qid;
326 cmdline_multi_string_t params;
327 };
328
329 static cmdline_parse_token_string_t cmd_set_port_cman_cfg_set =
330 TOKEN_STRING_INITIALIZER(
331 struct cmd_set_port_cman_cfg_result, set, "set");
332
333 static cmdline_parse_token_string_t cmd_set_port_cman_cfg_port =
334 TOKEN_STRING_INITIALIZER(
335 struct cmd_set_port_cman_cfg_result, port, "port");
336
337 static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cman =
338 TOKEN_STRING_INITIALIZER(
339 struct cmd_set_port_cman_cfg_result, cman, "cman");
340
341 static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cfg =
342 TOKEN_STRING_INITIALIZER(
343 struct cmd_set_port_cman_cfg_result, cfg, "config");
344
345 static cmdline_parse_token_num_t cmd_set_port_cman_cfg_port_id =
346 TOKEN_NUM_INITIALIZER(
347 struct cmd_set_port_cman_cfg_result, port_id, RTE_UINT16);
348
349 static cmdline_parse_token_num_t cmd_set_port_cman_cfg_qid =
350 TOKEN_NUM_INITIALIZER(
351 struct cmd_set_port_cman_cfg_result, qid, RTE_UINT16);
352
353 static cmdline_parse_token_string_t cmd_set_port_cman_cfg_params =
354 TOKEN_STRING_INITIALIZER(struct cmd_set_port_cman_cfg_result,
355 params, TOKEN_STRING_MULTI);
356
cmd_set_port_cman_cfg_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)357 static void cmd_set_port_cman_cfg_parsed(void *parsed_result,
358 __rte_unused struct cmdline *cl,
359 __rte_unused void *data)
360 {
361 struct cmd_set_port_cman_cfg_result *res = parsed_result;
362 uint16_t port_id = res->port_id;
363 struct rte_eth_cman_config cfg;
364 int ret;
365
366 ret = parse_cman_params_str(port_id, res->params, &cfg);
367 if (ret) {
368 fprintf(stderr, "params string parse error\n");
369 return;
370 }
371
372 cfg.obj_param.rx_queue = res->qid;
373 rte_eth_cman_config_set(port_id, &cfg);
374 }
375
376 cmdline_parse_inst_t cmd_set_port_cman_config = {
377 .f = cmd_set_port_cman_cfg_parsed,
378 .data = NULL,
379 .help_str = "set port cman config <port_id> <queue_id> "
380 "default | [obj <queue|queue_mempool> mode red "
381 "<min_thresh> <max_thresh> <prob_inv>]",
382 .tokens = {
383 (void *)&cmd_set_port_cman_cfg_set,
384 (void *)&cmd_set_port_cman_cfg_port,
385 (void *)&cmd_set_port_cman_cfg_cman,
386 (void *)&cmd_set_port_cman_cfg_cfg,
387 (void *)&cmd_set_port_cman_cfg_port_id,
388 (void *)&cmd_set_port_cman_cfg_qid,
389 (void *)&cmd_set_port_cman_cfg_params,
390 NULL,
391 },
392 };
393