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