1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2021 6WIND S.A.
3 * Copyright 2021 Mellanox Technologies, Ltd
4 */
5
6 #include <stdint.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #ifndef RTE_EXEC_ENV_WINDOWS
11 #include <sys/socket.h>
12 #include <sys/un.h>
13 #endif
14
15 #include <rte_prefetch.h>
16 #include <rte_common.h>
17 #include <rte_branch_prediction.h>
18 #include <rte_ether.h>
19 #include <rte_alarm.h>
20 #include <rte_pmd_mlx5.h>
21 #include <rte_ethdev.h>
22
23 #include "mlx5_testpmd.h"
24 #include "testpmd.h"
25
26 #define SHAPER_DISABLE_DELAY_US 100000 /* 100ms */
27 #define MAX_GENEVE_OPTIONS_RESOURCES 7
28 #define PARSE_DELIMITER " \f\n\r\t\v"
29 #define SPACE_DELIMITER (" ")
30
31 static uint8_t host_shaper_avail_thresh_triggered[RTE_MAX_ETHPORTS];
32
33 struct mlx5_port {
34 void *geneve_tlv_parser_handle;
35 };
36
37 static struct mlx5_port private_port[RTE_MAX_ETHPORTS] = {{0}};
38
39 struct tlv_list_manager {
40 uint8_t nb_options;
41 struct rte_pmd_mlx5_geneve_tlv tlv_list[MAX_GENEVE_OPTIONS_RESOURCES];
42 };
43
44 static struct tlv_list_manager tlv_mng = {.nb_options = 0};
45
46 static int
parse_uint(uint64_t * value,const char * str)47 parse_uint(uint64_t *value, const char *str)
48 {
49 char *next = NULL;
50 uint64_t n;
51
52 errno = 0;
53 /* Parse number string */
54 if (!strncasecmp(str, "0x", 2)) {
55 str += 2;
56 n = strtol(str, &next, 16);
57 } else {
58 n = strtol(str, &next, 10);
59 }
60 if (errno != 0 || str == next || *next != '\0')
61 return -1;
62
63 *value = n;
64
65 return 0;
66 }
67
68 /**
69 * Disable the host shaper and re-arm available descriptor threshold event.
70 *
71 * @param[in] args
72 * uint32_t integer combining port_id and rxq_id.
73 */
74 static void
mlx5_test_host_shaper_disable(void * args)75 mlx5_test_host_shaper_disable(void *args)
76 {
77 uint32_t port_rxq_id = (uint32_t)(uintptr_t)args;
78 uint16_t port_id = port_rxq_id & 0xffff;
79 uint16_t qid = (port_rxq_id >> 16) & 0xffff;
80 struct rte_eth_rxq_info qinfo;
81 struct rte_port *port;
82
83 port = &ports[port_id];
84 if (port->port_status != RTE_PORT_STARTED) {
85 printf("%s port_status(%d) is incorrect, stop avail_thresh "
86 "event processing.\n",
87 __func__, port->port_status);
88 return;
89 }
90 printf("%s disable shaper\n", __func__);
91 if (rte_eth_rx_queue_info_get(port_id, qid, &qinfo)) {
92 printf("rx_queue_info_get returns error\n");
93 return;
94 }
95 /* Rearm the available descriptor threshold event. */
96 if (rte_eth_rx_avail_thresh_set(port_id, qid, qinfo.avail_thresh)) {
97 printf("config avail_thresh returns error\n");
98 return;
99 }
100 /* Only disable the shaper when avail_thresh_triggered is set. */
101 if (host_shaper_avail_thresh_triggered[port_id] &&
102 rte_pmd_mlx5_host_shaper_config(port_id, 0, 0))
103 printf("%s disable shaper returns error\n", __func__);
104 }
105
106 void
mlx5_test_avail_thresh_event_handler(uint16_t port_id,uint16_t rxq_id)107 mlx5_test_avail_thresh_event_handler(uint16_t port_id, uint16_t rxq_id)
108 {
109 struct rte_eth_dev_info dev_info;
110 uint32_t port_rxq_id = port_id | (rxq_id << 16);
111
112 /* Ensure it's MLX5 port. */
113 if (rte_eth_dev_info_get(port_id, &dev_info) != 0 ||
114 (strncmp(dev_info.driver_name, "mlx5", 4) != 0))
115 return;
116 rte_eal_alarm_set(SHAPER_DISABLE_DELAY_US,
117 mlx5_test_host_shaper_disable,
118 (void *)(uintptr_t)port_rxq_id);
119 printf("%s port_id:%u rxq_id:%u\n", __func__, port_id, rxq_id);
120 }
121
122 /**
123 * Configure host shaper's avail_thresh_triggered and current rate.
124 *
125 * @param[in] avail_thresh_triggered
126 * Disable/enable avail_thresh_triggered.
127 * @param[in] rate
128 * Configure current host shaper rate.
129 * @return
130 * On success, returns 0.
131 * On failure, returns < 0.
132 */
133 static int
mlx5_test_set_port_host_shaper(uint16_t port_id,uint16_t avail_thresh_triggered,uint8_t rate)134 mlx5_test_set_port_host_shaper(uint16_t port_id, uint16_t avail_thresh_triggered, uint8_t rate)
135 {
136 struct rte_eth_link link;
137 bool port_id_valid = false;
138 uint16_t pid;
139 int ret;
140
141 RTE_ETH_FOREACH_DEV(pid)
142 if (port_id == pid) {
143 port_id_valid = true;
144 break;
145 }
146 if (!port_id_valid)
147 return -EINVAL;
148 ret = rte_eth_link_get_nowait(port_id, &link);
149 if (ret < 0)
150 return ret;
151 host_shaper_avail_thresh_triggered[port_id] = avail_thresh_triggered ? 1 : 0;
152 if (!avail_thresh_triggered) {
153 ret = rte_pmd_mlx5_host_shaper_config(port_id, 0,
154 RTE_BIT32(RTE_PMD_MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED));
155 } else {
156 ret = rte_pmd_mlx5_host_shaper_config(port_id, 1,
157 RTE_BIT32(RTE_PMD_MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED));
158 }
159 if (ret)
160 return ret;
161 ret = rte_pmd_mlx5_host_shaper_config(port_id, rate, 0);
162 if (ret)
163 return ret;
164 return 0;
165 }
166
167 #ifndef RTE_EXEC_ENV_WINDOWS
168 static const char*
mlx5_test_get_socket_path(char * extend)169 mlx5_test_get_socket_path(char *extend)
170 {
171 if (strstr(extend, "socket=") == extend) {
172 const char *socket_path = strchr(extend, '=') + 1;
173
174 TESTPMD_LOG(DEBUG, "MLX5 socket path is %s\n", socket_path);
175 return socket_path;
176 }
177
178 TESTPMD_LOG(ERR, "Failed to extract a valid socket path from %s\n",
179 extend);
180 return NULL;
181 }
182
183 static int
mlx5_test_extend_devargs(char * identifier,char * extend)184 mlx5_test_extend_devargs(char *identifier, char *extend)
185 {
186 struct sockaddr_un un = {
187 .sun_family = AF_UNIX,
188 };
189 int cmd_fd;
190 int pd_handle;
191 struct iovec iov = {
192 .iov_base = &pd_handle,
193 .iov_len = sizeof(int),
194 };
195 union {
196 char buf[CMSG_SPACE(sizeof(int))];
197 struct cmsghdr align;
198 } control;
199 struct msghdr msgh = {
200 .msg_iov = NULL,
201 .msg_iovlen = 0,
202 };
203 struct cmsghdr *cmsg;
204 const char *path = mlx5_test_get_socket_path(extend + 1);
205 size_t len = 1;
206 int socket_fd;
207 int ret;
208
209 if (path == NULL) {
210 TESTPMD_LOG(ERR, "Invalid devargs extension is specified\n");
211 return -1;
212 }
213
214 /* Initialize IPC channel. */
215 socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
216 if (socket_fd < 0) {
217 TESTPMD_LOG(ERR, "Failed to create unix socket: %s\n",
218 strerror(errno));
219 return -1;
220 }
221 rte_strlcpy(un.sun_path, path, sizeof(un.sun_path));
222 if (connect(socket_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
223 TESTPMD_LOG(ERR, "Failed to connect %s: %s\n", un.sun_path,
224 strerror(errno));
225 close(socket_fd);
226 return -1;
227 }
228
229 /* Send the request message. */
230 do {
231 ret = sendmsg(socket_fd, &msgh, 0);
232 } while (ret < 0 && errno == EINTR);
233 if (ret < 0) {
234 TESTPMD_LOG(ERR, "Failed to send request to (%s): %s\n", path,
235 strerror(errno));
236 close(socket_fd);
237 return -1;
238 }
239
240 msgh.msg_iov = &iov;
241 msgh.msg_iovlen = 1;
242 msgh.msg_control = control.buf;
243 msgh.msg_controllen = sizeof(control.buf);
244 do {
245 ret = recvmsg(socket_fd, &msgh, 0);
246 } while (ret < 0);
247 if (ret != sizeof(int) || (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
248 TESTPMD_LOG(ERR, "truncated msg");
249 close(socket_fd);
250 return -1;
251 }
252
253 /* Translate the FD. */
254 cmsg = CMSG_FIRSTHDR(&msgh);
255 if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
256 cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
257 TESTPMD_LOG(ERR, "Fail to get FD using SCM_RIGHTS mechanism\n");
258 close(socket_fd);
259 unlink(un.sun_path);
260 return -1;
261 }
262 memcpy(&cmd_fd, CMSG_DATA(cmsg), sizeof(int));
263
264 TESTPMD_LOG(DEBUG, "Command FD (%d) and PD handle (%d) "
265 "are successfully imported from remote process\n",
266 cmd_fd, pd_handle);
267
268 /* Cleanup IPC channel. */
269 close(socket_fd);
270
271 /* Calculate the new length of devargs string. */
272 len += snprintf(NULL, 0, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
273 /* Extend the devargs string. */
274 snprintf(extend, len, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
275
276 TESTPMD_LOG(DEBUG, "Attach port with extra devargs %s\n", identifier);
277 return 0;
278 }
279
280 static bool
is_delimiter_path_spaces(char * extend)281 is_delimiter_path_spaces(char *extend)
282 {
283 while (*extend != '\0') {
284 if (*extend != ' ')
285 return true;
286 extend++;
287 }
288 return false;
289 }
290
291 /*
292 * Extend devargs list with "cmd_fd" and "pd_handle" coming from external
293 * process. It happens only in this format:
294 * testpmd> mlx5 port attach (identifier) socket=<socket path>
295 * all "(identifier) socket=<socket path>" is in the same string pointed
296 * by the input parameter 'identifier'.
297 *
298 * @param identifier
299 * Identifier of port attach command line.
300 */
301 static void
mlx5_test_attach_port_extend_devargs(char * identifier)302 mlx5_test_attach_port_extend_devargs(char *identifier)
303 {
304 char *extend;
305
306 if (identifier == NULL) {
307 fprintf(stderr, "Invalid parameters are specified\n");
308 return;
309 }
310
311 extend = strchr(identifier, ' ');
312 if (extend != NULL && is_delimiter_path_spaces(extend) &&
313 mlx5_test_extend_devargs(identifier, extend) < 0) {
314 TESTPMD_LOG(ERR, "Failed to extend devargs for port %s\n",
315 identifier);
316 return;
317 }
318
319 attach_port(identifier);
320 }
321 #endif
322
323 static inline const char *
mode2string(uint8_t mode)324 mode2string(uint8_t mode)
325 {
326 switch (mode) {
327 case 0:
328 return "ignored\t";
329 case 1:
330 return "fixed\t";
331 case 2:
332 return "matchable";
333 default:
334 break;
335 }
336 return "unknown";
337 }
338
339 static inline uint8_t
string2mode(const char * mode)340 string2mode(const char *mode)
341 {
342 if (strcmp(mode, "ignored") == 0)
343 return 0;
344 if (strcmp(mode, "fixed") == 0)
345 return 1;
346 if (strcmp(mode, "matchable") == 0)
347 return 2;
348 return UINT8_MAX;
349 }
350
351 static int
mlx5_test_parse_geneve_option_data(const char * buff,uint8_t data_len,rte_be32_t ** match_data_mask)352 mlx5_test_parse_geneve_option_data(const char *buff, uint8_t data_len,
353 rte_be32_t **match_data_mask)
354 {
355 rte_be32_t *data;
356 char *buff2;
357 char *token;
358 uint8_t i = 0;
359
360 if (data_len == 0) {
361 *match_data_mask = NULL;
362 return 0;
363 }
364
365 data = calloc(data_len, sizeof(rte_be32_t));
366 if (data == NULL) {
367 TESTPMD_LOG(ERR, "Fail to allocate memory for GENEVE TLV option data\n");
368 return -ENOMEM;
369 }
370
371 buff2 = strdup(buff);
372 if (buff2 == NULL) {
373 TESTPMD_LOG(ERR,
374 "Fail to duplicate GENEVE TLV option data string (%s)\n",
375 buff);
376 free(data);
377 return -ENOMEM;
378 }
379
380 token = strtok(buff2, SPACE_DELIMITER);
381 while (token != NULL) {
382 if (i == data_len) {
383 TESTPMD_LOG(ERR,
384 "GENEVE TLV option has more data then given data length %u\n",
385 data_len);
386 free(buff2);
387 free(data);
388 return -EINVAL;
389 }
390
391 if (strcmp(token, "0xffffffff") == 0)
392 data[i] = 0xffffffff;
393 else
394 data[i] = 0x0;
395
396 token = strtok(NULL, SPACE_DELIMITER);
397 i++;
398 }
399
400 free(buff2);
401 *match_data_mask = data;
402 return 0;
403 }
404
405 /* *** SET HOST_SHAPER FOR A PORT *** */
406 struct cmd_port_host_shaper_result {
407 cmdline_fixed_string_t mlx5;
408 cmdline_fixed_string_t set;
409 cmdline_fixed_string_t port;
410 uint16_t port_num;
411 cmdline_fixed_string_t host_shaper;
412 cmdline_fixed_string_t avail_thresh_triggered;
413 uint16_t fr;
414 cmdline_fixed_string_t rate;
415 uint8_t rate_num;
416 };
417
cmd_port_host_shaper_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)418 static void cmd_port_host_shaper_parsed(void *parsed_result,
419 __rte_unused struct cmdline *cl,
420 __rte_unused void *data)
421 {
422 struct cmd_port_host_shaper_result *res = parsed_result;
423 int ret = 0;
424
425 if ((strcmp(res->mlx5, "mlx5") == 0) &&
426 (strcmp(res->set, "set") == 0) &&
427 (strcmp(res->port, "port") == 0) &&
428 (strcmp(res->host_shaper, "host_shaper") == 0) &&
429 (strcmp(res->avail_thresh_triggered, "avail_thresh_triggered") == 0) &&
430 (strcmp(res->rate, "rate") == 0))
431 ret = mlx5_test_set_port_host_shaper(res->port_num, res->fr,
432 res->rate_num);
433 if (ret < 0)
434 printf("cmd_port_host_shaper error: (%s)\n", strerror(-ret));
435 }
436
437 static cmdline_parse_token_string_t cmd_port_host_shaper_mlx5 =
438 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
439 mlx5, "mlx5");
440 static cmdline_parse_token_string_t cmd_port_host_shaper_set =
441 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
442 set, "set");
443 static cmdline_parse_token_string_t cmd_port_host_shaper_port =
444 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
445 port, "port");
446 static cmdline_parse_token_num_t cmd_port_host_shaper_portnum =
447 TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
448 port_num, RTE_UINT16);
449 static cmdline_parse_token_string_t cmd_port_host_shaper_host_shaper =
450 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
451 host_shaper, "host_shaper");
452 static cmdline_parse_token_string_t cmd_port_host_shaper_avail_thresh_triggered =
453 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
454 avail_thresh_triggered, "avail_thresh_triggered");
455 static cmdline_parse_token_num_t cmd_port_host_shaper_fr =
456 TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
457 fr, RTE_UINT16);
458 static cmdline_parse_token_string_t cmd_port_host_shaper_rate =
459 TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
460 rate, "rate");
461 static cmdline_parse_token_num_t cmd_port_host_shaper_rate_num =
462 TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
463 rate_num, RTE_UINT8);
464 static cmdline_parse_inst_t mlx5_test_cmd_port_host_shaper = {
465 .f = cmd_port_host_shaper_parsed,
466 .data = (void *)0,
467 .help_str = "mlx5 set port <port_id> host_shaper avail_thresh_triggered <0|1> "
468 "rate <rate_num>: Set HOST_SHAPER avail_thresh_triggered and rate with port_id",
469 .tokens = {
470 (void *)&cmd_port_host_shaper_mlx5,
471 (void *)&cmd_port_host_shaper_set,
472 (void *)&cmd_port_host_shaper_port,
473 (void *)&cmd_port_host_shaper_portnum,
474 (void *)&cmd_port_host_shaper_host_shaper,
475 (void *)&cmd_port_host_shaper_avail_thresh_triggered,
476 (void *)&cmd_port_host_shaper_fr,
477 (void *)&cmd_port_host_shaper_rate,
478 (void *)&cmd_port_host_shaper_rate_num,
479 NULL,
480 }
481 };
482
483 #ifndef RTE_EXEC_ENV_WINDOWS
484 /* *** attach a specified port *** */
485 struct mlx5_cmd_operate_attach_port_result {
486 cmdline_fixed_string_t mlx5;
487 cmdline_fixed_string_t port;
488 cmdline_fixed_string_t keyword;
489 cmdline_multi_string_t identifier;
490 };
491
mlx5_cmd_operate_attach_port_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)492 static void mlx5_cmd_operate_attach_port_parsed(void *parsed_result,
493 __rte_unused struct cmdline *cl,
494 __rte_unused void *data)
495 {
496 struct mlx5_cmd_operate_attach_port_result *res = parsed_result;
497
498 if (!strcmp(res->keyword, "attach"))
499 mlx5_test_attach_port_extend_devargs(res->identifier);
500 else
501 fprintf(stderr, "Unknown parameter\n");
502 }
503
504 static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_mlx5 =
505 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
506 mlx5, "mlx5");
507 static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_port =
508 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
509 port, "port");
510 static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_keyword =
511 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
512 keyword, "attach");
513 static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_identifier =
514 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
515 identifier, TOKEN_STRING_MULTI);
516
517 static cmdline_parse_inst_t mlx5_cmd_operate_attach_port = {
518 .f = mlx5_cmd_operate_attach_port_parsed,
519 .data = NULL,
520 .help_str = "mlx5 port attach <identifier> socket=<path>: "
521 "(identifier: pci address or virtual dev name"
522 ", path (optional): socket path to get cmd FD and PD handle)",
523 .tokens = {
524 (void *)&mlx5_cmd_operate_attach_port_mlx5,
525 (void *)&mlx5_cmd_operate_attach_port_port,
526 (void *)&mlx5_cmd_operate_attach_port_keyword,
527 (void *)&mlx5_cmd_operate_attach_port_identifier,
528 NULL,
529 },
530 };
531 #endif
532
533 /* Map HW queue index to rte queue index. */
534 struct mlx5_cmd_map_ext_rxq {
535 cmdline_fixed_string_t mlx5;
536 cmdline_fixed_string_t port;
537 portid_t port_id;
538 cmdline_fixed_string_t ext_rxq;
539 cmdline_fixed_string_t map;
540 uint16_t sw_queue_id;
541 uint32_t hw_queue_id;
542 };
543
544 cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_mlx5 =
545 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, mlx5, "mlx5");
546 cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_port =
547 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port, "port");
548 cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_port_id =
549 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port_id, RTE_UINT16);
550 cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_ext_rxq =
551 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, ext_rxq,
552 "ext_rxq");
553 cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_map =
554 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, map, "map");
555 cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_sw_queue_id =
556 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, sw_queue_id,
557 RTE_UINT16);
558 cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_hw_queue_id =
559 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, hw_queue_id,
560 RTE_UINT32);
561
562 static void
mlx5_cmd_map_ext_rxq_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)563 mlx5_cmd_map_ext_rxq_parsed(void *parsed_result,
564 __rte_unused struct cmdline *cl,
565 __rte_unused void *data)
566 {
567 struct mlx5_cmd_map_ext_rxq *res = parsed_result;
568 int ret;
569
570 if (port_id_is_invalid(res->port_id, ENABLED_WARN))
571 return;
572 ret = rte_pmd_mlx5_external_rx_queue_id_map(res->port_id,
573 res->sw_queue_id,
574 res->hw_queue_id);
575 switch (ret) {
576 case 0:
577 break;
578 case -EINVAL:
579 fprintf(stderr, "invalid ethdev index (%u), out of range\n",
580 res->sw_queue_id);
581 break;
582 case -ENODEV:
583 fprintf(stderr, "invalid port_id %u\n", res->port_id);
584 break;
585 case -ENOTSUP:
586 fprintf(stderr, "function not implemented or supported\n");
587 break;
588 case -EEXIST:
589 fprintf(stderr, "mapping with index %u already exists\n",
590 res->sw_queue_id);
591 break;
592 default:
593 fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
594 }
595 }
596
597 cmdline_parse_inst_t mlx5_cmd_map_ext_rxq = {
598 .f = mlx5_cmd_map_ext_rxq_parsed,
599 .data = NULL,
600 .help_str = "mlx5 port <port_id> ext_rxq map <sw_queue_id> <hw_queue_id>",
601 .tokens = {
602 (void *)&mlx5_cmd_map_ext_rxq_mlx5,
603 (void *)&mlx5_cmd_map_ext_rxq_port,
604 (void *)&mlx5_cmd_map_ext_rxq_port_id,
605 (void *)&mlx5_cmd_map_ext_rxq_ext_rxq,
606 (void *)&mlx5_cmd_map_ext_rxq_map,
607 (void *)&mlx5_cmd_map_ext_rxq_sw_queue_id,
608 (void *)&mlx5_cmd_map_ext_rxq_hw_queue_id,
609 NULL,
610 }
611 };
612
613 /* Unmap HW queue index to rte queue index. */
614 struct mlx5_cmd_unmap_ext_rxq {
615 cmdline_fixed_string_t mlx5;
616 cmdline_fixed_string_t port;
617 portid_t port_id;
618 cmdline_fixed_string_t ext_rxq;
619 cmdline_fixed_string_t unmap;
620 uint16_t queue_id;
621 };
622
623 cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_mlx5 =
624 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, mlx5, "mlx5");
625 cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_port =
626 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port, "port");
627 cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_port_id =
628 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port_id,
629 RTE_UINT16);
630 cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_ext_rxq =
631 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, ext_rxq,
632 "ext_rxq");
633 cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_unmap =
634 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, unmap, "unmap");
635 cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_queue_id =
636 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, queue_id,
637 RTE_UINT16);
638
639 static void
mlx5_cmd_unmap_ext_rxq_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)640 mlx5_cmd_unmap_ext_rxq_parsed(void *parsed_result,
641 __rte_unused struct cmdline *cl,
642 __rte_unused void *data)
643 {
644 struct mlx5_cmd_unmap_ext_rxq *res = parsed_result;
645 int ret;
646
647 if (port_id_is_invalid(res->port_id, ENABLED_WARN))
648 return;
649 ret = rte_pmd_mlx5_external_rx_queue_id_unmap(res->port_id,
650 res->queue_id);
651 switch (ret) {
652 case 0:
653 break;
654 case -EINVAL:
655 fprintf(stderr, "invalid rte_flow index (%u), "
656 "out of range, doesn't exist or still referenced\n",
657 res->queue_id);
658 break;
659 case -ENODEV:
660 fprintf(stderr, "invalid port_id %u\n", res->port_id);
661 break;
662 case -ENOTSUP:
663 fprintf(stderr, "function not implemented or supported\n");
664 break;
665 default:
666 fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
667 }
668 }
669
670 cmdline_parse_inst_t mlx5_cmd_unmap_ext_rxq = {
671 .f = mlx5_cmd_unmap_ext_rxq_parsed,
672 .data = NULL,
673 .help_str = "mlx5 port <port_id> ext_rxq unmap <queue_id>",
674 .tokens = {
675 (void *)&mlx5_cmd_unmap_ext_rxq_mlx5,
676 (void *)&mlx5_cmd_unmap_ext_rxq_port,
677 (void *)&mlx5_cmd_unmap_ext_rxq_port_id,
678 (void *)&mlx5_cmd_unmap_ext_rxq_ext_rxq,
679 (void *)&mlx5_cmd_unmap_ext_rxq_unmap,
680 (void *)&mlx5_cmd_unmap_ext_rxq_queue_id,
681 NULL,
682 }
683 };
684
685 /* Set flow engine mode with flags command. */
686 struct mlx5_cmd_set_flow_engine_mode {
687 cmdline_fixed_string_t mlx5;
688 cmdline_fixed_string_t set;
689 cmdline_fixed_string_t flow_engine;
690 cmdline_multi_string_t mode;
691 };
692
693 static int
parse_multi_token_flow_engine_mode(char * t_str,enum rte_pmd_mlx5_flow_engine_mode * mode,uint32_t * flag)694 parse_multi_token_flow_engine_mode(char *t_str,
695 enum rte_pmd_mlx5_flow_engine_mode *mode, uint32_t *flag)
696 {
697 uint64_t val;
698 char *token;
699 int ret;
700
701 *flag = 0;
702 /* First token: mode string */
703 token = strtok_r(t_str, PARSE_DELIMITER, &t_str);
704 if (token == NULL)
705 return -1;
706
707 if (!strcmp(token, "active"))
708 *mode = RTE_PMD_MLX5_FLOW_ENGINE_MODE_ACTIVE;
709 else if (!strcmp(token, "standby"))
710 *mode = RTE_PMD_MLX5_FLOW_ENGINE_MODE_STANDBY;
711 else
712 return -1;
713
714 /* Second token: flag */
715 token = strtok_r(t_str, PARSE_DELIMITER, &t_str);
716 if (token == NULL)
717 return 0;
718
719 ret = parse_uint(&val, token);
720 if (ret != 0 || val > UINT32_MAX)
721 return -1;
722
723 *flag = val;
724 return 0;
725 }
726
727 static void
mlx5_cmd_set_flow_engine_mode_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)728 mlx5_cmd_set_flow_engine_mode_parsed(void *parsed_result,
729 __rte_unused struct cmdline *cl,
730 __rte_unused void *data)
731 {
732 struct mlx5_cmd_set_flow_engine_mode *res = parsed_result;
733 enum rte_pmd_mlx5_flow_engine_mode mode;
734 uint32_t flag;
735 int ret;
736
737 ret = parse_multi_token_flow_engine_mode(res->mode, &mode, &flag);
738
739 if (ret < 0) {
740 fprintf(stderr, "Bad input\n");
741 return;
742 }
743
744 ret = rte_pmd_mlx5_flow_engine_set_mode(mode, flag);
745
746 if (ret < 0)
747 fprintf(stderr, "Fail to set flow_engine to %s mode with flag 0x%x, error %s\n",
748 mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_ACTIVE ? "active" : "standby", flag,
749 strerror(-ret));
750 else
751 TESTPMD_LOG(DEBUG, "Set %d ports flow_engine to %s mode with flag 0x%x\n", ret,
752 mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_ACTIVE ? "active" : "standby", flag);
753 }
754
755 cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_mlx5 =
756 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, mlx5,
757 "mlx5");
758 cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_set =
759 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, set,
760 "set");
761 cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_flow_engine =
762 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, flow_engine,
763 "flow_engine");
764 cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_mode =
765 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, mode,
766 TOKEN_STRING_MULTI);
767
768 cmdline_parse_inst_t mlx5_cmd_set_flow_engine_mode = {
769 .f = &mlx5_cmd_set_flow_engine_mode_parsed,
770 .data = NULL,
771 .help_str = "mlx5 set flow_engine <active|standby> [<flag>]",
772 .tokens = {
773 (void *)&mlx5_cmd_set_flow_engine_mode_mlx5,
774 (void *)&mlx5_cmd_set_flow_engine_mode_set,
775 (void *)&mlx5_cmd_set_flow_engine_mode_flow_engine,
776 (void *)&mlx5_cmd_set_flow_engine_mode_mode,
777 NULL,
778 }
779 };
780
781 /* Prepare single GENEVE TLV option and add it into global option list. */
782 struct mlx5_cmd_set_tlv_option {
783 cmdline_fixed_string_t mlx5;
784 cmdline_fixed_string_t set;
785 cmdline_fixed_string_t tlv_option;
786 cmdline_fixed_string_t class;
787 uint16_t class_id;
788 cmdline_fixed_string_t type;
789 uint8_t type_id;
790 cmdline_fixed_string_t len;
791 uint8_t option_len;
792 cmdline_fixed_string_t offset;
793 uint8_t off;
794 cmdline_fixed_string_t sample_len;
795 uint8_t length;
796 cmdline_fixed_string_t class_mode;
797 cmdline_fixed_string_t cmode;
798 cmdline_fixed_string_t data;
799 cmdline_fixed_string_t data_mask;
800 };
801
802 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_mlx5 =
803 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, mlx5, "mlx5");
804 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_set =
805 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, set, "set");
806 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_tlv_option =
807 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, tlv_option,
808 "tlv_option");
809 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_class =
810 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, class,
811 "class");
812 cmdline_parse_token_num_t mlx5_cmd_set_tlv_option_class_id =
813 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_set_tlv_option, class_id,
814 RTE_UINT16);
815 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_type =
816 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, type, "type");
817 cmdline_parse_token_num_t mlx5_cmd_set_tlv_option_type_id =
818 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_set_tlv_option, type_id,
819 RTE_UINT8);
820 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_len =
821 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, len, "len");
822 cmdline_parse_token_num_t mlx5_cmd_set_tlv_option_option_len =
823 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_set_tlv_option, option_len,
824 RTE_UINT8);
825 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_offset =
826 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, offset,
827 "offset");
828 cmdline_parse_token_num_t mlx5_cmd_set_tlv_option_off =
829 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_set_tlv_option, off, RTE_UINT8);
830 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_sample_len =
831 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, sample_len,
832 "sample_len");
833 cmdline_parse_token_num_t mlx5_cmd_set_tlv_option_length =
834 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_set_tlv_option, length,
835 RTE_UINT8);
836 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_class_mode =
837 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, class_mode,
838 "class_mode");
839 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_cmode =
840 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, cmode,
841 "ignored#fixed#matchable");
842 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_data =
843 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, data, "data");
844 cmdline_parse_token_string_t mlx5_cmd_set_tlv_option_data_mask =
845 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_tlv_option, data_mask, "");
846
847 static void
mlx5_cmd_set_tlv_option_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)848 mlx5_cmd_set_tlv_option_parsed(void *parsed_result,
849 __rte_unused struct cmdline *cl,
850 __rte_unused void *data)
851 {
852 struct mlx5_cmd_set_tlv_option *res = parsed_result;
853 struct rte_pmd_mlx5_geneve_tlv *option;
854 uint8_t class_mode;
855 int ret;
856
857 if (tlv_mng.nb_options == MAX_GENEVE_OPTIONS_RESOURCES) {
858 fprintf(stderr, "GENEVE TLV option list is full\n");
859 return;
860 }
861
862 if (res->option_len < res->length + res->off) {
863 fprintf(stderr,
864 "GENEVE TLV option length (%u) cannot be less than offset (%u) + sample_len (%u)\n",
865 res->option_len, res->length, res->off);
866 return;
867 }
868
869 if (res->option_len > 32) {
870 fprintf(stderr,
871 "GENEVE TLV option length (%u) must be less than 32\n",
872 res->option_len);
873 return;
874 }
875
876 class_mode = string2mode(res->cmode);
877 if (class_mode == UINT8_MAX) {
878 fprintf(stderr, "Invalid class mode \"%s\"\n", res->cmode);
879 return;
880 }
881
882 if (res->length > 0) {
883 if (strcmp(res->data, "data") || !strcmp(res->data_mask, "")) {
884 fprintf(stderr,
885 "sample_len is %u but any data isn't provided\n",
886 res->length);
887 return;
888 }
889 } else {
890 if (!strcmp(res->data, "data") && strcmp(res->data_mask, "")) {
891 fprintf(stderr,
892 "sample_len is 0 but data is provided (%s)\n",
893 res->data_mask);
894 return;
895 }
896 }
897
898 option = &tlv_mng.tlv_list[tlv_mng.nb_options];
899 ret = mlx5_test_parse_geneve_option_data(res->data_mask, res->length,
900 &option->match_data_mask);
901 if (ret < 0)
902 return;
903
904 option->match_on_class_mode = class_mode;
905 option->option_class = rte_cpu_to_be_16(res->class_id);
906 option->option_type = res->type_id;
907 option->option_len = res->option_len;
908 option->offset = res->off;
909 option->sample_len = res->length;
910 tlv_mng.nb_options++;
911
912 TESTPMD_LOG(DEBUG,
913 "set new option in global list, now it has %u options\n",
914 tlv_mng.nb_options);
915 }
916
917 cmdline_parse_inst_t mlx5_cmd_set_tlv_option = {
918 .f = mlx5_cmd_set_tlv_option_parsed,
919 .data = NULL,
920 .help_str = "mlx5 set tlv_option class <class_id> type <type_id> len "
921 "<option_len> offset <sample_offset> sample_len "
922 "<sample_length> class_mode <ignored|fixed|matchable> data <mask1 [mask2 [...]>",
923 .tokens = {
924 (void *)&mlx5_cmd_set_tlv_option_mlx5,
925 (void *)&mlx5_cmd_set_tlv_option_set,
926 (void *)&mlx5_cmd_set_tlv_option_tlv_option,
927 (void *)&mlx5_cmd_set_tlv_option_class,
928 (void *)&mlx5_cmd_set_tlv_option_class_id,
929 (void *)&mlx5_cmd_set_tlv_option_type,
930 (void *)&mlx5_cmd_set_tlv_option_type_id,
931 (void *)&mlx5_cmd_set_tlv_option_len,
932 (void *)&mlx5_cmd_set_tlv_option_option_len,
933 (void *)&mlx5_cmd_set_tlv_option_offset,
934 (void *)&mlx5_cmd_set_tlv_option_off,
935 (void *)&mlx5_cmd_set_tlv_option_sample_len,
936 (void *)&mlx5_cmd_set_tlv_option_length,
937 (void *)&mlx5_cmd_set_tlv_option_class_mode,
938 (void *)&mlx5_cmd_set_tlv_option_cmode,
939 (void *)&mlx5_cmd_set_tlv_option_data,
940 (void *)&mlx5_cmd_set_tlv_option_data_mask,
941 NULL,
942 }
943 };
944
945 /* Print all GENEVE TLV options which are configured so far. */
946 struct mlx5_cmd_list_tlv_options {
947 cmdline_fixed_string_t mlx5;
948 cmdline_fixed_string_t list;
949 cmdline_fixed_string_t tlv_options;
950 };
951
952 cmdline_parse_token_string_t mlx5_cmd_list_tlv_options_mlx5 =
953 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_list_tlv_options, mlx5,
954 "mlx5");
955 cmdline_parse_token_string_t mlx5_cmd_list_tlv_options_list =
956 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_list_tlv_options, list,
957 "list");
958 cmdline_parse_token_string_t mlx5_cmd_list_tlv_options_tlv_options =
959 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_list_tlv_options, tlv_options,
960 "tlv_options");
961
962 static void
mlx5_cmd_list_tlv_options_parsed(__rte_unused void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)963 mlx5_cmd_list_tlv_options_parsed(__rte_unused void *parsed_result,
964 __rte_unused struct cmdline *cl,
965 __rte_unused void *data)
966 {
967 struct rte_pmd_mlx5_geneve_tlv *option;
968 uint8_t i, j;
969
970 printf("ID\tType\tClass\tClass_mode\tLen\tOffset\tSample_len\tData\n");
971 for (i = 0; i < tlv_mng.nb_options; ++i) {
972 option = &tlv_mng.tlv_list[i];
973 printf("%u\t%u\t%u\t%s\t%u\t%u\t%u\t\t", i,
974 option->option_type, rte_be_to_cpu_16(option->option_class),
975 mode2string(option->match_on_class_mode),
976 option->option_len,
977 option->offset, option->sample_len);
978 for (j = 0; j < option->sample_len; ++j)
979 printf("0x%x ", option->match_data_mask[j]);
980 printf("\n");
981 }
982 }
983
984 cmdline_parse_inst_t mlx5_cmd_list_tlv_options = {
985 .f = mlx5_cmd_list_tlv_options_parsed,
986 .data = NULL,
987 .help_str = "mlx5 list tlv_options",
988 .tokens = {
989 (void *)&mlx5_cmd_list_tlv_options_mlx5,
990 (void *)&mlx5_cmd_list_tlv_options_list,
991 (void *)&mlx5_cmd_list_tlv_options_tlv_options,
992 NULL,
993 }
994 };
995
996 /* Clear all GENEVE TLV options which are configured so far. */
997 struct mlx5_cmd_flush_tlv_options {
998 cmdline_fixed_string_t mlx5;
999 cmdline_fixed_string_t flush;
1000 cmdline_fixed_string_t tlv_options;
1001 cmdline_fixed_string_t max;
1002 uint8_t number;
1003 };
1004
1005 cmdline_parse_token_string_t mlx5_cmd_flush_tlv_options_mlx5 =
1006 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_flush_tlv_options, mlx5,
1007 "mlx5");
1008 cmdline_parse_token_string_t mlx5_cmd_flush_tlv_options_flush =
1009 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_flush_tlv_options, flush,
1010 "flush");
1011 cmdline_parse_token_string_t mlx5_cmd_flush_tlv_options_tlv_options =
1012 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_flush_tlv_options, tlv_options,
1013 "tlv_options");
1014 cmdline_parse_token_string_t mlx5_cmd_flush_tlv_options_max =
1015 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_flush_tlv_options, max, "max");
1016 cmdline_parse_token_num_t mlx5_cmd_flush_tlv_options_number =
1017 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_flush_tlv_options, number,
1018 RTE_UINT8);
1019
1020 static void
mlx5_cmd_flush_tlv_options_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)1021 mlx5_cmd_flush_tlv_options_parsed(void *parsed_result,
1022 __rte_unused struct cmdline *cl,
1023 __rte_unused void *data)
1024 {
1025 struct mlx5_cmd_flush_tlv_options *res = parsed_result;
1026 struct rte_pmd_mlx5_geneve_tlv *option;
1027 uint8_t nb_options_flush = tlv_mng.nb_options;
1028 uint8_t nb_options_left = 0;
1029
1030 if (strcmp(res->max, "max") == 0 && res->number < tlv_mng.nb_options) {
1031 nb_options_left = tlv_mng.nb_options - res->number;
1032 nb_options_flush = RTE_MIN(res->number, nb_options_flush);
1033 }
1034
1035 while (tlv_mng.nb_options > nb_options_left) {
1036 tlv_mng.nb_options--;
1037 option = &tlv_mng.tlv_list[tlv_mng.nb_options];
1038 if (option->match_data_mask) {
1039 free(option->match_data_mask);
1040 option->match_data_mask = NULL;
1041 }
1042 }
1043
1044 TESTPMD_LOG(DEBUG, "Flush %u latest configured GENEVE TLV options, "
1045 "current number of options in the list is %u\n",
1046 nb_options_flush, nb_options_left);
1047 }
1048
1049 cmdline_parse_inst_t mlx5_cmd_flush_tlv_options = {
1050 .f = mlx5_cmd_flush_tlv_options_parsed,
1051 .data = NULL,
1052 .help_str = "mlx5 flush tlv_options max <nb_options>",
1053 .tokens = {
1054 (void *)&mlx5_cmd_flush_tlv_options_mlx5,
1055 (void *)&mlx5_cmd_flush_tlv_options_flush,
1056 (void *)&mlx5_cmd_flush_tlv_options_tlv_options,
1057 (void *)&mlx5_cmd_flush_tlv_options_max,
1058 (void *)&mlx5_cmd_flush_tlv_options_number,
1059 NULL,
1060 }
1061 };
1062
1063 /* Create GENEVE TLV parser using option list which is configured before. */
1064 struct mlx5_cmd_apply_tlv_options {
1065 cmdline_fixed_string_t mlx5;
1066 cmdline_fixed_string_t port;
1067 portid_t port_id;
1068 cmdline_fixed_string_t apply;
1069 cmdline_fixed_string_t tlv_options;
1070 };
1071
1072 cmdline_parse_token_string_t mlx5_cmd_apply_tlv_options_mlx5 =
1073 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_apply_tlv_options, mlx5,
1074 "mlx5");
1075 cmdline_parse_token_string_t mlx5_cmd_apply_tlv_options_port =
1076 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_apply_tlv_options, port,
1077 "port");
1078 cmdline_parse_token_num_t mlx5_cmd_apply_tlv_options_port_id =
1079 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_apply_tlv_options, port_id,
1080 RTE_UINT16);
1081 cmdline_parse_token_string_t mlx5_cmd_apply_tlv_options_apply =
1082 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_apply_tlv_options, apply,
1083 "apply");
1084 cmdline_parse_token_string_t mlx5_cmd_apply_tlv_options_tlv_options =
1085 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_apply_tlv_options, tlv_options,
1086 "tlv_options");
1087
1088 static void
mlx5_cmd_apply_tlv_options_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)1089 mlx5_cmd_apply_tlv_options_parsed(void *parsed_result,
1090 __rte_unused struct cmdline *cl,
1091 __rte_unused void *data)
1092 {
1093 struct mlx5_cmd_apply_tlv_options *res = parsed_result;
1094 struct mlx5_port *port;
1095 void *handle;
1096
1097 if (port_id_is_invalid(res->port_id, ENABLED_WARN))
1098 return;
1099
1100 if (tlv_mng.nb_options == 0) {
1101 fprintf(stderr, "The option list is empty, please set options\n");
1102 return;
1103 }
1104
1105 handle = rte_pmd_mlx5_create_geneve_tlv_parser(res->port_id,
1106 tlv_mng.tlv_list,
1107 tlv_mng.nb_options);
1108 if (handle == NULL) {
1109 fprintf(stderr,
1110 "Fail to create GENEVE TLV parser, nb_option=%u: %s\n",
1111 tlv_mng.nb_options, strerror(rte_errno));
1112 return;
1113 }
1114
1115 TESTPMD_LOG(DEBUG, "GENEVE TLV options parser is successfully created:"
1116 " nb_option=%u, handle=%p\n", tlv_mng.nb_options, handle);
1117
1118 port = &private_port[res->port_id];
1119 port->geneve_tlv_parser_handle = handle;
1120 }
1121
1122 cmdline_parse_inst_t mlx5_cmd_apply_tlv_options = {
1123 .f = mlx5_cmd_apply_tlv_options_parsed,
1124 .data = NULL,
1125 .help_str = "mlx5 port <port_id> apply tlv_options",
1126 .tokens = {
1127 (void *)&mlx5_cmd_apply_tlv_options_mlx5,
1128 (void *)&mlx5_cmd_apply_tlv_options_port,
1129 (void *)&mlx5_cmd_apply_tlv_options_port_id,
1130 (void *)&mlx5_cmd_apply_tlv_options_apply,
1131 (void *)&mlx5_cmd_apply_tlv_options_tlv_options,
1132 NULL,
1133 }
1134 };
1135
1136 /* Destroy GENEVE TLV parser created by apply command. */
1137 struct mlx5_cmd_destroy_tlv_options {
1138 cmdline_fixed_string_t mlx5;
1139 cmdline_fixed_string_t port;
1140 portid_t port_id;
1141 cmdline_fixed_string_t destroy;
1142 cmdline_fixed_string_t tlv_options;
1143 };
1144
1145 cmdline_parse_token_string_t mlx5_cmd_destroy_tlv_options_mlx5 =
1146 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_destroy_tlv_options, mlx5,
1147 "mlx5");
1148 cmdline_parse_token_string_t mlx5_cmd_destroy_tlv_options_port =
1149 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_destroy_tlv_options, port,
1150 "port");
1151 cmdline_parse_token_num_t mlx5_cmd_destroy_tlv_options_port_id =
1152 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_destroy_tlv_options, port_id,
1153 RTE_UINT16);
1154 cmdline_parse_token_string_t mlx5_cmd_destroy_tlv_options_destroy =
1155 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_destroy_tlv_options, destroy,
1156 "destroy");
1157 cmdline_parse_token_string_t mlx5_cmd_destroy_tlv_options_tlv_options =
1158 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_destroy_tlv_options, tlv_options,
1159 "tlv_options");
1160
1161 static void
mlx5_cmd_destroy_tlv_options_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)1162 mlx5_cmd_destroy_tlv_options_parsed(void *parsed_result,
1163 __rte_unused struct cmdline *cl,
1164 __rte_unused void *data)
1165 {
1166 struct mlx5_cmd_destroy_tlv_options *res = parsed_result;
1167 struct mlx5_port *port;
1168 int ret;
1169
1170 if (port_id_is_invalid(res->port_id, ENABLED_WARN))
1171 return;
1172
1173 port = &private_port[res->port_id];
1174 if (!port->geneve_tlv_parser_handle)
1175 return;
1176
1177 ret = rte_pmd_mlx5_destroy_geneve_tlv_parser(port->geneve_tlv_parser_handle);
1178 if (ret < 0) {
1179 fprintf(stderr, "Fail to destroy GENEVE TLV parser: %s\n",
1180 strerror(-ret));
1181 return;
1182 }
1183
1184 TESTPMD_LOG(DEBUG, "GENEVE TLV options parser is successfully released:"
1185 " handle=%p\n", port->geneve_tlv_parser_handle);
1186
1187 port->geneve_tlv_parser_handle = NULL;
1188 }
1189
1190 cmdline_parse_inst_t mlx5_cmd_destroy_tlv_options = {
1191 .f = mlx5_cmd_destroy_tlv_options_parsed,
1192 .data = NULL,
1193 .help_str = "mlx5 port <port_id> destroy tlv_options",
1194 .tokens = {
1195 (void *)&mlx5_cmd_destroy_tlv_options_mlx5,
1196 (void *)&mlx5_cmd_destroy_tlv_options_port,
1197 (void *)&mlx5_cmd_destroy_tlv_options_port_id,
1198 (void *)&mlx5_cmd_destroy_tlv_options_destroy,
1199 (void *)&mlx5_cmd_destroy_tlv_options_tlv_options,
1200 NULL,
1201 }
1202 };
1203
1204 /* Dump SQ Context for a given port/queue*/
1205 struct mlx5_cmd_dump_sq_context_options {
1206 cmdline_fixed_string_t mlx5;
1207 cmdline_fixed_string_t port;
1208 portid_t port_id;
1209 cmdline_fixed_string_t queue;
1210 queueid_t queue_id;
1211 cmdline_fixed_string_t dump;
1212 cmdline_fixed_string_t sq_context;
1213 cmdline_fixed_string_t file_name;
1214 };
1215
1216 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_mlx5 =
1217 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, mlx5,
1218 "mlx5");
1219 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_port =
1220 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, port,
1221 "port");
1222 cmdline_parse_token_num_t mlx5_cmd_dump_sq_context_options_port_id =
1223 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, port_id,
1224 RTE_UINT16);
1225 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_queue =
1226 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, queue,
1227 "queue");
1228 cmdline_parse_token_num_t mlx5_cmd_dump_sq_context_options_queue_id =
1229 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, queue_id,
1230 RTE_UINT16);
1231 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_dump =
1232 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, dump,
1233 "dump");
1234 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_sq_context =
1235 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, sq_context,
1236 "sq_context");
1237 cmdline_parse_token_string_t mlx5_cmd_dump_sq_context_options_file_name =
1238 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_sq_context_options, file_name,
1239 NULL);
1240
1241 static void
mlx5_cmd_dump_sq_context_options_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)1242 mlx5_cmd_dump_sq_context_options_parsed(void *parsed_result,
1243 __rte_unused struct cmdline *cl,
1244 __rte_unused void *data)
1245 {
1246 struct mlx5_cmd_dump_sq_context_options *res = parsed_result;
1247 int ret;
1248
1249 ret = rte_pmd_mlx5_txq_dump_contexts(res->port_id, res->queue_id, res->file_name);
1250
1251 switch (ret) {
1252 case 0:
1253 break;
1254 case -EINVAL:
1255 fprintf(stderr, "invalid queue index (%u), out of range\n",
1256 res->queue_id);
1257 break;
1258 case -ENODEV:
1259 fprintf(stderr, "invalid port_id %u\n", res->port_id);
1260 break;
1261 case -EIO:
1262 fprintf(stderr, "File Access Error (%s)\n", strerror(rte_errno));
1263 break;
1264 default:
1265 fprintf(stderr, "Unable to dump SQ/CQ HW Context (%s)\n", strerror(rte_errno));
1266 }
1267 }
1268
1269 cmdline_parse_inst_t mlx5_cmd_dump_sq_context_options = {
1270 .f = mlx5_cmd_dump_sq_context_options_parsed,
1271 .data = NULL,
1272 .help_str = "mlx5 port <port_id> queue <queue_id> dump sq_context <file_name>",
1273 .tokens = {
1274 (void *)&mlx5_cmd_dump_sq_context_options_mlx5,
1275 (void *)&mlx5_cmd_dump_sq_context_options_port,
1276 (void *)&mlx5_cmd_dump_sq_context_options_port_id,
1277 (void *)&mlx5_cmd_dump_sq_context_options_queue,
1278 (void *)&mlx5_cmd_dump_sq_context_options_queue_id,
1279 (void *)&mlx5_cmd_dump_sq_context_options_dump,
1280 (void *)&mlx5_cmd_dump_sq_context_options_sq_context,
1281 (void *)&mlx5_cmd_dump_sq_context_options_file_name,
1282 NULL,
1283 }
1284 };
1285
1286 /* Dump RQ Context for a given port/queue*/
1287 struct mlx5_cmd_dump_rq_context_options {
1288 cmdline_fixed_string_t mlx5;
1289 cmdline_fixed_string_t port;
1290 portid_t port_id;
1291 cmdline_fixed_string_t queue;
1292 queueid_t queue_id;
1293 cmdline_fixed_string_t dump;
1294 cmdline_fixed_string_t rq_context;
1295 cmdline_fixed_string_t file_name;
1296 };
1297
1298 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_mlx5 =
1299 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, mlx5,
1300 "mlx5");
1301 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_port =
1302 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, port,
1303 "port");
1304 cmdline_parse_token_num_t mlx5_cmd_dump_rq_context_options_port_id =
1305 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, port_id,
1306 RTE_UINT16);
1307 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_queue =
1308 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, queue,
1309 "queue");
1310 cmdline_parse_token_num_t mlx5_cmd_dump_rq_context_options_queue_id =
1311 TOKEN_NUM_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, queue_id,
1312 RTE_UINT16);
1313 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_dump =
1314 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, dump,
1315 "dump");
1316 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_rq_context =
1317 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, rq_context,
1318 "rq_context");
1319 cmdline_parse_token_string_t mlx5_cmd_dump_rq_context_options_file_name =
1320 TOKEN_STRING_INITIALIZER(struct mlx5_cmd_dump_rq_context_options, file_name,
1321 NULL);
1322
1323 static void
mlx5_cmd_dump_rq_context_options_parsed(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)1324 mlx5_cmd_dump_rq_context_options_parsed(void *parsed_result,
1325 __rte_unused struct cmdline *cl,
1326 __rte_unused void *data)
1327 {
1328 struct mlx5_cmd_dump_rq_context_options *res = parsed_result;
1329 int ret;
1330
1331 ret = rte_pmd_mlx5_rxq_dump_contexts(res->port_id, res->queue_id, res->file_name);
1332
1333 switch (ret) {
1334 case 0:
1335 break;
1336 case -EINVAL:
1337 fprintf(stderr, "invalid queue index (%u), out of range\n",
1338 res->queue_id);
1339 break;
1340 case -ENODEV:
1341 fprintf(stderr, "invalid port_id %u\n", res->port_id);
1342 break;
1343 case -EIO:
1344 fprintf(stderr, "File Access Error (%s)\n", strerror(rte_errno));
1345 break;
1346 default:
1347 fprintf(stderr, "Unable to dump RQ/CQ HW Context (%s)\n", strerror(rte_errno));
1348 }
1349 }
1350
1351 cmdline_parse_inst_t mlx5_cmd_dump_rq_context_options = {
1352 .f = mlx5_cmd_dump_rq_context_options_parsed,
1353 .data = NULL,
1354 .help_str = "mlx5 port <port_id> queue <queue_id> dump rq_context <file_name>",
1355 .tokens = {
1356 (void *)&mlx5_cmd_dump_rq_context_options_mlx5,
1357 (void *)&mlx5_cmd_dump_rq_context_options_port,
1358 (void *)&mlx5_cmd_dump_rq_context_options_port_id,
1359 (void *)&mlx5_cmd_dump_rq_context_options_queue,
1360 (void *)&mlx5_cmd_dump_rq_context_options_queue_id,
1361 (void *)&mlx5_cmd_dump_rq_context_options_dump,
1362 (void *)&mlx5_cmd_dump_rq_context_options_rq_context,
1363 (void *)&mlx5_cmd_dump_rq_context_options_file_name,
1364 NULL,
1365 }
1366 };
1367
1368 static struct testpmd_driver_commands mlx5_driver_cmds = {
1369 .commands = {
1370 {
1371 .ctx = &mlx5_test_cmd_port_host_shaper,
1372 .help = "mlx5 set port (port_id) host_shaper avail_thresh_triggered (on|off)"
1373 "rate (rate_num):\n"
1374 " Set HOST_SHAPER avail_thresh_triggered and rate with port_id\n\n",
1375 },
1376 #ifndef RTE_EXEC_ENV_WINDOWS
1377 {
1378 .ctx = &mlx5_cmd_operate_attach_port,
1379 .help = "mlx5 port attach (ident) socket=(path)\n"
1380 " Attach physical or virtual dev by pci address or virtual device name "
1381 "and add \"cmd_fd\" and \"pd_handle\" devargs before attaching\n\n",
1382 },
1383 #endif
1384 {
1385 .ctx = &mlx5_cmd_map_ext_rxq,
1386 .help = "mlx5 port (port_id) ext_rxq map (sw_queue_id) (hw_queue_id)\n"
1387 " Map HW queue index (32-bit) to ethdev"
1388 " queue index (16-bit) for external RxQ\n\n",
1389 },
1390 {
1391 .ctx = &mlx5_cmd_unmap_ext_rxq,
1392 .help = "mlx5 port (port_id) ext_rxq unmap (sw_queue_id)\n"
1393 " Unmap external Rx queue ethdev index mapping\n\n",
1394 },
1395 {
1396 .ctx = &mlx5_cmd_set_flow_engine_mode,
1397 .help = "mlx5 set flow_engine (active|standby) [(flag)]\n"
1398 " Set flow_engine to the specific mode with flag.\n\n"
1399 },
1400 {
1401 .ctx = &mlx5_cmd_set_tlv_option,
1402 .help = "mlx5 set tlv_option class (class_id) type "
1403 "(type_id) len (option_length) offset "
1404 "(sample_offset) sample_len (sample_length) "
1405 "class_mode (ignored|fixed|matchable) "
1406 "data (mask1) [(mask2) [...]]\n"
1407 " Set single GENEVE TLV option inside global list "
1408 "using later by apply command\n\n",
1409 },
1410 {
1411 .ctx = &mlx5_cmd_list_tlv_options,
1412 .help = "mlx5 list tlv_options\n"
1413 " Print all GENEVE TLV options which are configured "
1414 "so far by TLV option set command\n\n",
1415 },
1416 {
1417 .ctx = &mlx5_cmd_flush_tlv_options,
1418 .help = "mlx5 flush tlv_options [max (number options)]\n"
1419 " Clear all GENEVE TLV options which are configured "
1420 "so far by TLV option set command\n\n",
1421 },
1422 {
1423 .ctx = &mlx5_cmd_apply_tlv_options,
1424 .help = "mlx5 port (port_id) apply tlv_options\n"
1425 " Create GENEVE TLV parser using option list which is "
1426 "configured before by TLV option set command\n\n",
1427 },
1428 {
1429 .ctx = &mlx5_cmd_destroy_tlv_options,
1430 .help = "mlx5 port (port_id) destroy tlv_options\n"
1431 " Destroy GENEVE TLV parser\n\n",
1432 },
1433 {
1434 .ctx = &mlx5_cmd_dump_sq_context_options,
1435 .help = "mlx5 port (port_id) queue (queue_id) dump sq_context (file_name)\n"
1436 " Dump mlx5 SQ Context\n\n",
1437 },
1438 {
1439 .ctx = &mlx5_cmd_dump_rq_context_options,
1440 .help = "mlx5 port (port_id) queue (queue_id) dump rq_context (file_name)\n"
1441 " Dump mlx5 RQ Context\n\n",
1442 },
1443 {
1444 .ctx = NULL,
1445 },
1446 }
1447 };
1448 TESTPMD_ADD_DRIVER_COMMANDS(mlx5_driver_cmds);
1449