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 */ 28*baafc81eSRongwei Liu #define PARSE_DELIMITER " \f\n\r\t\v" 29*baafc81eSRongwei Liu 30*baafc81eSRongwei Liu static int 31*baafc81eSRongwei Liu parse_uint(uint64_t *value, const char *str) 32*baafc81eSRongwei Liu { 33*baafc81eSRongwei Liu char *next = NULL; 34*baafc81eSRongwei Liu uint64_t n; 35*baafc81eSRongwei Liu 36*baafc81eSRongwei Liu errno = 0; 37*baafc81eSRongwei Liu /* Parse number string */ 38*baafc81eSRongwei Liu if (!strncasecmp(str, "0x", 2)) { 39*baafc81eSRongwei Liu str += 2; 40*baafc81eSRongwei Liu n = strtol(str, &next, 16); 41*baafc81eSRongwei Liu } else { 42*baafc81eSRongwei Liu n = strtol(str, &next, 10); 43*baafc81eSRongwei Liu } 44*baafc81eSRongwei Liu if (errno != 0 || str == next || *next != '\0') 45*baafc81eSRongwei Liu return -1; 46*baafc81eSRongwei Liu 47*baafc81eSRongwei Liu *value = n; 48*baafc81eSRongwei Liu 49*baafc81eSRongwei Liu return 0; 50*baafc81eSRongwei Liu } 51f41a5092SSpike Du 52f41a5092SSpike Du /** 53f41a5092SSpike Du * Disable the host shaper and re-arm available descriptor threshold event. 54f41a5092SSpike Du * 55f41a5092SSpike Du * @param[in] args 56f41a5092SSpike Du * uint32_t integer combining port_id and rxq_id. 57f41a5092SSpike Du */ 58f41a5092SSpike Du static void 59f41a5092SSpike Du mlx5_test_host_shaper_disable(void *args) 60f41a5092SSpike Du { 61f41a5092SSpike Du uint32_t port_rxq_id = (uint32_t)(uintptr_t)args; 62f41a5092SSpike Du uint16_t port_id = port_rxq_id & 0xffff; 63f41a5092SSpike Du uint16_t qid = (port_rxq_id >> 16) & 0xffff; 64f41a5092SSpike Du struct rte_eth_rxq_info qinfo; 650f3ba0d4SSpike Du struct rte_port *port; 66f41a5092SSpike Du 670f3ba0d4SSpike Du port = &ports[port_id]; 680f3ba0d4SSpike Du if (port->port_status != RTE_PORT_STARTED) { 690f3ba0d4SSpike Du printf("%s port_status(%d) is incorrect, stop avail_thresh " 700f3ba0d4SSpike Du "event processing.\n", 710f3ba0d4SSpike Du __func__, port->port_status); 720f3ba0d4SSpike Du return; 730f3ba0d4SSpike Du } 74f41a5092SSpike Du printf("%s disable shaper\n", __func__); 75f41a5092SSpike Du if (rte_eth_rx_queue_info_get(port_id, qid, &qinfo)) { 76f41a5092SSpike Du printf("rx_queue_info_get returns error\n"); 77f41a5092SSpike Du return; 78f41a5092SSpike Du } 79f41a5092SSpike Du /* Rearm the available descriptor threshold event. */ 80f41a5092SSpike Du if (rte_eth_rx_avail_thresh_set(port_id, qid, qinfo.avail_thresh)) { 81f41a5092SSpike Du printf("config avail_thresh returns error\n"); 82f41a5092SSpike Du return; 83f41a5092SSpike Du } 84f41a5092SSpike Du /* Only disable the shaper when avail_thresh_triggered is set. */ 85f41a5092SSpike Du if (host_shaper_avail_thresh_triggered[port_id] && 86f41a5092SSpike Du rte_pmd_mlx5_host_shaper_config(port_id, 0, 0)) 87f41a5092SSpike Du printf("%s disable shaper returns error\n", __func__); 88f41a5092SSpike Du } 89f41a5092SSpike Du 90f41a5092SSpike Du void 91f41a5092SSpike Du mlx5_test_avail_thresh_event_handler(uint16_t port_id, uint16_t rxq_id) 92f41a5092SSpike Du { 93f41a5092SSpike Du struct rte_eth_dev_info dev_info; 94f41a5092SSpike Du uint32_t port_rxq_id = port_id | (rxq_id << 16); 95f41a5092SSpike Du 96f41a5092SSpike Du /* Ensure it's MLX5 port. */ 97f41a5092SSpike Du if (rte_eth_dev_info_get(port_id, &dev_info) != 0 || 98f41a5092SSpike Du (strncmp(dev_info.driver_name, "mlx5", 4) != 0)) 99f41a5092SSpike Du return; 100f41a5092SSpike Du rte_eal_alarm_set(SHAPER_DISABLE_DELAY_US, 101f41a5092SSpike Du mlx5_test_host_shaper_disable, 102f41a5092SSpike Du (void *)(uintptr_t)port_rxq_id); 103f41a5092SSpike Du printf("%s port_id:%u rxq_id:%u\n", __func__, port_id, rxq_id); 104f41a5092SSpike Du } 105f41a5092SSpike Du 106f41a5092SSpike Du /** 107f41a5092SSpike Du * Configure host shaper's avail_thresh_triggered and current rate. 108f41a5092SSpike Du * 109f41a5092SSpike Du * @param[in] avail_thresh_triggered 110f41a5092SSpike Du * Disable/enable avail_thresh_triggered. 111f41a5092SSpike Du * @param[in] rate 112f41a5092SSpike Du * Configure current host shaper rate. 113f41a5092SSpike Du * @return 114f41a5092SSpike Du * On success, returns 0. 115f41a5092SSpike Du * On failure, returns < 0. 116f41a5092SSpike Du */ 117f41a5092SSpike Du static int 118f41a5092SSpike Du mlx5_test_set_port_host_shaper(uint16_t port_id, uint16_t avail_thresh_triggered, uint8_t rate) 119f41a5092SSpike Du { 120f41a5092SSpike Du struct rte_eth_link link; 121f41a5092SSpike Du bool port_id_valid = false; 122f41a5092SSpike Du uint16_t pid; 123f41a5092SSpike Du int ret; 124f41a5092SSpike Du 125f41a5092SSpike Du RTE_ETH_FOREACH_DEV(pid) 126f41a5092SSpike Du if (port_id == pid) { 127f41a5092SSpike Du port_id_valid = true; 128f41a5092SSpike Du break; 129f41a5092SSpike Du } 130f41a5092SSpike Du if (!port_id_valid) 131f41a5092SSpike Du return -EINVAL; 132f41a5092SSpike Du ret = rte_eth_link_get_nowait(port_id, &link); 133f41a5092SSpike Du if (ret < 0) 134f41a5092SSpike Du return ret; 135f41a5092SSpike Du host_shaper_avail_thresh_triggered[port_id] = avail_thresh_triggered ? 1 : 0; 136f41a5092SSpike Du if (!avail_thresh_triggered) { 137f41a5092SSpike Du ret = rte_pmd_mlx5_host_shaper_config(port_id, 0, 138f41a5092SSpike Du RTE_BIT32(MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED)); 139f41a5092SSpike Du } else { 140f41a5092SSpike Du ret = rte_pmd_mlx5_host_shaper_config(port_id, 1, 141f41a5092SSpike Du RTE_BIT32(MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED)); 142f41a5092SSpike Du } 143f41a5092SSpike Du if (ret) 144f41a5092SSpike Du return ret; 145f41a5092SSpike Du ret = rte_pmd_mlx5_host_shaper_config(port_id, rate, 0); 146f41a5092SSpike Du if (ret) 147f41a5092SSpike Du return ret; 148f41a5092SSpike Du return 0; 149f41a5092SSpike Du } 150f41a5092SSpike Du 15185d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS 15285d9252eSMichael Baum static const char* 15385d9252eSMichael Baum mlx5_test_get_socket_path(char *extend) 15485d9252eSMichael Baum { 15585d9252eSMichael Baum if (strstr(extend, "socket=") == extend) { 15685d9252eSMichael Baum const char *socket_path = strchr(extend, '=') + 1; 15785d9252eSMichael Baum 15885d9252eSMichael Baum TESTPMD_LOG(DEBUG, "MLX5 socket path is %s\n", socket_path); 15985d9252eSMichael Baum return socket_path; 16085d9252eSMichael Baum } 16185d9252eSMichael Baum 16285d9252eSMichael Baum TESTPMD_LOG(ERR, "Failed to extract a valid socket path from %s\n", 16385d9252eSMichael Baum extend); 16485d9252eSMichael Baum return NULL; 16585d9252eSMichael Baum } 16685d9252eSMichael Baum 16785d9252eSMichael Baum static int 16885d9252eSMichael Baum mlx5_test_extend_devargs(char *identifier, char *extend) 16985d9252eSMichael Baum { 17085d9252eSMichael Baum struct sockaddr_un un = { 17185d9252eSMichael Baum .sun_family = AF_UNIX, 17285d9252eSMichael Baum }; 17385d9252eSMichael Baum int cmd_fd; 17485d9252eSMichael Baum int pd_handle; 17585d9252eSMichael Baum struct iovec iov = { 17685d9252eSMichael Baum .iov_base = &pd_handle, 17785d9252eSMichael Baum .iov_len = sizeof(int), 17885d9252eSMichael Baum }; 17985d9252eSMichael Baum union { 18085d9252eSMichael Baum char buf[CMSG_SPACE(sizeof(int))]; 18185d9252eSMichael Baum struct cmsghdr align; 18285d9252eSMichael Baum } control; 18385d9252eSMichael Baum struct msghdr msgh = { 18485d9252eSMichael Baum .msg_iov = NULL, 18585d9252eSMichael Baum .msg_iovlen = 0, 18685d9252eSMichael Baum }; 18785d9252eSMichael Baum struct cmsghdr *cmsg; 18885d9252eSMichael Baum const char *path = mlx5_test_get_socket_path(extend + 1); 18985d9252eSMichael Baum size_t len = 1; 19085d9252eSMichael Baum int socket_fd; 19185d9252eSMichael Baum int ret; 19285d9252eSMichael Baum 19385d9252eSMichael Baum if (path == NULL) { 19485d9252eSMichael Baum TESTPMD_LOG(ERR, "Invalid devargs extension is specified\n"); 19585d9252eSMichael Baum return -1; 19685d9252eSMichael Baum } 19785d9252eSMichael Baum 19885d9252eSMichael Baum /* Initialize IPC channel. */ 19985d9252eSMichael Baum socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 20085d9252eSMichael Baum if (socket_fd < 0) { 20185d9252eSMichael Baum TESTPMD_LOG(ERR, "Failed to create unix socket: %s\n", 20285d9252eSMichael Baum strerror(errno)); 20385d9252eSMichael Baum return -1; 20485d9252eSMichael Baum } 20585d9252eSMichael Baum rte_strlcpy(un.sun_path, path, sizeof(un.sun_path)); 20685d9252eSMichael Baum if (connect(socket_fd, (struct sockaddr *)&un, sizeof(un)) < 0) { 20785d9252eSMichael Baum TESTPMD_LOG(ERR, "Failed to connect %s: %s\n", un.sun_path, 20885d9252eSMichael Baum strerror(errno)); 20985d9252eSMichael Baum close(socket_fd); 21085d9252eSMichael Baum return -1; 21185d9252eSMichael Baum } 21285d9252eSMichael Baum 21385d9252eSMichael Baum /* Send the request message. */ 21485d9252eSMichael Baum do { 21585d9252eSMichael Baum ret = sendmsg(socket_fd, &msgh, 0); 21685d9252eSMichael Baum } while (ret < 0 && errno == EINTR); 21785d9252eSMichael Baum if (ret < 0) { 21885d9252eSMichael Baum TESTPMD_LOG(ERR, "Failed to send request to (%s): %s\n", path, 21985d9252eSMichael Baum strerror(errno)); 22085d9252eSMichael Baum close(socket_fd); 22185d9252eSMichael Baum return -1; 22285d9252eSMichael Baum } 22385d9252eSMichael Baum 22485d9252eSMichael Baum msgh.msg_iov = &iov; 22585d9252eSMichael Baum msgh.msg_iovlen = 1; 22685d9252eSMichael Baum msgh.msg_control = control.buf; 22785d9252eSMichael Baum msgh.msg_controllen = sizeof(control.buf); 22885d9252eSMichael Baum do { 22985d9252eSMichael Baum ret = recvmsg(socket_fd, &msgh, 0); 23085d9252eSMichael Baum } while (ret < 0); 23185d9252eSMichael Baum if (ret != sizeof(int) || (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { 23285d9252eSMichael Baum TESTPMD_LOG(ERR, "truncated msg"); 23385d9252eSMichael Baum close(socket_fd); 23485d9252eSMichael Baum return -1; 23585d9252eSMichael Baum } 23685d9252eSMichael Baum 23785d9252eSMichael Baum /* Translate the FD. */ 23885d9252eSMichael Baum cmsg = CMSG_FIRSTHDR(&msgh); 23985d9252eSMichael Baum if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || 24085d9252eSMichael Baum cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { 24185d9252eSMichael Baum TESTPMD_LOG(ERR, "Fail to get FD using SCM_RIGHTS mechanism\n"); 24285d9252eSMichael Baum close(socket_fd); 24385d9252eSMichael Baum unlink(un.sun_path); 24485d9252eSMichael Baum return -1; 24585d9252eSMichael Baum } 24685d9252eSMichael Baum memcpy(&cmd_fd, CMSG_DATA(cmsg), sizeof(int)); 24785d9252eSMichael Baum 24885d9252eSMichael Baum TESTPMD_LOG(DEBUG, "Command FD (%d) and PD handle (%d) " 24985d9252eSMichael Baum "are successfully imported from remote process\n", 25085d9252eSMichael Baum cmd_fd, pd_handle); 25185d9252eSMichael Baum 25285d9252eSMichael Baum /* Cleanup IPC channel. */ 25385d9252eSMichael Baum close(socket_fd); 25485d9252eSMichael Baum 25585d9252eSMichael Baum /* Calculate the new length of devargs string. */ 25685d9252eSMichael Baum len += snprintf(NULL, 0, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle); 25785d9252eSMichael Baum /* Extend the devargs string. */ 25885d9252eSMichael Baum snprintf(extend, len, ",cmd_fd=%d,pd_handle=%d", cmd_fd, pd_handle); 25985d9252eSMichael Baum 26085d9252eSMichael Baum TESTPMD_LOG(DEBUG, "Attach port with extra devargs %s\n", identifier); 26185d9252eSMichael Baum return 0; 26285d9252eSMichael Baum } 26385d9252eSMichael Baum 26485d9252eSMichael Baum static bool 26585d9252eSMichael Baum is_delimiter_path_spaces(char *extend) 26685d9252eSMichael Baum { 26785d9252eSMichael Baum while (*extend != '\0') { 26885d9252eSMichael Baum if (*extend != ' ') 26985d9252eSMichael Baum return true; 27085d9252eSMichael Baum extend++; 27185d9252eSMichael Baum } 27285d9252eSMichael Baum return false; 27385d9252eSMichael Baum } 27485d9252eSMichael Baum 27585d9252eSMichael Baum /* 27685d9252eSMichael Baum * Extend devargs list with "cmd_fd" and "pd_handle" coming from external 27785d9252eSMichael Baum * process. It happens only in this format: 27885d9252eSMichael Baum * testpmd> mlx5 port attach (identifier) socket=<socket path> 27985d9252eSMichael Baum * all "(identifier) socket=<socket path>" is in the same string pointed 28085d9252eSMichael Baum * by the input parameter 'identifier'. 28185d9252eSMichael Baum * 28285d9252eSMichael Baum * @param identifier 28385d9252eSMichael Baum * Identifier of port attach command line. 28485d9252eSMichael Baum */ 28585d9252eSMichael Baum static void 28685d9252eSMichael Baum mlx5_test_attach_port_extend_devargs(char *identifier) 28785d9252eSMichael Baum { 28885d9252eSMichael Baum char *extend; 28985d9252eSMichael Baum 29085d9252eSMichael Baum if (identifier == NULL) { 29185d9252eSMichael Baum fprintf(stderr, "Invalid parameters are specified\n"); 29285d9252eSMichael Baum return; 29385d9252eSMichael Baum } 29485d9252eSMichael Baum 29585d9252eSMichael Baum extend = strchr(identifier, ' '); 29685d9252eSMichael Baum if (extend != NULL && is_delimiter_path_spaces(extend) && 29785d9252eSMichael Baum mlx5_test_extend_devargs(identifier, extend) < 0) { 29885d9252eSMichael Baum TESTPMD_LOG(ERR, "Failed to extend devargs for port %s\n", 29985d9252eSMichael Baum identifier); 30085d9252eSMichael Baum return; 30185d9252eSMichael Baum } 30285d9252eSMichael Baum 30385d9252eSMichael Baum attach_port(identifier); 30485d9252eSMichael Baum } 30585d9252eSMichael Baum #endif 30685d9252eSMichael Baum 307f41a5092SSpike Du /* *** SET HOST_SHAPER FOR A PORT *** */ 308f41a5092SSpike Du struct cmd_port_host_shaper_result { 309f41a5092SSpike Du cmdline_fixed_string_t mlx5; 310f41a5092SSpike Du cmdline_fixed_string_t set; 311f41a5092SSpike Du cmdline_fixed_string_t port; 312f41a5092SSpike Du uint16_t port_num; 313f41a5092SSpike Du cmdline_fixed_string_t host_shaper; 314f41a5092SSpike Du cmdline_fixed_string_t avail_thresh_triggered; 315f41a5092SSpike Du uint16_t fr; 316f41a5092SSpike Du cmdline_fixed_string_t rate; 317f41a5092SSpike Du uint8_t rate_num; 318f41a5092SSpike Du }; 319f41a5092SSpike Du 320f41a5092SSpike Du static void cmd_port_host_shaper_parsed(void *parsed_result, 321f41a5092SSpike Du __rte_unused struct cmdline *cl, 322f41a5092SSpike Du __rte_unused void *data) 323f41a5092SSpike Du { 324f41a5092SSpike Du struct cmd_port_host_shaper_result *res = parsed_result; 325f41a5092SSpike Du int ret = 0; 326f41a5092SSpike Du 327f41a5092SSpike Du if ((strcmp(res->mlx5, "mlx5") == 0) && 328f41a5092SSpike Du (strcmp(res->set, "set") == 0) && 329f41a5092SSpike Du (strcmp(res->port, "port") == 0) && 330f41a5092SSpike Du (strcmp(res->host_shaper, "host_shaper") == 0) && 331f41a5092SSpike Du (strcmp(res->avail_thresh_triggered, "avail_thresh_triggered") == 0) && 332f41a5092SSpike Du (strcmp(res->rate, "rate") == 0)) 333f41a5092SSpike Du ret = mlx5_test_set_port_host_shaper(res->port_num, res->fr, 334f41a5092SSpike Du res->rate_num); 335f41a5092SSpike Du if (ret < 0) 336f41a5092SSpike Du printf("cmd_port_host_shaper error: (%s)\n", strerror(-ret)); 337f41a5092SSpike Du } 338f41a5092SSpike Du 339f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_mlx5 = 340f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 341f41a5092SSpike Du mlx5, "mlx5"); 342f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_set = 343f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 344f41a5092SSpike Du set, "set"); 345f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_port = 346f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 347f41a5092SSpike Du port, "port"); 348f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_portnum = 349f41a5092SSpike Du TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result, 350f41a5092SSpike Du port_num, RTE_UINT16); 351f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_host_shaper = 352f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 353f41a5092SSpike Du host_shaper, "host_shaper"); 354f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_avail_thresh_triggered = 355f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 356f41a5092SSpike Du avail_thresh_triggered, "avail_thresh_triggered"); 357f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_fr = 358f41a5092SSpike Du TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result, 359f41a5092SSpike Du fr, RTE_UINT16); 360f41a5092SSpike Du static cmdline_parse_token_string_t cmd_port_host_shaper_rate = 361f41a5092SSpike Du TOKEN_STRING_INITIALIZER(struct cmd_port_host_shaper_result, 362f41a5092SSpike Du rate, "rate"); 363f41a5092SSpike Du static cmdline_parse_token_num_t cmd_port_host_shaper_rate_num = 364f41a5092SSpike Du TOKEN_NUM_INITIALIZER(struct cmd_port_host_shaper_result, 365f41a5092SSpike Du rate_num, RTE_UINT8); 366f41a5092SSpike Du static cmdline_parse_inst_t mlx5_test_cmd_port_host_shaper = { 367f41a5092SSpike Du .f = cmd_port_host_shaper_parsed, 368f41a5092SSpike Du .data = (void *)0, 369f41a5092SSpike Du .help_str = "mlx5 set port <port_id> host_shaper avail_thresh_triggered <0|1> " 370f41a5092SSpike Du "rate <rate_num>: Set HOST_SHAPER avail_thresh_triggered and rate with port_id", 371f41a5092SSpike Du .tokens = { 372f41a5092SSpike Du (void *)&cmd_port_host_shaper_mlx5, 373f41a5092SSpike Du (void *)&cmd_port_host_shaper_set, 374f41a5092SSpike Du (void *)&cmd_port_host_shaper_port, 375f41a5092SSpike Du (void *)&cmd_port_host_shaper_portnum, 376f41a5092SSpike Du (void *)&cmd_port_host_shaper_host_shaper, 377f41a5092SSpike Du (void *)&cmd_port_host_shaper_avail_thresh_triggered, 378f41a5092SSpike Du (void *)&cmd_port_host_shaper_fr, 379f41a5092SSpike Du (void *)&cmd_port_host_shaper_rate, 380f41a5092SSpike Du (void *)&cmd_port_host_shaper_rate_num, 381f41a5092SSpike Du NULL, 382f41a5092SSpike Du } 383f41a5092SSpike Du }; 384f41a5092SSpike Du 38585d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS 38685d9252eSMichael Baum /* *** attach a specified port *** */ 38785d9252eSMichael Baum struct mlx5_cmd_operate_attach_port_result { 38885d9252eSMichael Baum cmdline_fixed_string_t mlx5; 38985d9252eSMichael Baum cmdline_fixed_string_t port; 39085d9252eSMichael Baum cmdline_fixed_string_t keyword; 39185d9252eSMichael Baum cmdline_multi_string_t identifier; 39285d9252eSMichael Baum }; 39385d9252eSMichael Baum 39485d9252eSMichael Baum static void mlx5_cmd_operate_attach_port_parsed(void *parsed_result, 39585d9252eSMichael Baum __rte_unused struct cmdline *cl, 39685d9252eSMichael Baum __rte_unused void *data) 39785d9252eSMichael Baum { 39885d9252eSMichael Baum struct mlx5_cmd_operate_attach_port_result *res = parsed_result; 39985d9252eSMichael Baum 40085d9252eSMichael Baum if (!strcmp(res->keyword, "attach")) 40185d9252eSMichael Baum mlx5_test_attach_port_extend_devargs(res->identifier); 40285d9252eSMichael Baum else 40385d9252eSMichael Baum fprintf(stderr, "Unknown parameter\n"); 40485d9252eSMichael Baum } 40585d9252eSMichael Baum 40685d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_mlx5 = 40785d9252eSMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result, 40885d9252eSMichael Baum mlx5, "mlx5"); 40985d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_port = 41085d9252eSMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result, 41185d9252eSMichael Baum port, "port"); 41285d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_keyword = 41385d9252eSMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result, 41485d9252eSMichael Baum keyword, "attach"); 41585d9252eSMichael Baum static cmdline_parse_token_string_t mlx5_cmd_operate_attach_port_identifier = 41685d9252eSMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_operate_attach_port_result, 41785d9252eSMichael Baum identifier, TOKEN_STRING_MULTI); 41885d9252eSMichael Baum 41985d9252eSMichael Baum static cmdline_parse_inst_t mlx5_cmd_operate_attach_port = { 42085d9252eSMichael Baum .f = mlx5_cmd_operate_attach_port_parsed, 42185d9252eSMichael Baum .data = NULL, 42285d9252eSMichael Baum .help_str = "mlx5 port attach <identifier> socket=<path>: " 42385d9252eSMichael Baum "(identifier: pci address or virtual dev name" 42485d9252eSMichael Baum ", path (optional): socket path to get cmd FD and PD handle)", 42585d9252eSMichael Baum .tokens = { 42685d9252eSMichael Baum (void *)&mlx5_cmd_operate_attach_port_mlx5, 42785d9252eSMichael Baum (void *)&mlx5_cmd_operate_attach_port_port, 42885d9252eSMichael Baum (void *)&mlx5_cmd_operate_attach_port_keyword, 42985d9252eSMichael Baum (void *)&mlx5_cmd_operate_attach_port_identifier, 43085d9252eSMichael Baum NULL, 43185d9252eSMichael Baum }, 43285d9252eSMichael Baum }; 43385d9252eSMichael Baum #endif 43485d9252eSMichael Baum 435740a2836SMichael Baum /* Map HW queue index to rte queue index. */ 436740a2836SMichael Baum struct mlx5_cmd_map_ext_rxq { 437740a2836SMichael Baum cmdline_fixed_string_t mlx5; 438740a2836SMichael Baum cmdline_fixed_string_t port; 439740a2836SMichael Baum portid_t port_id; 440740a2836SMichael Baum cmdline_fixed_string_t ext_rxq; 441740a2836SMichael Baum cmdline_fixed_string_t map; 442740a2836SMichael Baum uint16_t sw_queue_id; 443740a2836SMichael Baum uint32_t hw_queue_id; 444740a2836SMichael Baum }; 445740a2836SMichael Baum 446740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_mlx5 = 447740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, mlx5, "mlx5"); 448740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_port = 449740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port, "port"); 450740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_port_id = 451740a2836SMichael Baum TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, port_id, RTE_UINT16); 452740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_ext_rxq = 453740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, ext_rxq, 454740a2836SMichael Baum "ext_rxq"); 455740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_map_ext_rxq_map = 456740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_map_ext_rxq, map, "map"); 457740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_sw_queue_id = 458740a2836SMichael Baum TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, sw_queue_id, 459740a2836SMichael Baum RTE_UINT16); 460740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_map_ext_rxq_hw_queue_id = 461740a2836SMichael Baum TOKEN_NUM_INITIALIZER(struct mlx5_cmd_map_ext_rxq, hw_queue_id, 462740a2836SMichael Baum RTE_UINT32); 463740a2836SMichael Baum 464740a2836SMichael Baum static void 465740a2836SMichael Baum mlx5_cmd_map_ext_rxq_parsed(void *parsed_result, 466740a2836SMichael Baum __rte_unused struct cmdline *cl, 467740a2836SMichael Baum __rte_unused void *data) 468740a2836SMichael Baum { 469740a2836SMichael Baum struct mlx5_cmd_map_ext_rxq *res = parsed_result; 470740a2836SMichael Baum int ret; 471740a2836SMichael Baum 472740a2836SMichael Baum if (port_id_is_invalid(res->port_id, ENABLED_WARN)) 473740a2836SMichael Baum return; 474740a2836SMichael Baum ret = rte_pmd_mlx5_external_rx_queue_id_map(res->port_id, 475740a2836SMichael Baum res->sw_queue_id, 476740a2836SMichael Baum res->hw_queue_id); 477740a2836SMichael Baum switch (ret) { 478740a2836SMichael Baum case 0: 479740a2836SMichael Baum break; 480740a2836SMichael Baum case -EINVAL: 481740a2836SMichael Baum fprintf(stderr, "invalid ethdev index (%u), out of range\n", 482740a2836SMichael Baum res->sw_queue_id); 483740a2836SMichael Baum break; 484740a2836SMichael Baum case -ENODEV: 485740a2836SMichael Baum fprintf(stderr, "invalid port_id %u\n", res->port_id); 486740a2836SMichael Baum break; 487740a2836SMichael Baum case -ENOTSUP: 488740a2836SMichael Baum fprintf(stderr, "function not implemented or supported\n"); 489740a2836SMichael Baum break; 490740a2836SMichael Baum case -EEXIST: 491740a2836SMichael Baum fprintf(stderr, "mapping with index %u already exists\n", 492740a2836SMichael Baum res->sw_queue_id); 493740a2836SMichael Baum break; 494740a2836SMichael Baum default: 495740a2836SMichael Baum fprintf(stderr, "programming error: (%s)\n", strerror(-ret)); 496740a2836SMichael Baum } 497740a2836SMichael Baum } 498740a2836SMichael Baum 499740a2836SMichael Baum cmdline_parse_inst_t mlx5_cmd_map_ext_rxq = { 500740a2836SMichael Baum .f = mlx5_cmd_map_ext_rxq_parsed, 501740a2836SMichael Baum .data = NULL, 502740a2836SMichael Baum .help_str = "mlx5 port <port_id> ext_rxq map <sw_queue_id> <hw_queue_id>", 503740a2836SMichael Baum .tokens = { 504740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_mlx5, 505740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_port, 506740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_port_id, 507740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_ext_rxq, 508740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_map, 509740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_sw_queue_id, 510740a2836SMichael Baum (void *)&mlx5_cmd_map_ext_rxq_hw_queue_id, 511740a2836SMichael Baum NULL, 512740a2836SMichael Baum } 513740a2836SMichael Baum }; 514740a2836SMichael Baum 515740a2836SMichael Baum /* Unmap HW queue index to rte queue index. */ 516740a2836SMichael Baum struct mlx5_cmd_unmap_ext_rxq { 517740a2836SMichael Baum cmdline_fixed_string_t mlx5; 518740a2836SMichael Baum cmdline_fixed_string_t port; 519740a2836SMichael Baum portid_t port_id; 520740a2836SMichael Baum cmdline_fixed_string_t ext_rxq; 521740a2836SMichael Baum cmdline_fixed_string_t unmap; 522740a2836SMichael Baum uint16_t queue_id; 523740a2836SMichael Baum }; 524740a2836SMichael Baum 525740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_mlx5 = 526740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, mlx5, "mlx5"); 527740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_port = 528740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port, "port"); 529740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_port_id = 530740a2836SMichael Baum TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, port_id, 531740a2836SMichael Baum RTE_UINT16); 532740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_ext_rxq = 533740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, ext_rxq, 534740a2836SMichael Baum "ext_rxq"); 535740a2836SMichael Baum cmdline_parse_token_string_t mlx5_cmd_unmap_ext_rxq_unmap = 536740a2836SMichael Baum TOKEN_STRING_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, unmap, "unmap"); 537740a2836SMichael Baum cmdline_parse_token_num_t mlx5_cmd_unmap_ext_rxq_queue_id = 538740a2836SMichael Baum TOKEN_NUM_INITIALIZER(struct mlx5_cmd_unmap_ext_rxq, queue_id, 539740a2836SMichael Baum RTE_UINT16); 540740a2836SMichael Baum 541740a2836SMichael Baum static void 542740a2836SMichael Baum mlx5_cmd_unmap_ext_rxq_parsed(void *parsed_result, 543740a2836SMichael Baum __rte_unused struct cmdline *cl, 544740a2836SMichael Baum __rte_unused void *data) 545740a2836SMichael Baum { 546740a2836SMichael Baum struct mlx5_cmd_unmap_ext_rxq *res = parsed_result; 547740a2836SMichael Baum int ret; 548740a2836SMichael Baum 549740a2836SMichael Baum if (port_id_is_invalid(res->port_id, ENABLED_WARN)) 550740a2836SMichael Baum return; 551740a2836SMichael Baum ret = rte_pmd_mlx5_external_rx_queue_id_unmap(res->port_id, 552740a2836SMichael Baum res->queue_id); 553740a2836SMichael Baum switch (ret) { 554740a2836SMichael Baum case 0: 555740a2836SMichael Baum break; 556740a2836SMichael Baum case -EINVAL: 557740a2836SMichael Baum fprintf(stderr, "invalid rte_flow index (%u), " 558740a2836SMichael Baum "out of range, doesn't exist or still referenced\n", 559740a2836SMichael Baum res->queue_id); 560740a2836SMichael Baum break; 561740a2836SMichael Baum case -ENODEV: 562740a2836SMichael Baum fprintf(stderr, "invalid port_id %u\n", res->port_id); 563740a2836SMichael Baum break; 564740a2836SMichael Baum case -ENOTSUP: 565740a2836SMichael Baum fprintf(stderr, "function not implemented or supported\n"); 566740a2836SMichael Baum break; 567740a2836SMichael Baum default: 568740a2836SMichael Baum fprintf(stderr, "programming error: (%s)\n", strerror(-ret)); 569740a2836SMichael Baum } 570740a2836SMichael Baum } 571740a2836SMichael Baum 572740a2836SMichael Baum cmdline_parse_inst_t mlx5_cmd_unmap_ext_rxq = { 573740a2836SMichael Baum .f = mlx5_cmd_unmap_ext_rxq_parsed, 574740a2836SMichael Baum .data = NULL, 575740a2836SMichael Baum .help_str = "mlx5 port <port_id> ext_rxq unmap <queue_id>", 576740a2836SMichael Baum .tokens = { 577740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_mlx5, 578740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_port, 579740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_port_id, 580740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_ext_rxq, 581740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_unmap, 582740a2836SMichael Baum (void *)&mlx5_cmd_unmap_ext_rxq_queue_id, 583740a2836SMichael Baum NULL, 584740a2836SMichael Baum } 585740a2836SMichael Baum }; 586740a2836SMichael Baum 587*baafc81eSRongwei Liu /* Set flow engine mode with flags command. */ 588*baafc81eSRongwei Liu struct mlx5_cmd_set_flow_engine_mode { 589*baafc81eSRongwei Liu cmdline_fixed_string_t mlx5; 590*baafc81eSRongwei Liu cmdline_fixed_string_t set; 591*baafc81eSRongwei Liu cmdline_fixed_string_t flow_engine; 592*baafc81eSRongwei Liu cmdline_multi_string_t mode; 593*baafc81eSRongwei Liu }; 594*baafc81eSRongwei Liu 595*baafc81eSRongwei Liu static int 596*baafc81eSRongwei Liu parse_multi_token_flow_engine_mode(char *t_str, enum mlx5_flow_engine_mode *mode, 597*baafc81eSRongwei Liu uint32_t *flag) 598*baafc81eSRongwei Liu { 599*baafc81eSRongwei Liu uint64_t val; 600*baafc81eSRongwei Liu char *token; 601*baafc81eSRongwei Liu int ret; 602*baafc81eSRongwei Liu 603*baafc81eSRongwei Liu *flag = 0; 604*baafc81eSRongwei Liu /* First token: mode string */ 605*baafc81eSRongwei Liu token = strtok_r(t_str, PARSE_DELIMITER, &t_str); 606*baafc81eSRongwei Liu if (token == NULL) 607*baafc81eSRongwei Liu return -1; 608*baafc81eSRongwei Liu 609*baafc81eSRongwei Liu if (!strcmp(token, "active")) 610*baafc81eSRongwei Liu *mode = MLX5_FLOW_ENGINE_MODE_ACTIVE; 611*baafc81eSRongwei Liu else if (!strcmp(token, "standby")) 612*baafc81eSRongwei Liu *mode = MLX5_FLOW_ENGINE_MODE_STANDBY; 613*baafc81eSRongwei Liu else 614*baafc81eSRongwei Liu return -1; 615*baafc81eSRongwei Liu 616*baafc81eSRongwei Liu /* Second token: flag */ 617*baafc81eSRongwei Liu token = strtok_r(t_str, PARSE_DELIMITER, &t_str); 618*baafc81eSRongwei Liu if (token == NULL) 619*baafc81eSRongwei Liu return 0; 620*baafc81eSRongwei Liu 621*baafc81eSRongwei Liu ret = parse_uint(&val, token); 622*baafc81eSRongwei Liu if (ret != 0 || val > UINT32_MAX) 623*baafc81eSRongwei Liu return -1; 624*baafc81eSRongwei Liu 625*baafc81eSRongwei Liu *flag = val; 626*baafc81eSRongwei Liu return 0; 627*baafc81eSRongwei Liu } 628*baafc81eSRongwei Liu 629*baafc81eSRongwei Liu static void 630*baafc81eSRongwei Liu mlx5_cmd_set_flow_engine_mode_parsed(void *parsed_result, 631*baafc81eSRongwei Liu __rte_unused struct cmdline *cl, 632*baafc81eSRongwei Liu __rte_unused void *data) 633*baafc81eSRongwei Liu { 634*baafc81eSRongwei Liu struct mlx5_cmd_set_flow_engine_mode *res = parsed_result; 635*baafc81eSRongwei Liu enum mlx5_flow_engine_mode mode; 636*baafc81eSRongwei Liu uint32_t flag; 637*baafc81eSRongwei Liu int ret; 638*baafc81eSRongwei Liu 639*baafc81eSRongwei Liu ret = parse_multi_token_flow_engine_mode(res->mode, &mode, &flag); 640*baafc81eSRongwei Liu 641*baafc81eSRongwei Liu if (ret < 0) { 642*baafc81eSRongwei Liu fprintf(stderr, "Bad input\n"); 643*baafc81eSRongwei Liu return; 644*baafc81eSRongwei Liu } 645*baafc81eSRongwei Liu 646*baafc81eSRongwei Liu ret = rte_pmd_mlx5_flow_engine_set_mode(mode, flag); 647*baafc81eSRongwei Liu 648*baafc81eSRongwei Liu if (ret < 0) 649*baafc81eSRongwei Liu fprintf(stderr, "Fail to set flow_engine to %s mode with flag 0x%x, error %s\n", 650*baafc81eSRongwei Liu mode == MLX5_FLOW_ENGINE_MODE_ACTIVE ? "active" : "standby", flag, 651*baafc81eSRongwei Liu strerror(-ret)); 652*baafc81eSRongwei Liu else 653*baafc81eSRongwei Liu TESTPMD_LOG(DEBUG, "Set %d ports flow_engine to %s mode with flag 0x%x\n", ret, 654*baafc81eSRongwei Liu mode == MLX5_FLOW_ENGINE_MODE_ACTIVE ? "active" : "standby", flag); 655*baafc81eSRongwei Liu } 656*baafc81eSRongwei Liu 657*baafc81eSRongwei Liu cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_mlx5 = 658*baafc81eSRongwei Liu TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, mlx5, 659*baafc81eSRongwei Liu "mlx5"); 660*baafc81eSRongwei Liu cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_set = 661*baafc81eSRongwei Liu TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, set, 662*baafc81eSRongwei Liu "set"); 663*baafc81eSRongwei Liu cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_flow_engine = 664*baafc81eSRongwei Liu TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, flow_engine, 665*baafc81eSRongwei Liu "flow_engine"); 666*baafc81eSRongwei Liu cmdline_parse_token_string_t mlx5_cmd_set_flow_engine_mode_mode = 667*baafc81eSRongwei Liu TOKEN_STRING_INITIALIZER(struct mlx5_cmd_set_flow_engine_mode, mode, 668*baafc81eSRongwei Liu TOKEN_STRING_MULTI); 669*baafc81eSRongwei Liu 670*baafc81eSRongwei Liu cmdline_parse_inst_t mlx5_cmd_set_flow_engine_mode = { 671*baafc81eSRongwei Liu .f = &mlx5_cmd_set_flow_engine_mode_parsed, 672*baafc81eSRongwei Liu .data = NULL, 673*baafc81eSRongwei Liu .help_str = "mlx5 set flow_engine <active|standby> [<flag>]", 674*baafc81eSRongwei Liu .tokens = { 675*baafc81eSRongwei Liu (void *)&mlx5_cmd_set_flow_engine_mode_mlx5, 676*baafc81eSRongwei Liu (void *)&mlx5_cmd_set_flow_engine_mode_set, 677*baafc81eSRongwei Liu (void *)&mlx5_cmd_set_flow_engine_mode_flow_engine, 678*baafc81eSRongwei Liu (void *)&mlx5_cmd_set_flow_engine_mode_mode, 679*baafc81eSRongwei Liu NULL, 680*baafc81eSRongwei Liu } 681*baafc81eSRongwei Liu }; 682*baafc81eSRongwei Liu 683f41a5092SSpike Du static struct testpmd_driver_commands mlx5_driver_cmds = { 684f41a5092SSpike Du .commands = { 685f41a5092SSpike Du { 686f41a5092SSpike Du .ctx = &mlx5_test_cmd_port_host_shaper, 687f41a5092SSpike Du .help = "mlx5 set port (port_id) host_shaper avail_thresh_triggered (on|off)" 688f41a5092SSpike Du "rate (rate_num):\n" 689f41a5092SSpike Du " Set HOST_SHAPER avail_thresh_triggered and rate with port_id\n\n", 690f41a5092SSpike Du }, 69185d9252eSMichael Baum #ifndef RTE_EXEC_ENV_WINDOWS 69285d9252eSMichael Baum { 69385d9252eSMichael Baum .ctx = &mlx5_cmd_operate_attach_port, 69485d9252eSMichael Baum .help = "mlx5 port attach (ident) socket=(path)\n" 69585d9252eSMichael Baum " Attach physical or virtual dev by pci address or virtual device name " 69685d9252eSMichael Baum "and add \"cmd_fd\" and \"pd_handle\" devargs before attaching\n\n", 69785d9252eSMichael Baum }, 69885d9252eSMichael Baum #endif 699f41a5092SSpike Du { 700740a2836SMichael Baum .ctx = &mlx5_cmd_map_ext_rxq, 701740a2836SMichael Baum .help = "mlx5 port (port_id) ext_rxq map (sw_queue_id) (hw_queue_id)\n" 702740a2836SMichael Baum " Map HW queue index (32-bit) to ethdev" 703740a2836SMichael Baum " queue index (16-bit) for external RxQ\n\n", 704740a2836SMichael Baum }, 705740a2836SMichael Baum { 706740a2836SMichael Baum .ctx = &mlx5_cmd_unmap_ext_rxq, 707740a2836SMichael Baum .help = "mlx5 port (port_id) ext_rxq unmap (sw_queue_id)\n" 708740a2836SMichael Baum " Unmap external Rx queue ethdev index mapping\n\n", 709740a2836SMichael Baum }, 710740a2836SMichael Baum { 711*baafc81eSRongwei Liu .ctx = &mlx5_cmd_set_flow_engine_mode, 712*baafc81eSRongwei Liu .help = "mlx5 set flow_engine (active|standby) [(flag)]\n" 713*baafc81eSRongwei Liu " Set flow_engine to the specific mode with flag.\n\n" 714*baafc81eSRongwei Liu }, 715*baafc81eSRongwei Liu { 716f41a5092SSpike Du .ctx = NULL, 717f41a5092SSpike Du }, 718f41a5092SSpike Du } 719f41a5092SSpike Du }; 720f41a5092SSpike Du TESTPMD_ADD_DRIVER_COMMANDS(mlx5_driver_cmds); 721