xref: /dpdk/drivers/net/mlx5/mlx5_testpmd.c (revision 740a28366cc0735b8ea83c2b4fc6d407a76dc5f8)
1f41a5092SSpike Du /* SPDX-License-Identifier: BSD-3-Clause
2f41a5092SSpike Du  * Copyright 2021 6WIND S.A.
3f41a5092SSpike Du  * Copyright 2021 Mellanox Technologies, Ltd
4f41a5092SSpike Du  */
5f41a5092SSpike Du 
6f41a5092SSpike Du #include <stdint.h>
7f41a5092SSpike Du #include <string.h>
8f41a5092SSpike Du #include <stdlib.h>
985d9252eSMichael Baum #include <unistd.h>
1085d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
1185d9252eSMichael Baum #include <sys/socket.h>
1285d9252eSMichael Baum #include <sys/un.h>
1385d9252eSMichael Baum #endif
14f41a5092SSpike Du 
15f41a5092SSpike Du #include <rte_prefetch.h>
16f41a5092SSpike Du #include <rte_common.h>
17f41a5092SSpike Du #include <rte_branch_prediction.h>
18f41a5092SSpike Du #include <rte_ether.h>
19f41a5092SSpike Du #include <rte_alarm.h>
20f41a5092SSpike Du #include <rte_pmd_mlx5.h>
21f41a5092SSpike Du #include <rte_ethdev.h>
2285d9252eSMichael Baum 
23f41a5092SSpike Du #include "mlx5_testpmd.h"
24f41a5092SSpike Du #include "testpmd.h"
25f41a5092SSpike Du 
26f41a5092SSpike Du static uint8_t host_shaper_avail_thresh_triggered[RTE_MAX_ETHPORTS];
27f41a5092SSpike Du #define SHAPER_DISABLE_DELAY_US 100000 /* 100ms */
28f41a5092SSpike Du 
29f41a5092SSpike Du /**
30f41a5092SSpike Du  * Disable the host shaper and re-arm available descriptor threshold event.
31f41a5092SSpike Du  *
32f41a5092SSpike Du  * @param[in] args
33f41a5092SSpike Du  *   uint32_t integer combining port_id and rxq_id.
34f41a5092SSpike Du  */
35f41a5092SSpike Du static void
36f41a5092SSpike Du mlx5_test_host_shaper_disable(void *args)
37f41a5092SSpike Du {
38f41a5092SSpike Du 	uint32_t port_rxq_id = (uint32_t)(uintptr_t)args;
39f41a5092SSpike Du 	uint16_t port_id = port_rxq_id & 0xffff;
40f41a5092SSpike Du 	uint16_t qid = (port_rxq_id >> 16) & 0xffff;
41f41a5092SSpike Du 	struct rte_eth_rxq_info qinfo;
42f41a5092SSpike Du 
43f41a5092SSpike Du 	printf("%s disable shaper\n", __func__);
44f41a5092SSpike Du 	if (rte_eth_rx_queue_info_get(port_id, qid, &qinfo)) {
45f41a5092SSpike Du 		printf("rx_queue_info_get returns error\n");
46f41a5092SSpike Du 		return;
47f41a5092SSpike Du 	}
48f41a5092SSpike Du 	/* Rearm the available descriptor threshold event. */
49f41a5092SSpike Du 	if (rte_eth_rx_avail_thresh_set(port_id, qid, qinfo.avail_thresh)) {
50f41a5092SSpike Du 		printf("config avail_thresh returns error\n");
51f41a5092SSpike Du 		return;
52f41a5092SSpike Du 	}
53f41a5092SSpike Du 	/* Only disable the shaper when avail_thresh_triggered is set. */
54f41a5092SSpike Du 	if (host_shaper_avail_thresh_triggered[port_id] &&
55f41a5092SSpike Du 	    rte_pmd_mlx5_host_shaper_config(port_id, 0, 0))
56f41a5092SSpike Du 		printf("%s disable shaper returns error\n", __func__);
57f41a5092SSpike Du }
58f41a5092SSpike Du 
59f41a5092SSpike Du void
60f41a5092SSpike Du mlx5_test_avail_thresh_event_handler(uint16_t port_id, uint16_t rxq_id)
61f41a5092SSpike Du {
62f41a5092SSpike Du 	struct rte_eth_dev_info dev_info;
63f41a5092SSpike Du 	uint32_t port_rxq_id = port_id | (rxq_id << 16);
64f41a5092SSpike Du 
65f41a5092SSpike Du 	/* Ensure it's MLX5 port. */
66f41a5092SSpike Du 	if (rte_eth_dev_info_get(port_id, &dev_info) != 0 ||
67f41a5092SSpike Du 	    (strncmp(dev_info.driver_name, "mlx5", 4) != 0))
68f41a5092SSpike Du 		return;
69f41a5092SSpike Du 	rte_eal_alarm_set(SHAPER_DISABLE_DELAY_US,
70f41a5092SSpike Du 			  mlx5_test_host_shaper_disable,
71f41a5092SSpike Du 			  (void *)(uintptr_t)port_rxq_id);
72f41a5092SSpike Du 	printf("%s port_id:%u rxq_id:%u\n", __func__, port_id, rxq_id);
73f41a5092SSpike Du }
74f41a5092SSpike Du 
75f41a5092SSpike Du /**
76f41a5092SSpike Du  * Configure host shaper's avail_thresh_triggered and current rate.
77f41a5092SSpike Du  *
78f41a5092SSpike Du  * @param[in] avail_thresh_triggered
79f41a5092SSpike Du  *   Disable/enable avail_thresh_triggered.
80f41a5092SSpike Du  * @param[in] rate
81f41a5092SSpike Du  *   Configure current host shaper rate.
82f41a5092SSpike Du  * @return
83f41a5092SSpike Du  *   On success, returns 0.
84f41a5092SSpike Du  *   On failure, returns < 0.
85f41a5092SSpike Du  */
86f41a5092SSpike Du static int
87f41a5092SSpike Du mlx5_test_set_port_host_shaper(uint16_t port_id, uint16_t avail_thresh_triggered, uint8_t rate)
88f41a5092SSpike Du {
89f41a5092SSpike Du 	struct rte_eth_link link;
90f41a5092SSpike Du 	bool port_id_valid = false;
91f41a5092SSpike Du 	uint16_t pid;
92f41a5092SSpike Du 	int ret;
93f41a5092SSpike Du 
94f41a5092SSpike Du 	RTE_ETH_FOREACH_DEV(pid)
95f41a5092SSpike Du 		if (port_id == pid) {
96f41a5092SSpike Du 			port_id_valid = true;
97f41a5092SSpike Du 			break;
98f41a5092SSpike Du 		}
99f41a5092SSpike Du 	if (!port_id_valid)
100f41a5092SSpike Du 		return -EINVAL;
101f41a5092SSpike Du 	ret = rte_eth_link_get_nowait(port_id, &link);
102f41a5092SSpike Du 	if (ret < 0)
103f41a5092SSpike Du 		return ret;
104f41a5092SSpike Du 	host_shaper_avail_thresh_triggered[port_id] = avail_thresh_triggered ? 1 : 0;
105f41a5092SSpike Du 	if (!avail_thresh_triggered) {
106f41a5092SSpike Du 		ret = rte_pmd_mlx5_host_shaper_config(port_id, 0,
107f41a5092SSpike Du 		RTE_BIT32(MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED));
108f41a5092SSpike Du 	} else {
109f41a5092SSpike Du 		ret = rte_pmd_mlx5_host_shaper_config(port_id, 1,
110f41a5092SSpike Du 		RTE_BIT32(MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED));
111f41a5092SSpike Du 	}
112f41a5092SSpike Du 	if (ret)
113f41a5092SSpike Du 		return ret;
114f41a5092SSpike Du 	ret = rte_pmd_mlx5_host_shaper_config(port_id, rate, 0);
115f41a5092SSpike Du 	if (ret)
116f41a5092SSpike Du 		return ret;
117f41a5092SSpike Du 	return 0;
118f41a5092SSpike Du }
119f41a5092SSpike Du 
12085d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
12185d9252eSMichael Baum static const char*
12285d9252eSMichael Baum mlx5_test_get_socket_path(char *extend)
12385d9252eSMichael Baum {
12485d9252eSMichael Baum 	if (strstr(extend, "socket=") == extend) {
12585d9252eSMichael Baum 		const char *socket_path = strchr(extend, '=') + 1;
12685d9252eSMichael Baum 
12785d9252eSMichael Baum 		TESTPMD_LOG(DEBUG, "MLX5 socket path is %s\n", socket_path);
12885d9252eSMichael Baum 		return socket_path;
12985d9252eSMichael Baum 	}
13085d9252eSMichael Baum 
13185d9252eSMichael Baum 	TESTPMD_LOG(ERR, "Failed to extract a valid socket path from %s\n",
13285d9252eSMichael Baum 		    extend);
13385d9252eSMichael Baum 	return NULL;
13485d9252eSMichael Baum }
13585d9252eSMichael Baum 
13685d9252eSMichael Baum static int
13785d9252eSMichael Baum mlx5_test_extend_devargs(char *identifier, char *extend)
13885d9252eSMichael Baum {
13985d9252eSMichael Baum 	struct sockaddr_un un = {
14085d9252eSMichael Baum 		.sun_family = AF_UNIX,
14185d9252eSMichael Baum 	};
14285d9252eSMichael Baum 	int cmd_fd;
14385d9252eSMichael Baum 	int pd_handle;
14485d9252eSMichael Baum 	struct iovec iov = {
14585d9252eSMichael Baum 		.iov_base = &pd_handle,
14685d9252eSMichael Baum 		.iov_len = sizeof(int),
14785d9252eSMichael Baum 	};
14885d9252eSMichael Baum 	union {
14985d9252eSMichael Baum 		char buf[CMSG_SPACE(sizeof(int))];
15085d9252eSMichael Baum 		struct cmsghdr align;
15185d9252eSMichael Baum 	} control;
15285d9252eSMichael Baum 	struct msghdr msgh = {
15385d9252eSMichael Baum 		.msg_iov = NULL,
15485d9252eSMichael Baum 		.msg_iovlen = 0,
15585d9252eSMichael Baum 	};
15685d9252eSMichael Baum 	struct cmsghdr *cmsg;
15785d9252eSMichael Baum 	const char *path = mlx5_test_get_socket_path(extend + 1);
15885d9252eSMichael Baum 	size_t len = 1;
15985d9252eSMichael Baum 	int socket_fd;
16085d9252eSMichael Baum 	int ret;
16185d9252eSMichael Baum 
16285d9252eSMichael Baum 	if (path == NULL) {
16385d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Invalid devargs extension is specified\n");
16485d9252eSMichael Baum 		return -1;
16585d9252eSMichael Baum 	}
16685d9252eSMichael Baum 
16785d9252eSMichael Baum 	/* Initialize IPC channel. */
16885d9252eSMichael Baum 	socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
16985d9252eSMichael Baum 	if (socket_fd < 0) {
17085d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to create unix socket: %s\n",
17185d9252eSMichael Baum 			    strerror(errno));
17285d9252eSMichael Baum 		return -1;
17385d9252eSMichael Baum 	}
17485d9252eSMichael Baum 	rte_strlcpy(un.sun_path, path, sizeof(un.sun_path));
17585d9252eSMichael Baum 	if (connect(socket_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
17685d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to connect %s: %s\n", un.sun_path,
17785d9252eSMichael Baum 			    strerror(errno));
17885d9252eSMichael Baum 		close(socket_fd);
17985d9252eSMichael Baum 		return -1;
18085d9252eSMichael Baum 	}
18185d9252eSMichael Baum 
18285d9252eSMichael Baum 	/* Send the request message. */
18385d9252eSMichael Baum 	do {
18485d9252eSMichael Baum 		ret = sendmsg(socket_fd, &msgh, 0);
18585d9252eSMichael Baum 	} while (ret < 0 && errno == EINTR);
18685d9252eSMichael Baum 	if (ret < 0) {
18785d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to send request to (%s): %s\n", path,
18885d9252eSMichael Baum 			    strerror(errno));
18985d9252eSMichael Baum 		close(socket_fd);
19085d9252eSMichael Baum 		return -1;
19185d9252eSMichael Baum 	}
19285d9252eSMichael Baum 
19385d9252eSMichael Baum 	msgh.msg_iov = &iov;
19485d9252eSMichael Baum 	msgh.msg_iovlen = 1;
19585d9252eSMichael Baum 	msgh.msg_control = control.buf;
19685d9252eSMichael Baum 	msgh.msg_controllen = sizeof(control.buf);
19785d9252eSMichael Baum 	do {
19885d9252eSMichael Baum 		ret = recvmsg(socket_fd, &msgh, 0);
19985d9252eSMichael Baum 	} while (ret < 0);
20085d9252eSMichael Baum 	if (ret != sizeof(int) || (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
20185d9252eSMichael Baum 		TESTPMD_LOG(ERR, "truncated msg");
20285d9252eSMichael Baum 		close(socket_fd);
20385d9252eSMichael Baum 		return -1;
20485d9252eSMichael Baum 	}
20585d9252eSMichael Baum 
20685d9252eSMichael Baum 	/* Translate the FD. */
20785d9252eSMichael Baum 	cmsg = CMSG_FIRSTHDR(&msgh);
20885d9252eSMichael Baum 	if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
20985d9252eSMichael Baum 	    cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
21085d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Fail to get FD using SCM_RIGHTS mechanism\n");
21185d9252eSMichael Baum 		close(socket_fd);
21285d9252eSMichael Baum 		unlink(un.sun_path);
21385d9252eSMichael Baum 		return -1;
21485d9252eSMichael Baum 	}
21585d9252eSMichael Baum 	memcpy(&cmd_fd, CMSG_DATA(cmsg), sizeof(int));
21685d9252eSMichael Baum 
21785d9252eSMichael Baum 	TESTPMD_LOG(DEBUG, "Command FD (%d) and PD handle (%d) "
21885d9252eSMichael Baum 		    "are successfully imported from remote process\n",
21985d9252eSMichael Baum 		    cmd_fd, pd_handle);
22085d9252eSMichael Baum 
22185d9252eSMichael Baum 	/* Cleanup IPC channel. */
22285d9252eSMichael Baum 	close(socket_fd);
22385d9252eSMichael Baum 
22485d9252eSMichael Baum 	/* Calculate the new length of devargs string. */
22585d9252eSMichael Baum 	len += snprintf(NULL, 0, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
22685d9252eSMichael Baum 	/* Extend the devargs string. */
22785d9252eSMichael Baum 	snprintf(extend, len, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
22885d9252eSMichael Baum 
22985d9252eSMichael Baum 	TESTPMD_LOG(DEBUG, "Attach port with extra devargs %s\n", identifier);
23085d9252eSMichael Baum 	return 0;
23185d9252eSMichael Baum }
23285d9252eSMichael Baum 
23385d9252eSMichael Baum static bool
23485d9252eSMichael Baum is_delimiter_path_spaces(char *extend)
23585d9252eSMichael Baum {
23685d9252eSMichael Baum 	while (*extend != '\0') {
23785d9252eSMichael Baum 		if (*extend != ' ')
23885d9252eSMichael Baum 			return true;
23985d9252eSMichael Baum 		extend++;
24085d9252eSMichael Baum 	}
24185d9252eSMichael Baum 	return false;
24285d9252eSMichael Baum }
24385d9252eSMichael Baum 
24485d9252eSMichael Baum /*
24585d9252eSMichael Baum  * Extend devargs list with "cmd_fd" and "pd_handle" coming from external
24685d9252eSMichael Baum  * process. It happens only in this format:
24785d9252eSMichael Baum  *  testpmd> mlx5 port attach (identifier) socket=<socket path>
24885d9252eSMichael Baum  * all "(identifier) socket=<socket path>" is in the same string pointed
24985d9252eSMichael Baum  * by the input parameter 'identifier'.
25085d9252eSMichael Baum  *
25185d9252eSMichael Baum  * @param identifier
25285d9252eSMichael Baum  *   Identifier of port attach command line.
25385d9252eSMichael Baum  */
25485d9252eSMichael Baum static void
25585d9252eSMichael Baum mlx5_test_attach_port_extend_devargs(char *identifier)
25685d9252eSMichael Baum {
25785d9252eSMichael Baum 	char *extend;
25885d9252eSMichael Baum 
25985d9252eSMichael Baum 	if (identifier == NULL) {
26085d9252eSMichael Baum 		fprintf(stderr, "Invalid parameters are specified\n");
26185d9252eSMichael Baum 		return;
26285d9252eSMichael Baum 	}
26385d9252eSMichael Baum 
26485d9252eSMichael Baum 	extend = strchr(identifier, ' ');
26585d9252eSMichael Baum 	if (extend != NULL && is_delimiter_path_spaces(extend) &&
26685d9252eSMichael Baum 	    mlx5_test_extend_devargs(identifier, extend) < 0) {
26785d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to extend devargs for port %s\n",
26885d9252eSMichael Baum 			    identifier);
26985d9252eSMichael Baum 		return;
27085d9252eSMichael Baum 	}
27185d9252eSMichael Baum 
27285d9252eSMichael Baum 	attach_port(identifier);
27385d9252eSMichael Baum }
27485d9252eSMichael Baum #endif
27585d9252eSMichael Baum 
276f41a5092SSpike Du /* *** SET HOST_SHAPER FOR A PORT *** */
277f41a5092SSpike Du struct cmd_port_host_shaper_result {
278f41a5092SSpike Du 	cmdline_fixed_string_t mlx5;
279f41a5092SSpike Du 	cmdline_fixed_string_t set;
280f41a5092SSpike Du 	cmdline_fixed_string_t port;
281f41a5092SSpike Du 	uint16_t port_num;
282f41a5092SSpike Du 	cmdline_fixed_string_t host_shaper;
283f41a5092SSpike Du 	cmdline_fixed_string_t avail_thresh_triggered;
284f41a5092SSpike Du 	uint16_t fr;
285f41a5092SSpike Du 	cmdline_fixed_string_t rate;
286f41a5092SSpike Du 	uint8_t rate_num;
287f41a5092SSpike Du };
288f41a5092SSpike Du 
289f41a5092SSpike Du static void cmd_port_host_shaper_parsed(void *parsed_result,
290f41a5092SSpike Du 		__rte_unused struct cmdline *cl,
291f41a5092SSpike Du 		__rte_unused void *data)
292f41a5092SSpike Du {
293f41a5092SSpike Du 	struct cmd_port_host_shaper_result *res = parsed_result;
294f41a5092SSpike Du 	int ret = 0;
295f41a5092SSpike Du 
296f41a5092SSpike Du 	if ((strcmp(res->mlx5, "mlx5") == 0) &&
297f41a5092SSpike Du 	    (strcmp(res->set, "set") == 0) &&
298f41a5092SSpike Du 	    (strcmp(res->port, "port") == 0) &&
299f41a5092SSpike Du 	    (strcmp(res->host_shaper, "host_shaper") == 0) &&
300f41a5092SSpike Du 	    (strcmp(res->avail_thresh_triggered, "avail_thresh_triggered") == 0) &&
301f41a5092SSpike Du 	    (strcmp(res->rate, "rate") == 0))
302f41a5092SSpike Du 		ret = mlx5_test_set_port_host_shaper(res->port_num, res->fr,
303f41a5092SSpike Du 					   res->rate_num);
304f41a5092SSpike Du 	if (ret < 0)
305f41a5092SSpike Du 		printf("cmd_port_host_shaper error: (%s)\n", strerror(-ret));
306f41a5092SSpike Du }
307f41a5092SSpike Du 
308f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_mlx5 =
309f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
310f41a5092SSpike Du 				mlx5, "mlx5");
311f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_set =
312f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
313f41a5092SSpike Du 				set, "set");
314f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_port =
315f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
316f41a5092SSpike Du 				port, "port");
317f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_portnum =
318f41a5092SSpike Du 	TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
319f41a5092SSpike Du 				port_num, RTE_UINT16);
320f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_host_shaper =
321f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
322f41a5092SSpike Du 				 host_shaper, "host_shaper");
323f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_avail_thresh_triggered =
324f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
325f41a5092SSpike Du 				 avail_thresh_triggered, "avail_thresh_triggered");
326f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_fr =
327f41a5092SSpike Du 	TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
328f41a5092SSpike Du 			      fr, RTE_UINT16);
329f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_rate =
330f41a5092SSpike Du 	TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result,
331f41a5092SSpike Du 				 rate, "rate");
332f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_rate_num =
333f41a5092SSpike Du 	TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result,
334f41a5092SSpike Du 			      rate_num, RTE_UINT8);
335f41a5092SSpike Du static cmdline_parse_inst_t mlx5_test_cmd_port_host_shaper = {
336f41a5092SSpike Du 	.f = cmd_port_host_shaper_parsed,
337f41a5092SSpike Du 	.data = (void *)0,
338f41a5092SSpike Du 	.help_str = "mlx5 set port <port_id> host_shaper avail_thresh_triggered <0|1> "
339f41a5092SSpike Du 	"rate <rate_num>: Set HOST_SHAPER avail_thresh_triggered and rate with port_id",
340f41a5092SSpike Du 	.tokens = {
341f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_mlx5,
342f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_set,
343f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_port,
344f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_portnum,
345f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_host_shaper,
346f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_avail_thresh_triggered,
347f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_fr,
348f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_rate,
349f41a5092SSpike Du 		(void *)&cmd_port_host_shaper_rate_num,
350f41a5092SSpike Du 		NULL,
351f41a5092SSpike Du 	}
352f41a5092SSpike Du };
353f41a5092SSpike Du 
35485d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
35585d9252eSMichael Baum /* *** attach a specified port *** */
35685d9252eSMichael Baum struct mlx5_cmd_operate_attach_port_result {
35785d9252eSMichael Baum 	cmdline_fixed_string_t mlx5;
35885d9252eSMichael Baum 	cmdline_fixed_string_t port;
35985d9252eSMichael Baum 	cmdline_fixed_string_t keyword;
36085d9252eSMichael Baum 	cmdline_multi_string_t identifier;
36185d9252eSMichael Baum };
36285d9252eSMichael Baum 
36385d9252eSMichael Baum static void mlx5_cmd_operate_attach_port_parsed(void *parsed_result,
36485d9252eSMichael Baum 						__rte_unused struct cmdline *cl,
36585d9252eSMichael Baum 						__rte_unused void *data)
36685d9252eSMichael Baum {
36785d9252eSMichael Baum 	struct mlx5_cmd_operate_attach_port_result *res = parsed_result;
36885d9252eSMichael Baum 
36985d9252eSMichael Baum 	if (!strcmp(res->keyword, "attach"))
37085d9252eSMichael Baum 		mlx5_test_attach_port_extend_devargs(res->identifier);
37185d9252eSMichael Baum 	else
37285d9252eSMichael Baum 		fprintf(stderr, "Unknown parameter\n");
37385d9252eSMichael Baum }
37485d9252eSMichael Baum 
37585d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_mlx5 =
37685d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
37785d9252eSMichael Baum 				 mlx5, "mlx5");
37885d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_port =
37985d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
38085d9252eSMichael Baum 				 port, "port");
38185d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_keyword =
38285d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
38385d9252eSMichael Baum 				 keyword, "attach");
38485d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_identifier =
38585d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
38685d9252eSMichael Baum 				 identifier, TOKEN_STRING_MULTI);
38785d9252eSMichael Baum 
38885d9252eSMichael Baum static cmdline_parse_inst_t mlx5_cmd_operate_attach_port = {
38985d9252eSMichael Baum 	.f = mlx5_cmd_operate_attach_port_parsed,
39085d9252eSMichael Baum 	.data = NULL,
39185d9252eSMichael Baum 	.help_str = "mlx5 port attach <identifier> socket=<path>: "
39285d9252eSMichael Baum 		"(identifier: pci address or virtual dev name"
39385d9252eSMichael Baum 		", path (optional): socket path to get cmd FD and PD handle)",
39485d9252eSMichael Baum 	.tokens = {
39585d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_mlx5,
39685d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_port,
39785d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_keyword,
39885d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_identifier,
39985d9252eSMichael Baum 		NULL,
40085d9252eSMichael Baum 	},
40185d9252eSMichael Baum };
40285d9252eSMichael Baum #endif
40385d9252eSMichael Baum 
404*740a2836SMichael Baum /* Map HW queue index to rte queue index. */
405*740a2836SMichael Baum struct mlx5_cmd_map_ext_rxq {
406*740a2836SMichael Baum 	cmdline_fixed_string_t mlx5;
407*740a2836SMichael Baum 	cmdline_fixed_string_t port;
408*740a2836SMichael Baum 	portid_t port_id;
409*740a2836SMichael Baum 	cmdline_fixed_string_t ext_rxq;
410*740a2836SMichael Baum 	cmdline_fixed_string_t map;
411*740a2836SMichael Baum 	uint16_t sw_queue_id;
412*740a2836SMichael Baum 	uint32_t hw_queue_id;
413*740a2836SMichael Baum };
414*740a2836SMichael Baum 
415*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_mlx5 =
416*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, mlx5, "mlx5");
417*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_port =
418*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port, "port");
419*740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_port_id =
420*740a2836SMichael Baum 	TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port_id, RTE_UINT16);
421*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_ext_rxq =
422*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, ext_rxq,
423*740a2836SMichael Baum 				 "ext_rxq");
424*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_map =
425*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, map, "map");
426*740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_sw_queue_id =
427*740a2836SMichael Baum 	TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, sw_queue_id,
428*740a2836SMichael Baum 			      RTE_UINT16);
429*740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_hw_queue_id =
430*740a2836SMichael Baum 	TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, hw_queue_id,
431*740a2836SMichael Baum 			      RTE_UINT32);
432*740a2836SMichael Baum 
433*740a2836SMichael Baum static void
434*740a2836SMichael Baum mlx5_cmd_map_ext_rxq_parsed(void *parsed_result,
435*740a2836SMichael Baum 			    __rte_unused struct cmdline *cl,
436*740a2836SMichael Baum 			    __rte_unused void *data)
437*740a2836SMichael Baum {
438*740a2836SMichael Baum 	struct mlx5_cmd_map_ext_rxq *res = parsed_result;
439*740a2836SMichael Baum 	int ret;
440*740a2836SMichael Baum 
441*740a2836SMichael Baum 	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
442*740a2836SMichael Baum 		return;
443*740a2836SMichael Baum 	ret = rte_pmd_mlx5_external_rx_queue_id_map(res->port_id,
444*740a2836SMichael Baum 						    res->sw_queue_id,
445*740a2836SMichael Baum 						    res->hw_queue_id);
446*740a2836SMichael Baum 	switch (ret) {
447*740a2836SMichael Baum 	case 0:
448*740a2836SMichael Baum 		break;
449*740a2836SMichael Baum 	case -EINVAL:
450*740a2836SMichael Baum 		fprintf(stderr, "invalid ethdev index (%u), out of range\n",
451*740a2836SMichael Baum 			res->sw_queue_id);
452*740a2836SMichael Baum 		break;
453*740a2836SMichael Baum 	case -ENODEV:
454*740a2836SMichael Baum 		fprintf(stderr, "invalid port_id %u\n", res->port_id);
455*740a2836SMichael Baum 		break;
456*740a2836SMichael Baum 	case -ENOTSUP:
457*740a2836SMichael Baum 		fprintf(stderr, "function not implemented or supported\n");
458*740a2836SMichael Baum 		break;
459*740a2836SMichael Baum 	case -EEXIST:
460*740a2836SMichael Baum 		fprintf(stderr, "mapping with index %u already exists\n",
461*740a2836SMichael Baum 			res->sw_queue_id);
462*740a2836SMichael Baum 		break;
463*740a2836SMichael Baum 	default:
464*740a2836SMichael Baum 		fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
465*740a2836SMichael Baum 	}
466*740a2836SMichael Baum }
467*740a2836SMichael Baum 
468*740a2836SMichael Baum cmdline_parse_inst_t mlx5_cmd_map_ext_rxq = {
469*740a2836SMichael Baum 	.f = mlx5_cmd_map_ext_rxq_parsed,
470*740a2836SMichael Baum 	.data = NULL,
471*740a2836SMichael Baum 	.help_str = "mlx5 port <port_id> ext_rxq map <sw_queue_id> <hw_queue_id>",
472*740a2836SMichael Baum 	.tokens = {
473*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_mlx5,
474*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_port,
475*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_port_id,
476*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_ext_rxq,
477*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_map,
478*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_sw_queue_id,
479*740a2836SMichael Baum 		(void *)&mlx5_cmd_map_ext_rxq_hw_queue_id,
480*740a2836SMichael Baum 		NULL,
481*740a2836SMichael Baum 	}
482*740a2836SMichael Baum };
483*740a2836SMichael Baum 
484*740a2836SMichael Baum /* Unmap HW queue index to rte queue index. */
485*740a2836SMichael Baum struct mlx5_cmd_unmap_ext_rxq {
486*740a2836SMichael Baum 	cmdline_fixed_string_t mlx5;
487*740a2836SMichael Baum 	cmdline_fixed_string_t port;
488*740a2836SMichael Baum 	portid_t port_id;
489*740a2836SMichael Baum 	cmdline_fixed_string_t ext_rxq;
490*740a2836SMichael Baum 	cmdline_fixed_string_t unmap;
491*740a2836SMichael Baum 	uint16_t queue_id;
492*740a2836SMichael Baum };
493*740a2836SMichael Baum 
494*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_mlx5 =
495*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, mlx5, "mlx5");
496*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_port =
497*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port, "port");
498*740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_port_id =
499*740a2836SMichael Baum 	TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port_id,
500*740a2836SMichael Baum 			      RTE_UINT16);
501*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_ext_rxq =
502*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, ext_rxq,
503*740a2836SMichael Baum 				 "ext_rxq");
504*740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_unmap =
505*740a2836SMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, unmap, "unmap");
506*740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_queue_id =
507*740a2836SMichael Baum 	TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, queue_id,
508*740a2836SMichael Baum 			      RTE_UINT16);
509*740a2836SMichael Baum 
510*740a2836SMichael Baum static void
511*740a2836SMichael Baum mlx5_cmd_unmap_ext_rxq_parsed(void *parsed_result,
512*740a2836SMichael Baum 			      __rte_unused struct cmdline *cl,
513*740a2836SMichael Baum 			      __rte_unused void *data)
514*740a2836SMichael Baum {
515*740a2836SMichael Baum 	struct mlx5_cmd_unmap_ext_rxq *res = parsed_result;
516*740a2836SMichael Baum 	int ret;
517*740a2836SMichael Baum 
518*740a2836SMichael Baum 	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
519*740a2836SMichael Baum 		return;
520*740a2836SMichael Baum 	ret = rte_pmd_mlx5_external_rx_queue_id_unmap(res->port_id,
521*740a2836SMichael Baum 						      res->queue_id);
522*740a2836SMichael Baum 	switch (ret) {
523*740a2836SMichael Baum 	case 0:
524*740a2836SMichael Baum 		break;
525*740a2836SMichael Baum 	case -EINVAL:
526*740a2836SMichael Baum 		fprintf(stderr, "invalid rte_flow index (%u), "
527*740a2836SMichael Baum 			"out of range, doesn't exist or still referenced\n",
528*740a2836SMichael Baum 			res->queue_id);
529*740a2836SMichael Baum 		break;
530*740a2836SMichael Baum 	case -ENODEV:
531*740a2836SMichael Baum 		fprintf(stderr, "invalid port_id %u\n", res->port_id);
532*740a2836SMichael Baum 		break;
533*740a2836SMichael Baum 	case -ENOTSUP:
534*740a2836SMichael Baum 		fprintf(stderr, "function not implemented or supported\n");
535*740a2836SMichael Baum 		break;
536*740a2836SMichael Baum 	default:
537*740a2836SMichael Baum 		fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
538*740a2836SMichael Baum 	}
539*740a2836SMichael Baum }
540*740a2836SMichael Baum 
541*740a2836SMichael Baum cmdline_parse_inst_t mlx5_cmd_unmap_ext_rxq = {
542*740a2836SMichael Baum 	.f = mlx5_cmd_unmap_ext_rxq_parsed,
543*740a2836SMichael Baum 	.data = NULL,
544*740a2836SMichael Baum 	.help_str = "mlx5 port <port_id> ext_rxq unmap <queue_id>",
545*740a2836SMichael Baum 	.tokens = {
546*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_mlx5,
547*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_port,
548*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_port_id,
549*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_ext_rxq,
550*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_unmap,
551*740a2836SMichael Baum 		(void *)&mlx5_cmd_unmap_ext_rxq_queue_id,
552*740a2836SMichael Baum 		NULL,
553*740a2836SMichael Baum 	}
554*740a2836SMichael Baum };
555*740a2836SMichael Baum 
556f41a5092SSpike Du static struct testpmd_driver_commands mlx5_driver_cmds = {
557f41a5092SSpike Du 	.commands = {
558f41a5092SSpike Du 		{
559f41a5092SSpike Du 			.ctx = &mlx5_test_cmd_port_host_shaper,
560f41a5092SSpike Du 			.help = "mlx5 set port (port_id) host_shaper avail_thresh_triggered (on|off)"
561f41a5092SSpike Du 				"rate (rate_num):\n"
562f41a5092SSpike Du 				"    Set HOST_SHAPER avail_thresh_triggered and rate with port_id\n\n",
563f41a5092SSpike Du 		},
56485d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
56585d9252eSMichael Baum 		{
56685d9252eSMichael Baum 			.ctx = &mlx5_cmd_operate_attach_port,
56785d9252eSMichael Baum 			.help = "mlx5 port attach (ident) socket=(path)\n"
56885d9252eSMichael Baum 				"    Attach physical or virtual dev by pci address or virtual device name "
56985d9252eSMichael Baum 				"and add \"cmd_fd\" and \"pd_handle\" devargs before attaching\n\n",
57085d9252eSMichael Baum 		},
57185d9252eSMichael Baum #endif
572f41a5092SSpike Du 		{
573*740a2836SMichael Baum 			.ctx = &mlx5_cmd_map_ext_rxq,
574*740a2836SMichael Baum 			.help = "mlx5 port (port_id) ext_rxq map (sw_queue_id) (hw_queue_id)\n"
575*740a2836SMichael Baum 				"    Map HW queue index (32-bit) to ethdev"
576*740a2836SMichael Baum 				" queue index (16-bit) for external RxQ\n\n",
577*740a2836SMichael Baum 		},
578*740a2836SMichael Baum 		{
579*740a2836SMichael Baum 			.ctx = &mlx5_cmd_unmap_ext_rxq,
580*740a2836SMichael Baum 			.help = "mlx5 port (port_id) ext_rxq unmap (sw_queue_id)\n"
581*740a2836SMichael Baum 				"    Unmap external Rx queue ethdev index mapping\n\n",
582*740a2836SMichael Baum 		},
583*740a2836SMichael Baum 		{
584f41a5092SSpike Du 			.ctx = NULL,
585f41a5092SSpike Du 		},
586f41a5092SSpike Du 	}
587f41a5092SSpike Du };
588f41a5092SSpike Du TESTPMD_ADD_DRIVER_COMMANDS(mlx5_driver_cmds);
589