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