xref: /dpdk/drivers/net/mlx5/mlx5_testpmd.c (revision 85d9252e55f2a0cec836c2334ecc32ecf999c52a)
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>
9*85d9252eSMichael Baum #include <unistd.h>
10*85d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
11*85d9252eSMichael Baum #include <sys/socket.h>
12*85d9252eSMichael Baum #include <sys/un.h>
13*85d9252eSMichael 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>
22*85d9252eSMichael 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 
120*85d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
121*85d9252eSMichael Baum static const char*
122*85d9252eSMichael Baum mlx5_test_get_socket_path(char *extend)
123*85d9252eSMichael Baum {
124*85d9252eSMichael Baum 	if (strstr(extend, "socket=") == extend) {
125*85d9252eSMichael Baum 		const char *socket_path = strchr(extend, '=') + 1;
126*85d9252eSMichael Baum 
127*85d9252eSMichael Baum 		TESTPMD_LOG(DEBUG, "MLX5 socket path is %s\n", socket_path);
128*85d9252eSMichael Baum 		return socket_path;
129*85d9252eSMichael Baum 	}
130*85d9252eSMichael Baum 
131*85d9252eSMichael Baum 	TESTPMD_LOG(ERR, "Failed to extract a valid socket path from %s\n",
132*85d9252eSMichael Baum 		    extend);
133*85d9252eSMichael Baum 	return NULL;
134*85d9252eSMichael Baum }
135*85d9252eSMichael Baum 
136*85d9252eSMichael Baum static int
137*85d9252eSMichael Baum mlx5_test_extend_devargs(char *identifier, char *extend)
138*85d9252eSMichael Baum {
139*85d9252eSMichael Baum 	struct sockaddr_un un = {
140*85d9252eSMichael Baum 		.sun_family = AF_UNIX,
141*85d9252eSMichael Baum 	};
142*85d9252eSMichael Baum 	int cmd_fd;
143*85d9252eSMichael Baum 	int pd_handle;
144*85d9252eSMichael Baum 	struct iovec iov = {
145*85d9252eSMichael Baum 		.iov_base = &pd_handle,
146*85d9252eSMichael Baum 		.iov_len = sizeof(int),
147*85d9252eSMichael Baum 	};
148*85d9252eSMichael Baum 	union {
149*85d9252eSMichael Baum 		char buf[CMSG_SPACE(sizeof(int))];
150*85d9252eSMichael Baum 		struct cmsghdr align;
151*85d9252eSMichael Baum 	} control;
152*85d9252eSMichael Baum 	struct msghdr msgh = {
153*85d9252eSMichael Baum 		.msg_iov = NULL,
154*85d9252eSMichael Baum 		.msg_iovlen = 0,
155*85d9252eSMichael Baum 	};
156*85d9252eSMichael Baum 	struct cmsghdr *cmsg;
157*85d9252eSMichael Baum 	const char *path = mlx5_test_get_socket_path(extend + 1);
158*85d9252eSMichael Baum 	size_t len = 1;
159*85d9252eSMichael Baum 	int socket_fd;
160*85d9252eSMichael Baum 	int ret;
161*85d9252eSMichael Baum 
162*85d9252eSMichael Baum 	if (path == NULL) {
163*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Invalid devargs extension is specified\n");
164*85d9252eSMichael Baum 		return -1;
165*85d9252eSMichael Baum 	}
166*85d9252eSMichael Baum 
167*85d9252eSMichael Baum 	/* Initialize IPC channel. */
168*85d9252eSMichael Baum 	socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
169*85d9252eSMichael Baum 	if (socket_fd < 0) {
170*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to create unix socket: %s\n",
171*85d9252eSMichael Baum 			    strerror(errno));
172*85d9252eSMichael Baum 		return -1;
173*85d9252eSMichael Baum 	}
174*85d9252eSMichael Baum 	rte_strlcpy(un.sun_path, path, sizeof(un.sun_path));
175*85d9252eSMichael Baum 	if (connect(socket_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
176*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to connect %s: %s\n", un.sun_path,
177*85d9252eSMichael Baum 			    strerror(errno));
178*85d9252eSMichael Baum 		close(socket_fd);
179*85d9252eSMichael Baum 		return -1;
180*85d9252eSMichael Baum 	}
181*85d9252eSMichael Baum 
182*85d9252eSMichael Baum 	/* Send the request message. */
183*85d9252eSMichael Baum 	do {
184*85d9252eSMichael Baum 		ret = sendmsg(socket_fd, &msgh, 0);
185*85d9252eSMichael Baum 	} while (ret < 0 && errno == EINTR);
186*85d9252eSMichael Baum 	if (ret < 0) {
187*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to send request to (%s): %s\n", path,
188*85d9252eSMichael Baum 			    strerror(errno));
189*85d9252eSMichael Baum 		close(socket_fd);
190*85d9252eSMichael Baum 		return -1;
191*85d9252eSMichael Baum 	}
192*85d9252eSMichael Baum 
193*85d9252eSMichael Baum 	msgh.msg_iov = &iov;
194*85d9252eSMichael Baum 	msgh.msg_iovlen = 1;
195*85d9252eSMichael Baum 	msgh.msg_control = control.buf;
196*85d9252eSMichael Baum 	msgh.msg_controllen = sizeof(control.buf);
197*85d9252eSMichael Baum 	do {
198*85d9252eSMichael Baum 		ret = recvmsg(socket_fd, &msgh, 0);
199*85d9252eSMichael Baum 	} while (ret < 0);
200*85d9252eSMichael Baum 	if (ret != sizeof(int) || (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
201*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "truncated msg");
202*85d9252eSMichael Baum 		close(socket_fd);
203*85d9252eSMichael Baum 		return -1;
204*85d9252eSMichael Baum 	}
205*85d9252eSMichael Baum 
206*85d9252eSMichael Baum 	/* Translate the FD. */
207*85d9252eSMichael Baum 	cmsg = CMSG_FIRSTHDR(&msgh);
208*85d9252eSMichael Baum 	if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
209*85d9252eSMichael Baum 	    cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
210*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Fail to get FD using SCM_RIGHTS mechanism\n");
211*85d9252eSMichael Baum 		close(socket_fd);
212*85d9252eSMichael Baum 		unlink(un.sun_path);
213*85d9252eSMichael Baum 		return -1;
214*85d9252eSMichael Baum 	}
215*85d9252eSMichael Baum 	memcpy(&cmd_fd, CMSG_DATA(cmsg), sizeof(int));
216*85d9252eSMichael Baum 
217*85d9252eSMichael Baum 	TESTPMD_LOG(DEBUG, "Command FD (%d) and PD handle (%d) "
218*85d9252eSMichael Baum 		    "are successfully imported from remote process\n",
219*85d9252eSMichael Baum 		    cmd_fd, pd_handle);
220*85d9252eSMichael Baum 
221*85d9252eSMichael Baum 	/* Cleanup IPC channel. */
222*85d9252eSMichael Baum 	close(socket_fd);
223*85d9252eSMichael Baum 
224*85d9252eSMichael Baum 	/* Calculate the new length of devargs string. */
225*85d9252eSMichael Baum 	len += snprintf(NULL, 0, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
226*85d9252eSMichael Baum 	/* Extend the devargs string. */
227*85d9252eSMichael Baum 	snprintf(extend, len, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle);
228*85d9252eSMichael Baum 
229*85d9252eSMichael Baum 	TESTPMD_LOG(DEBUG, "Attach port with extra devargs %s\n", identifier);
230*85d9252eSMichael Baum 	return 0;
231*85d9252eSMichael Baum }
232*85d9252eSMichael Baum 
233*85d9252eSMichael Baum static bool
234*85d9252eSMichael Baum is_delimiter_path_spaces(char *extend)
235*85d9252eSMichael Baum {
236*85d9252eSMichael Baum 	while (*extend != '\0') {
237*85d9252eSMichael Baum 		if (*extend != ' ')
238*85d9252eSMichael Baum 			return true;
239*85d9252eSMichael Baum 		extend++;
240*85d9252eSMichael Baum 	}
241*85d9252eSMichael Baum 	return false;
242*85d9252eSMichael Baum }
243*85d9252eSMichael Baum 
244*85d9252eSMichael Baum /*
245*85d9252eSMichael Baum  * Extend devargs list with "cmd_fd" and "pd_handle" coming from external
246*85d9252eSMichael Baum  * process. It happens only in this format:
247*85d9252eSMichael Baum  *  testpmd> mlx5 port attach (identifier) socket=<socket path>
248*85d9252eSMichael Baum  * all "(identifier) socket=<socket path>" is in the same string pointed
249*85d9252eSMichael Baum  * by the input parameter 'identifier'.
250*85d9252eSMichael Baum  *
251*85d9252eSMichael Baum  * @param identifier
252*85d9252eSMichael Baum  *   Identifier of port attach command line.
253*85d9252eSMichael Baum  */
254*85d9252eSMichael Baum static void
255*85d9252eSMichael Baum mlx5_test_attach_port_extend_devargs(char *identifier)
256*85d9252eSMichael Baum {
257*85d9252eSMichael Baum 	char *extend;
258*85d9252eSMichael Baum 
259*85d9252eSMichael Baum 	if (identifier == NULL) {
260*85d9252eSMichael Baum 		fprintf(stderr, "Invalid parameters are specified\n");
261*85d9252eSMichael Baum 		return;
262*85d9252eSMichael Baum 	}
263*85d9252eSMichael Baum 
264*85d9252eSMichael Baum 	extend = strchr(identifier, ' ');
265*85d9252eSMichael Baum 	if (extend != NULL && is_delimiter_path_spaces(extend) &&
266*85d9252eSMichael Baum 	    mlx5_test_extend_devargs(identifier, extend) < 0) {
267*85d9252eSMichael Baum 		TESTPMD_LOG(ERR, "Failed to extend devargs for port %s\n",
268*85d9252eSMichael Baum 			    identifier);
269*85d9252eSMichael Baum 		return;
270*85d9252eSMichael Baum 	}
271*85d9252eSMichael Baum 
272*85d9252eSMichael Baum 	attach_port(identifier);
273*85d9252eSMichael Baum }
274*85d9252eSMichael Baum #endif
275*85d9252eSMichael 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 
354*85d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
355*85d9252eSMichael Baum /* *** attach a specified port *** */
356*85d9252eSMichael Baum struct mlx5_cmd_operate_attach_port_result {
357*85d9252eSMichael Baum 	cmdline_fixed_string_t mlx5;
358*85d9252eSMichael Baum 	cmdline_fixed_string_t port;
359*85d9252eSMichael Baum 	cmdline_fixed_string_t keyword;
360*85d9252eSMichael Baum 	cmdline_multi_string_t identifier;
361*85d9252eSMichael Baum };
362*85d9252eSMichael Baum 
363*85d9252eSMichael Baum static void mlx5_cmd_operate_attach_port_parsed(void *parsed_result,
364*85d9252eSMichael Baum 						__rte_unused struct cmdline *cl,
365*85d9252eSMichael Baum 						__rte_unused void *data)
366*85d9252eSMichael Baum {
367*85d9252eSMichael Baum 	struct mlx5_cmd_operate_attach_port_result *res = parsed_result;
368*85d9252eSMichael Baum 
369*85d9252eSMichael Baum 	if (!strcmp(res->keyword, "attach"))
370*85d9252eSMichael Baum 		mlx5_test_attach_port_extend_devargs(res->identifier);
371*85d9252eSMichael Baum 	else
372*85d9252eSMichael Baum 		fprintf(stderr, "Unknown parameter\n");
373*85d9252eSMichael Baum }
374*85d9252eSMichael Baum 
375*85d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_mlx5 =
376*85d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
377*85d9252eSMichael Baum 				 mlx5, "mlx5");
378*85d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_port =
379*85d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
380*85d9252eSMichael Baum 				 port, "port");
381*85d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_keyword =
382*85d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
383*85d9252eSMichael Baum 				 keyword, "attach");
384*85d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_identifier =
385*85d9252eSMichael Baum 	TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result,
386*85d9252eSMichael Baum 				 identifier, TOKEN_STRING_MULTI);
387*85d9252eSMichael Baum 
388*85d9252eSMichael Baum static cmdline_parse_inst_t mlx5_cmd_operate_attach_port = {
389*85d9252eSMichael Baum 	.f = mlx5_cmd_operate_attach_port_parsed,
390*85d9252eSMichael Baum 	.data = NULL,
391*85d9252eSMichael Baum 	.help_str = "mlx5 port attach <identifier> socket=<path>: "
392*85d9252eSMichael Baum 		"(identifier: pci address or virtual dev name"
393*85d9252eSMichael Baum 		", path (optional): socket path to get cmd FD and PD handle)",
394*85d9252eSMichael Baum 	.tokens = {
395*85d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_mlx5,
396*85d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_port,
397*85d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_keyword,
398*85d9252eSMichael Baum 		(void *)&mlx5_cmd_operate_attach_port_identifier,
399*85d9252eSMichael Baum 		NULL,
400*85d9252eSMichael Baum 	},
401*85d9252eSMichael Baum };
402*85d9252eSMichael Baum #endif
403*85d9252eSMichael Baum 
404f41a5092SSpike Du static struct testpmd_driver_commands mlx5_driver_cmds = {
405f41a5092SSpike Du 	.commands = {
406f41a5092SSpike Du 		{
407f41a5092SSpike Du 			.ctx = &mlx5_test_cmd_port_host_shaper,
408f41a5092SSpike Du 			.help = "mlx5 set port (port_id) host_shaper avail_thresh_triggered (on|off)"
409f41a5092SSpike Du 				"rate (rate_num):\n"
410f41a5092SSpike Du 				"    Set HOST_SHAPER avail_thresh_triggered and rate with port_id\n\n",
411f41a5092SSpike Du 		},
412*85d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS
413*85d9252eSMichael Baum 		{
414*85d9252eSMichael Baum 			.ctx = &mlx5_cmd_operate_attach_port,
415*85d9252eSMichael Baum 			.help = "mlx5 port attach (ident) socket=(path)\n"
416*85d9252eSMichael Baum 				"    Attach physical or virtual dev by pci address or virtual device name "
417*85d9252eSMichael Baum 				"and add \"cmd_fd\" and \"pd_handle\" devargs before attaching\n\n",
418*85d9252eSMichael Baum 		},
419*85d9252eSMichael Baum #endif
420f41a5092SSpike Du 		{
421f41a5092SSpike Du 			.ctx = NULL,
422f41a5092SSpike Du 		},
423f41a5092SSpike Du 	}
424f41a5092SSpike Du };
425f41a5092SSpike Du TESTPMD_ADD_DRIVER_COMMANDS(mlx5_driver_cmds);
426