xref: /dpdk/drivers/net/mlx5/mlx5_testpmd.c (revision 3dfa78770ed53c376df2da7c2bd997e0b2d33cd1)
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