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