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