1f484ffa1SOphir Munk /* SPDX-License-Identifier: BSD-3-Clause 2f484ffa1SOphir Munk * Copyright 2019 Mellanox Technologies, Ltd 3f484ffa1SOphir Munk */ 4f484ffa1SOphir Munk 5*bd0a9315SHaifei Luo #ifndef _GNU_SOURCE 6*bd0a9315SHaifei Luo #define _GNU_SOURCE 7*bd0a9315SHaifei Luo #endif 8*bd0a9315SHaifei Luo 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 23733bbf51SXueming Li #define MLX5_SOCKET_PATH "/var/tmp/dpdk_net_mlx5_%d" 24733bbf51SXueming 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; 37*bd0a9315SHaifei Luo uint32_t data[MLX5_SENDMSG_MAX / sizeof(uint32_t)]; 38*bd0a9315SHaifei Luo uint64_t flow_ptr = 0; 39*bd0a9315SHaifei Luo uint8_t buf[CMSG_SPACE(sizeof(int))] = { 0 }; 40f484ffa1SOphir Munk struct iovec io = { 41*bd0a9315SHaifei Luo .iov_base = data, 42f484ffa1SOphir Munk .iov_len = sizeof(data), 43f484ffa1SOphir Munk }; 44f484ffa1SOphir Munk struct msghdr msg = { 45f484ffa1SOphir Munk .msg_iov = &io, 46f484ffa1SOphir Munk .msg_iovlen = 1, 47f484ffa1SOphir Munk .msg_control = buf, 48f484ffa1SOphir Munk .msg_controllen = sizeof(buf), 49f484ffa1SOphir Munk }; 50*bd0a9315SHaifei Luo 51*bd0a9315SHaifei Luo uint32_t port_id; 52f484ffa1SOphir Munk int fd; 53f484ffa1SOphir Munk FILE *file = NULL; 54f484ffa1SOphir Munk struct rte_eth_dev *dev; 55*bd0a9315SHaifei Luo struct rte_flow_error err; 56*bd0a9315SHaifei Luo struct mlx5_flow_dump_req *dump_req; 57*bd0a9315SHaifei Luo struct mlx5_flow_dump_ack *dump_ack; 58f484ffa1SOphir Munk 59*bd0a9315SHaifei Luo memset(data, 0, sizeof(data)); 60f484ffa1SOphir Munk /* Accept the connection from the client. */ 61f484ffa1SOphir Munk conn_sock = accept(server_socket, NULL, NULL); 62f484ffa1SOphir Munk if (conn_sock < 0) { 63f484ffa1SOphir Munk DRV_LOG(WARNING, "connection failed: %s", strerror(errno)); 64f484ffa1SOphir Munk return; 65f484ffa1SOphir Munk } 66f484ffa1SOphir Munk ret = recvmsg(conn_sock, &msg, MSG_WAITALL); 67*bd0a9315SHaifei Luo if (ret != sizeof(struct mlx5_flow_dump_req)) { 68f484ffa1SOphir Munk DRV_LOG(WARNING, "wrong message received: %s", 69f484ffa1SOphir Munk strerror(errno)); 70f484ffa1SOphir Munk goto error; 71f484ffa1SOphir Munk } 72*bd0a9315SHaifei Luo 73f484ffa1SOphir Munk /* Receive file descriptor. */ 74f484ffa1SOphir Munk cmsg = CMSG_FIRSTHDR(&msg); 75f484ffa1SOphir Munk if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS || 76f484ffa1SOphir Munk cmsg->cmsg_len < sizeof(int)) { 77f484ffa1SOphir Munk DRV_LOG(WARNING, "invalid file descriptor message"); 78f484ffa1SOphir Munk goto error; 79f484ffa1SOphir Munk } 80f484ffa1SOphir Munk memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 81f484ffa1SOphir Munk file = fdopen(fd, "w"); 82f484ffa1SOphir Munk if (!file) { 83f484ffa1SOphir Munk DRV_LOG(WARNING, "Failed to open file"); 84f484ffa1SOphir Munk goto error; 85f484ffa1SOphir Munk } 86f484ffa1SOphir Munk /* Receive port number. */ 87f484ffa1SOphir Munk if (msg.msg_iovlen != 1 || msg.msg_iov->iov_len < sizeof(uint16_t)) { 88f484ffa1SOphir Munk DRV_LOG(WARNING, "wrong port number message"); 89f484ffa1SOphir Munk goto error; 90f484ffa1SOphir Munk } 91*bd0a9315SHaifei Luo 92*bd0a9315SHaifei Luo dump_req = (struct mlx5_flow_dump_req *)msg.msg_iov->iov_base; 93*bd0a9315SHaifei Luo if (dump_req) { 94*bd0a9315SHaifei Luo port_id = dump_req->port_id; 95*bd0a9315SHaifei Luo flow_ptr = dump_req->flow_id; 96*bd0a9315SHaifei Luo } else { 97*bd0a9315SHaifei Luo DRV_LOG(WARNING, "Invalid message"); 98*bd0a9315SHaifei Luo goto error; 99*bd0a9315SHaifei Luo } 100*bd0a9315SHaifei Luo 101f484ffa1SOphir Munk if (!rte_eth_dev_is_valid_port(port_id)) { 102f484ffa1SOphir Munk DRV_LOG(WARNING, "Invalid port %u", port_id); 103f484ffa1SOphir Munk goto error; 104f484ffa1SOphir Munk } 105*bd0a9315SHaifei Luo 106f484ffa1SOphir Munk /* Dump flow. */ 107f484ffa1SOphir Munk dev = &rte_eth_devices[port_id]; 108*bd0a9315SHaifei Luo if (flow_ptr == 0) 10950c38379SHaifei Luo ret = mlx5_flow_dev_dump(dev, NULL, file, NULL); 110*bd0a9315SHaifei Luo else 111*bd0a9315SHaifei Luo ret = mlx5_flow_dev_dump(dev, 112*bd0a9315SHaifei Luo (struct rte_flow *)((uintptr_t)flow_ptr), file, &err); 113*bd0a9315SHaifei Luo 114f484ffa1SOphir Munk /* Set-up the ancillary data and reply. */ 115f484ffa1SOphir Munk msg.msg_controllen = 0; 116f484ffa1SOphir Munk msg.msg_control = NULL; 117f484ffa1SOphir Munk msg.msg_iovlen = 1; 118f484ffa1SOphir Munk msg.msg_iov = &io; 119*bd0a9315SHaifei Luo dump_ack = (struct mlx5_flow_dump_ack *)data; 120*bd0a9315SHaifei Luo dump_ack->rc = -ret; 121*bd0a9315SHaifei Luo io.iov_len = sizeof(struct mlx5_flow_dump_ack); 122*bd0a9315SHaifei Luo io.iov_base = dump_ack; 123f484ffa1SOphir Munk do { 124f484ffa1SOphir Munk ret = sendmsg(conn_sock, &msg, 0); 125f484ffa1SOphir Munk } while (ret < 0 && errno == EINTR); 126f484ffa1SOphir Munk if (ret < 0) 127f484ffa1SOphir Munk DRV_LOG(WARNING, "failed to send response %s", 128f484ffa1SOphir Munk strerror(errno)); 129f484ffa1SOphir Munk error: 130f484ffa1SOphir Munk if (conn_sock >= 0) 131f484ffa1SOphir Munk close(conn_sock); 132f484ffa1SOphir Munk if (file) 133f484ffa1SOphir Munk fclose(file); 134f484ffa1SOphir Munk } 135f484ffa1SOphir Munk 136f484ffa1SOphir Munk /** 137f484ffa1SOphir Munk * Install interrupt handler. 138f484ffa1SOphir Munk * 139f484ffa1SOphir Munk * @param dev 140f484ffa1SOphir Munk * Pointer to Ethernet device. 141f484ffa1SOphir Munk * @return 142f484ffa1SOphir Munk * 0 on success, a negative errno value otherwise. 143f484ffa1SOphir Munk */ 144f484ffa1SOphir Munk static int 145f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_install(void) 146f484ffa1SOphir Munk { 147f484ffa1SOphir Munk MLX5_ASSERT(server_socket); 148f484ffa1SOphir Munk server_intr_handle.fd = server_socket; 149f484ffa1SOphir Munk server_intr_handle.type = RTE_INTR_HANDLE_EXT; 150f484ffa1SOphir Munk return rte_intr_callback_register(&server_intr_handle, 151f484ffa1SOphir Munk mlx5_pmd_socket_handle, NULL); 152f484ffa1SOphir Munk } 153f484ffa1SOphir Munk 154f484ffa1SOphir Munk /** 155f484ffa1SOphir Munk * Uninstall interrupt handler. 156f484ffa1SOphir Munk */ 157f484ffa1SOphir Munk static void 158f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_uninstall(void) 159f484ffa1SOphir Munk { 160f484ffa1SOphir Munk if (server_socket) { 161f484ffa1SOphir Munk mlx5_intr_callback_unregister(&server_intr_handle, 162f484ffa1SOphir Munk mlx5_pmd_socket_handle, 163f484ffa1SOphir Munk NULL); 164f484ffa1SOphir Munk } 165f484ffa1SOphir Munk server_intr_handle.fd = 0; 166f484ffa1SOphir Munk server_intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 167f484ffa1SOphir Munk } 168f484ffa1SOphir Munk 169f484ffa1SOphir Munk /** 170f484ffa1SOphir Munk * Initialise the socket to communicate with the secondary process 171f484ffa1SOphir Munk * 172f484ffa1SOphir Munk * @param[in] dev 173f484ffa1SOphir Munk * Pointer to Ethernet device. 174f484ffa1SOphir Munk * 175f484ffa1SOphir Munk * @return 176f484ffa1SOphir Munk * 0 on success, a negative value otherwise. 177f484ffa1SOphir Munk */ 178f484ffa1SOphir Munk int 179f484ffa1SOphir Munk mlx5_pmd_socket_init(void) 180f484ffa1SOphir Munk { 181f484ffa1SOphir Munk struct sockaddr_un sun = { 182f484ffa1SOphir Munk .sun_family = AF_UNIX, 183f484ffa1SOphir Munk }; 184f484ffa1SOphir Munk int ret; 185f484ffa1SOphir Munk int flags; 186f484ffa1SOphir Munk 187f484ffa1SOphir Munk MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 188f484ffa1SOphir Munk if (server_socket) 189f484ffa1SOphir Munk return 0; 190f484ffa1SOphir Munk /* 191f484ffa1SOphir Munk * Initialize the socket to communicate with the secondary 192f484ffa1SOphir Munk * process. 193f484ffa1SOphir Munk */ 194f484ffa1SOphir Munk ret = socket(AF_UNIX, SOCK_STREAM, 0); 195f484ffa1SOphir Munk if (ret < 0) { 196f484ffa1SOphir Munk DRV_LOG(WARNING, "Failed to open mlx5 socket: %s", 197f484ffa1SOphir Munk strerror(errno)); 198f484ffa1SOphir Munk goto error; 199f484ffa1SOphir Munk } 200f484ffa1SOphir Munk server_socket = ret; 201f484ffa1SOphir Munk flags = fcntl(server_socket, F_GETFL, 0); 202f484ffa1SOphir Munk if (flags == -1) 203f484ffa1SOphir Munk goto error; 204f484ffa1SOphir Munk ret = fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); 205f484ffa1SOphir Munk if (ret < 0) 206f484ffa1SOphir Munk goto error; 207733bbf51SXueming Li snprintf(sun.sun_path, sizeof(sun.sun_path), MLX5_SOCKET_PATH, 208733bbf51SXueming Li getpid()); 209f484ffa1SOphir Munk remove(sun.sun_path); 210f484ffa1SOphir Munk ret = bind(server_socket, (const struct sockaddr *)&sun, sizeof(sun)); 211f484ffa1SOphir Munk if (ret < 0) { 212f484ffa1SOphir Munk DRV_LOG(WARNING, 213f484ffa1SOphir Munk "cannot bind mlx5 socket: %s", strerror(errno)); 214f484ffa1SOphir Munk goto close; 215f484ffa1SOphir Munk } 216f484ffa1SOphir Munk ret = listen(server_socket, 0); 217f484ffa1SOphir Munk if (ret < 0) { 218f484ffa1SOphir Munk DRV_LOG(WARNING, "cannot listen on mlx5 socket: %s", 219f484ffa1SOphir Munk strerror(errno)); 220f484ffa1SOphir Munk goto close; 221f484ffa1SOphir Munk } 222f484ffa1SOphir Munk if (mlx5_pmd_interrupt_handler_install()) { 223f484ffa1SOphir Munk DRV_LOG(WARNING, "cannot register interrupt handler for mlx5 socket: %s", 224f484ffa1SOphir Munk strerror(errno)); 225f484ffa1SOphir Munk goto close; 226f484ffa1SOphir Munk } 227f484ffa1SOphir Munk return 0; 228f484ffa1SOphir Munk close: 229f484ffa1SOphir Munk remove(sun.sun_path); 230f484ffa1SOphir Munk error: 231f484ffa1SOphir Munk claim_zero(close(server_socket)); 232f484ffa1SOphir Munk server_socket = 0; 233f484ffa1SOphir Munk DRV_LOG(ERR, "Cannot initialize socket: %s", strerror(errno)); 234f484ffa1SOphir Munk return -errno; 235f484ffa1SOphir Munk } 236f484ffa1SOphir Munk 237f484ffa1SOphir Munk /** 238f484ffa1SOphir Munk * Un-Initialize the pmd socket 239f484ffa1SOphir Munk */ 240f484ffa1SOphir Munk RTE_FINI(mlx5_pmd_socket_uninit) 241f484ffa1SOphir Munk { 242f484ffa1SOphir Munk if (!server_socket) 243f484ffa1SOphir Munk return; 244f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_uninstall(); 245f484ffa1SOphir Munk claim_zero(close(server_socket)); 246f484ffa1SOphir Munk server_socket = 0; 247733bbf51SXueming Li MKSTR(path, MLX5_SOCKET_PATH, getpid()); 248f484ffa1SOphir Munk claim_zero(remove(path)); 249f484ffa1SOphir Munk } 250