1f484ffa1SOphir Munk /* SPDX-License-Identifier: BSD-3-Clause 2f484ffa1SOphir Munk * Copyright 2019 Mellanox Technologies, Ltd 3f484ffa1SOphir Munk */ 4f484ffa1SOphir Munk 5f484ffa1SOphir Munk #include <sys/types.h> 6f484ffa1SOphir Munk #include <sys/socket.h> 7f484ffa1SOphir Munk #include <sys/un.h> 8f484ffa1SOphir Munk #include <fcntl.h> 9f484ffa1SOphir Munk #include <stdio.h> 10f484ffa1SOphir Munk #include <unistd.h> 11f484ffa1SOphir Munk #include <sys/stat.h> 12f484ffa1SOphir Munk 13f484ffa1SOphir Munk #include "rte_eal.h" 14f484ffa1SOphir Munk #include "mlx5_utils.h" 15f484ffa1SOphir Munk #include "mlx5.h" 16f484ffa1SOphir Munk 17f484ffa1SOphir Munk /* PMD socket service for tools. */ 18f484ffa1SOphir Munk 19733bbf51SXueming Li #define MLX5_SOCKET_PATH "/var/tmp/dpdk_net_mlx5_%d" 20733bbf51SXueming Li 21f484ffa1SOphir Munk int server_socket; /* Unix socket for primary process. */ 22f484ffa1SOphir Munk struct rte_intr_handle server_intr_handle; /* Interrupt handler. */ 23f484ffa1SOphir Munk 24f484ffa1SOphir Munk /** 25f484ffa1SOphir Munk * Handle server pmd socket interrupts. 26f484ffa1SOphir Munk */ 27f484ffa1SOphir Munk static void 28f484ffa1SOphir Munk mlx5_pmd_socket_handle(void *cb __rte_unused) 29f484ffa1SOphir Munk { 30f484ffa1SOphir Munk int conn_sock; 31f484ffa1SOphir Munk int ret; 32f484ffa1SOphir Munk struct cmsghdr *cmsg = NULL; 33f484ffa1SOphir Munk int data; 34f484ffa1SOphir Munk char buf[CMSG_SPACE(sizeof(int))] = { 0 }; 35f484ffa1SOphir Munk struct iovec io = { 36f484ffa1SOphir Munk .iov_base = &data, 37f484ffa1SOphir Munk .iov_len = sizeof(data), 38f484ffa1SOphir Munk }; 39f484ffa1SOphir Munk struct msghdr msg = { 40f484ffa1SOphir Munk .msg_iov = &io, 41f484ffa1SOphir Munk .msg_iovlen = 1, 42f484ffa1SOphir Munk .msg_control = buf, 43f484ffa1SOphir Munk .msg_controllen = sizeof(buf), 44f484ffa1SOphir Munk }; 45f484ffa1SOphir Munk uint16_t port_id; 46f484ffa1SOphir Munk int fd; 47f484ffa1SOphir Munk FILE *file = NULL; 48f484ffa1SOphir Munk struct rte_eth_dev *dev; 49f484ffa1SOphir Munk 50f484ffa1SOphir Munk /* Accept the connection from the client. */ 51f484ffa1SOphir Munk conn_sock = accept(server_socket, NULL, NULL); 52f484ffa1SOphir Munk if (conn_sock < 0) { 53f484ffa1SOphir Munk DRV_LOG(WARNING, "connection failed: %s", strerror(errno)); 54f484ffa1SOphir Munk return; 55f484ffa1SOphir Munk } 56f484ffa1SOphir Munk ret = recvmsg(conn_sock, &msg, MSG_WAITALL); 57f484ffa1SOphir Munk if (ret < 0) { 58f484ffa1SOphir Munk DRV_LOG(WARNING, "wrong message received: %s", 59f484ffa1SOphir Munk strerror(errno)); 60f484ffa1SOphir Munk goto error; 61f484ffa1SOphir Munk } 62f484ffa1SOphir Munk /* Receive file descriptor. */ 63f484ffa1SOphir Munk cmsg = CMSG_FIRSTHDR(&msg); 64f484ffa1SOphir Munk if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS || 65f484ffa1SOphir Munk cmsg->cmsg_len < sizeof(int)) { 66f484ffa1SOphir Munk DRV_LOG(WARNING, "invalid file descriptor message"); 67f484ffa1SOphir Munk goto error; 68f484ffa1SOphir Munk } 69f484ffa1SOphir Munk memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 70f484ffa1SOphir Munk file = fdopen(fd, "w"); 71f484ffa1SOphir Munk if (!file) { 72f484ffa1SOphir Munk DRV_LOG(WARNING, "Failed to open file"); 73f484ffa1SOphir Munk goto error; 74f484ffa1SOphir Munk } 75f484ffa1SOphir Munk /* Receive port number. */ 76f484ffa1SOphir Munk if (msg.msg_iovlen != 1 || msg.msg_iov->iov_len < sizeof(uint16_t)) { 77f484ffa1SOphir Munk DRV_LOG(WARNING, "wrong port number message"); 78f484ffa1SOphir Munk goto error; 79f484ffa1SOphir Munk } 80f484ffa1SOphir Munk memcpy(&port_id, msg.msg_iov->iov_base, sizeof(port_id)); 81f484ffa1SOphir Munk if (!rte_eth_dev_is_valid_port(port_id)) { 82f484ffa1SOphir Munk DRV_LOG(WARNING, "Invalid port %u", port_id); 83f484ffa1SOphir Munk goto error; 84f484ffa1SOphir Munk } 85f484ffa1SOphir Munk /* Dump flow. */ 86f484ffa1SOphir Munk dev = &rte_eth_devices[port_id]; 87*50c38379SHaifei Luo ret = mlx5_flow_dev_dump(dev, NULL, file, NULL); 88f484ffa1SOphir Munk /* Set-up the ancillary data and reply. */ 89f484ffa1SOphir Munk msg.msg_controllen = 0; 90f484ffa1SOphir Munk msg.msg_control = NULL; 91f484ffa1SOphir Munk msg.msg_iovlen = 1; 92f484ffa1SOphir Munk msg.msg_iov = &io; 93f484ffa1SOphir Munk data = -ret; 94f484ffa1SOphir Munk io.iov_len = sizeof(data); 95f484ffa1SOphir Munk io.iov_base = &data; 96f484ffa1SOphir Munk do { 97f484ffa1SOphir Munk ret = sendmsg(conn_sock, &msg, 0); 98f484ffa1SOphir Munk } while (ret < 0 && errno == EINTR); 99f484ffa1SOphir Munk if (ret < 0) 100f484ffa1SOphir Munk DRV_LOG(WARNING, "failed to send response %s", 101f484ffa1SOphir Munk strerror(errno)); 102f484ffa1SOphir Munk error: 103f484ffa1SOphir Munk if (conn_sock >= 0) 104f484ffa1SOphir Munk close(conn_sock); 105f484ffa1SOphir Munk if (file) 106f484ffa1SOphir Munk fclose(file); 107f484ffa1SOphir Munk } 108f484ffa1SOphir Munk 109f484ffa1SOphir Munk /** 110f484ffa1SOphir Munk * Install interrupt handler. 111f484ffa1SOphir Munk * 112f484ffa1SOphir Munk * @param dev 113f484ffa1SOphir Munk * Pointer to Ethernet device. 114f484ffa1SOphir Munk * @return 115f484ffa1SOphir Munk * 0 on success, a negative errno value otherwise. 116f484ffa1SOphir Munk */ 117f484ffa1SOphir Munk static int 118f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_install(void) 119f484ffa1SOphir Munk { 120f484ffa1SOphir Munk MLX5_ASSERT(server_socket); 121f484ffa1SOphir Munk server_intr_handle.fd = server_socket; 122f484ffa1SOphir Munk server_intr_handle.type = RTE_INTR_HANDLE_EXT; 123f484ffa1SOphir Munk return rte_intr_callback_register(&server_intr_handle, 124f484ffa1SOphir Munk mlx5_pmd_socket_handle, NULL); 125f484ffa1SOphir Munk } 126f484ffa1SOphir Munk 127f484ffa1SOphir Munk /** 128f484ffa1SOphir Munk * Uninstall interrupt handler. 129f484ffa1SOphir Munk */ 130f484ffa1SOphir Munk static void 131f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_uninstall(void) 132f484ffa1SOphir Munk { 133f484ffa1SOphir Munk if (server_socket) { 134f484ffa1SOphir Munk mlx5_intr_callback_unregister(&server_intr_handle, 135f484ffa1SOphir Munk mlx5_pmd_socket_handle, 136f484ffa1SOphir Munk NULL); 137f484ffa1SOphir Munk } 138f484ffa1SOphir Munk server_intr_handle.fd = 0; 139f484ffa1SOphir Munk server_intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 140f484ffa1SOphir Munk } 141f484ffa1SOphir Munk 142f484ffa1SOphir Munk /** 143f484ffa1SOphir Munk * Initialise the socket to communicate with the secondary process 144f484ffa1SOphir Munk * 145f484ffa1SOphir Munk * @param[in] dev 146f484ffa1SOphir Munk * Pointer to Ethernet device. 147f484ffa1SOphir Munk * 148f484ffa1SOphir Munk * @return 149f484ffa1SOphir Munk * 0 on success, a negative value otherwise. 150f484ffa1SOphir Munk */ 151f484ffa1SOphir Munk int 152f484ffa1SOphir Munk mlx5_pmd_socket_init(void) 153f484ffa1SOphir Munk { 154f484ffa1SOphir Munk struct sockaddr_un sun = { 155f484ffa1SOphir Munk .sun_family = AF_UNIX, 156f484ffa1SOphir Munk }; 157f484ffa1SOphir Munk int ret; 158f484ffa1SOphir Munk int flags; 159f484ffa1SOphir Munk 160f484ffa1SOphir Munk MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 161f484ffa1SOphir Munk if (server_socket) 162f484ffa1SOphir Munk return 0; 163f484ffa1SOphir Munk /* 164f484ffa1SOphir Munk * Initialize the socket to communicate with the secondary 165f484ffa1SOphir Munk * process. 166f484ffa1SOphir Munk */ 167f484ffa1SOphir Munk ret = socket(AF_UNIX, SOCK_STREAM, 0); 168f484ffa1SOphir Munk if (ret < 0) { 169f484ffa1SOphir Munk DRV_LOG(WARNING, "Failed to open mlx5 socket: %s", 170f484ffa1SOphir Munk strerror(errno)); 171f484ffa1SOphir Munk goto error; 172f484ffa1SOphir Munk } 173f484ffa1SOphir Munk server_socket = ret; 174f484ffa1SOphir Munk flags = fcntl(server_socket, F_GETFL, 0); 175f484ffa1SOphir Munk if (flags == -1) 176f484ffa1SOphir Munk goto error; 177f484ffa1SOphir Munk ret = fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); 178f484ffa1SOphir Munk if (ret < 0) 179f484ffa1SOphir Munk goto error; 180733bbf51SXueming Li snprintf(sun.sun_path, sizeof(sun.sun_path), MLX5_SOCKET_PATH, 181733bbf51SXueming Li getpid()); 182f484ffa1SOphir Munk remove(sun.sun_path); 183f484ffa1SOphir Munk ret = bind(server_socket, (const struct sockaddr *)&sun, sizeof(sun)); 184f484ffa1SOphir Munk if (ret < 0) { 185f484ffa1SOphir Munk DRV_LOG(WARNING, 186f484ffa1SOphir Munk "cannot bind mlx5 socket: %s", strerror(errno)); 187f484ffa1SOphir Munk goto close; 188f484ffa1SOphir Munk } 189f484ffa1SOphir Munk ret = listen(server_socket, 0); 190f484ffa1SOphir Munk if (ret < 0) { 191f484ffa1SOphir Munk DRV_LOG(WARNING, "cannot listen on mlx5 socket: %s", 192f484ffa1SOphir Munk strerror(errno)); 193f484ffa1SOphir Munk goto close; 194f484ffa1SOphir Munk } 195f484ffa1SOphir Munk if (mlx5_pmd_interrupt_handler_install()) { 196f484ffa1SOphir Munk DRV_LOG(WARNING, "cannot register interrupt handler for mlx5 socket: %s", 197f484ffa1SOphir Munk strerror(errno)); 198f484ffa1SOphir Munk goto close; 199f484ffa1SOphir Munk } 200f484ffa1SOphir Munk return 0; 201f484ffa1SOphir Munk close: 202f484ffa1SOphir Munk remove(sun.sun_path); 203f484ffa1SOphir Munk error: 204f484ffa1SOphir Munk claim_zero(close(server_socket)); 205f484ffa1SOphir Munk server_socket = 0; 206f484ffa1SOphir Munk DRV_LOG(ERR, "Cannot initialize socket: %s", strerror(errno)); 207f484ffa1SOphir Munk return -errno; 208f484ffa1SOphir Munk } 209f484ffa1SOphir Munk 210f484ffa1SOphir Munk /** 211f484ffa1SOphir Munk * Un-Initialize the pmd socket 212f484ffa1SOphir Munk */ 213f484ffa1SOphir Munk RTE_FINI(mlx5_pmd_socket_uninit) 214f484ffa1SOphir Munk { 215f484ffa1SOphir Munk if (!server_socket) 216f484ffa1SOphir Munk return; 217f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_uninstall(); 218f484ffa1SOphir Munk claim_zero(close(server_socket)); 219f484ffa1SOphir Munk server_socket = 0; 220733bbf51SXueming Li MKSTR(path, MLX5_SOCKET_PATH, getpid()); 221f484ffa1SOphir Munk claim_zero(remove(path)); 222f484ffa1SOphir Munk } 223