X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_socket.c;h=a79896cb33a6101770d59786333c2f39ff81396d;hb=7bc39dac4a088617175b559323ff4b6d74bd5d48;hp=61c1a4a502d827ba7aceab000dc5ff40c188cad8;hpb=8fd92a66c60a7310cf5ab91996b9b09447512a61;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_socket.c b/drivers/net/mlx5/mlx5_socket.c index 61c1a4a502..a79896cb33 100644 --- a/drivers/net/mlx5/mlx5_socket.c +++ b/drivers/net/mlx5/mlx5_socket.c @@ -1,8 +1,10 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2016 6WIND S.A. + * Copyright 2019 Mellanox Technologies, Ltd */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -12,107 +14,36 @@ #include #include -#include "mlx5.h" +#include "rte_eal.h" #include "mlx5_utils.h" +#include "mlx5.h" -/** - * Initialise the socket to communicate with the secondary process - * - * @param[in] priv - * Pointer to private structure. - * - * @return - * 0 on success, errno value on failure. - */ -int -priv_socket_init(struct priv *priv) -{ - struct sockaddr_un sun = { - .sun_family = AF_UNIX, - }; - int ret; - int flags; - struct stat file_stat; +/* PMD socket service for tools. */ - /* - * Initialise the socket to communicate with the secondary - * process. - */ - ret = socket(AF_UNIX, SOCK_STREAM, 0); - if (ret < 0) { - WARN("secondary process not supported: %s", strerror(errno)); - return ret; - } - priv->primary_socket = ret; - flags = fcntl(priv->primary_socket, F_GETFL, 0); - if (flags == -1) - goto out; - ret = fcntl(priv->primary_socket, F_SETFL, flags | O_NONBLOCK); - if (ret < 0) - goto out; - snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d", - MLX5_DRIVER_NAME, priv->primary_socket); - ret = stat(sun.sun_path, &file_stat); - if (!ret) - claim_zero(remove(sun.sun_path)); - ret = bind(priv->primary_socket, (const struct sockaddr *)&sun, - sizeof(sun)); - if (ret < 0) { - WARN("cannot bind socket, secondary process not supported: %s", - strerror(errno)); - goto close; - } - ret = listen(priv->primary_socket, 0); - if (ret < 0) { - WARN("Secondary process not supported: %s", strerror(errno)); - goto close; - } - return ret; -close: - remove(sun.sun_path); -out: - claim_zero(close(priv->primary_socket)); - priv->primary_socket = 0; - return -(ret); -} +int server_socket; /* Unix socket for primary process. */ +struct rte_intr_handle server_intr_handle; /* Interrupt handler. */ -/** - * Un-Initialise the socket to communicate with the secondary process - * - * @param[in] priv - * Pointer to private structure. - * - * @return - * 0 on success, errno value on failure. - */ -int -priv_socket_uninit(struct priv *priv) +static void +mlx5_pmd_make_path(struct sockaddr_un *addr, int pid) { - MKSTR(path, "/var/tmp/%s_%d", MLX5_DRIVER_NAME, priv->primary_socket); - claim_zero(close(priv->primary_socket)); - priv->primary_socket = 0; - claim_zero(remove(path)); - return 0; + snprintf(addr->sun_path, sizeof(addr->sun_path), "/var/tmp/dpdk_%s_%d", + MLX5_DRIVER_NAME, pid); } /** - * Handle socket interrupts. - * - * @param priv - * Pointer to private structure. + * Handle server pmd socket interrupts. */ -void -priv_socket_handle(struct priv *priv) +static void +mlx5_pmd_socket_handle(void *cb __rte_unused) { int conn_sock; - int ret = 0; + int ret = -1; struct cmsghdr *cmsg = NULL; - struct ucred *cred = NULL; - char buf[CMSG_SPACE(sizeof(struct ucred))] = { 0 }; - char vbuf[1024] = { 0 }; + int data; + char buf[CMSG_SPACE(sizeof(int))] = { 0 }; struct iovec io = { - .iov_base = vbuf, - .iov_len = sizeof(*vbuf), + .iov_base = &data, + .iov_len = sizeof(data), }; struct msghdr msg = { .msg_iov = &io, @@ -120,148 +51,180 @@ priv_socket_handle(struct priv *priv) .msg_control = buf, .msg_controllen = sizeof(buf), }; - int *fd; + uint16_t port_id; + int fd; + FILE *file = NULL; + struct rte_eth_dev *dev; /* Accept the connection from the client. */ - conn_sock = accept(priv->primary_socket, NULL, NULL); + conn_sock = accept(server_socket, NULL, NULL); if (conn_sock < 0) { - WARN("connection failed: %s", strerror(errno)); + DRV_LOG(WARNING, "connection failed: %s", strerror(errno)); return; } - ret = setsockopt(conn_sock, SOL_SOCKET, SO_PASSCRED, &(int){1}, - sizeof(int)); - if (ret < 0) { - WARN("cannot change socket options"); - goto out; - } ret = recvmsg(conn_sock, &msg, MSG_WAITALL); if (ret < 0) { - WARN("received an empty message: %s", strerror(errno)); - goto out; + DRV_LOG(WARNING, "wrong message received: %s", + strerror(errno)); + goto error; } - /* Expect to receive credentials only. */ + /* Receive file descriptor. */ cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg == NULL) { - WARN("no message"); - goto out; - } - if ((cmsg->cmsg_type == SCM_CREDENTIALS) && - (cmsg->cmsg_len >= sizeof(*cred))) { - cred = (struct ucred *)CMSG_DATA(cmsg); - assert(cred != NULL); - } - cmsg = CMSG_NXTHDR(&msg, cmsg); - if (cmsg != NULL) { - WARN("Message wrongly formatted"); - goto out; - } - /* Make sure all the ancillary data was received and valid. */ - if ((cred == NULL) || (cred->uid != getuid()) || - (cred->gid != getgid())) { - WARN("wrong credentials"); - goto out; - } - /* Set-up the ancillary data. */ - cmsg = CMSG_FIRSTHDR(&msg); - assert(cmsg != NULL); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(priv->ctx->cmd_fd)); - fd = (int *)CMSG_DATA(cmsg); - *fd = priv->ctx->cmd_fd; - ret = sendmsg(conn_sock, &msg, 0); + if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS || + cmsg->cmsg_len < sizeof(int)) { + DRV_LOG(WARNING, "invalid file descriptor message"); + goto error; + } + memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + file = fdopen(fd, "w"); + if (!file) { + DRV_LOG(WARNING, "Failed to open file"); + goto error; + } + /* Receive port number. */ + if (msg.msg_iovlen != 1 || msg.msg_iov->iov_len < sizeof(uint16_t)) { + DRV_LOG(WARNING, "wrong port number message"); + goto error; + } + memcpy(&port_id, msg.msg_iov->iov_base, sizeof(port_id)); + if (!rte_eth_dev_is_valid_port(port_id)) { + DRV_LOG(WARNING, "Invalid port %u", port_id); + goto error; + } + /* Dump flow. */ + dev = &rte_eth_devices[port_id]; + ret = mlx5_flow_dev_dump(dev, file, NULL); + /* Set-up the ancillary data and reply. */ + msg.msg_controllen = 0; + msg.msg_control = NULL; + msg.msg_iovlen = 1; + msg.msg_iov = &io; + data = -ret; + io.iov_len = sizeof(data); + io.iov_base = &data; + do { + ret = sendmsg(conn_sock, &msg, 0); + } while (ret < 0 && errno == EINTR); if (ret < 0) - WARN("cannot send response"); -out: - close(conn_sock); + DRV_LOG(WARNING, "failed to send response %s", + strerror(errno)); +error: + if (conn_sock > 0) + close(conn_sock); + if (file) + fclose(file); } /** - * Connect to the primary process. + * Install interrupt handler. * - * @param[in] priv - * Pointer to private structure. + * @param dev + * Pointer to Ethernet device. + * @return + * 0 on success, a negative errno value otherwise. + */ +static int +mlx5_pmd_interrupt_handler_install(void) +{ + MLX5_ASSERT(server_socket); + server_intr_handle.fd = server_socket; + server_intr_handle.type = RTE_INTR_HANDLE_EXT; + return rte_intr_callback_register(&server_intr_handle, + mlx5_pmd_socket_handle, NULL); +} + +/** + * Uninstall interrupt handler. + */ +static void +mlx5_pmd_interrupt_handler_uninstall(void) +{ + if (server_socket) { + mlx5_intr_callback_unregister(&server_intr_handle, + mlx5_pmd_socket_handle, + NULL); + } + server_intr_handle.fd = 0; + server_intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; +} + +/** + * Initialise the socket to communicate with the secondary process + * + * @param[in] dev + * Pointer to Ethernet device. * * @return - * fd on success, negative errno value on failure. + * 0 on success, a negative value otherwise. */ int -priv_socket_connect(struct priv *priv) +mlx5_pmd_socket_init(void) { struct sockaddr_un sun = { .sun_family = AF_UNIX, }; - int socket_fd; - int *fd = NULL; - int ret; - struct ucred *cred; - char buf[CMSG_SPACE(sizeof(*cred))] = { 0 }; - char vbuf[1024] = { 0 }; - struct iovec io = { - .iov_base = vbuf, - .iov_len = sizeof(*vbuf), - }; - struct msghdr msg = { - .msg_control = buf, - .msg_controllen = sizeof(buf), - .msg_iov = &io, - .msg_iovlen = 1, - }; - struct cmsghdr *cmsg; + int ret = -1; + int flags; + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); + if (server_socket) + return 0; + /* + * Initialize the socket to communicate with the secondary + * process. + */ ret = socket(AF_UNIX, SOCK_STREAM, 0); if (ret < 0) { - WARN("cannot connect to primary"); - return ret; + DRV_LOG(WARNING, "Failed to open mlx5 socket: %s", + strerror(errno)); + goto error; } - socket_fd = ret; - snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d", - MLX5_DRIVER_NAME, priv->primary_socket); - ret = connect(socket_fd, (const struct sockaddr *)&sun, sizeof(sun)); + server_socket = ret; + flags = fcntl(server_socket, F_GETFL, 0); + if (flags == -1) + goto error; + ret = fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); + if (ret < 0) + goto error; + mlx5_pmd_make_path(&sun, getpid()); + remove(sun.sun_path); + ret = bind(server_socket, (const struct sockaddr *)&sun, sizeof(sun)); if (ret < 0) { - WARN("cannot connect to primary"); - goto out; - } - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg == NULL) { - DEBUG("cannot get first message"); - goto out; - } - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_CREDENTIALS; - cmsg->cmsg_len = CMSG_LEN(sizeof(*cred)); - cred = (struct ucred *)CMSG_DATA(cmsg); - if (cred == NULL) { - DEBUG("no credentials received"); - goto out; + DRV_LOG(WARNING, + "cannot bind mlx5 socket: %s", strerror(errno)); + goto close; } - cred->pid = getpid(); - cred->uid = getuid(); - cred->gid = getgid(); - ret = sendmsg(socket_fd, &msg, MSG_DONTWAIT); + ret = listen(server_socket, 0); if (ret < 0) { - WARN("cannot send credentials to primary: %s", - strerror(errno)); - goto out; - } - ret = recvmsg(socket_fd, &msg, MSG_WAITALL); - if (ret <= 0) { - WARN("no message from primary: %s", strerror(errno)); - goto out; - } - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg == NULL) { - WARN("No file descriptor received"); - goto out; + DRV_LOG(WARNING, "cannot listen on mlx5 socket: %s", + strerror(errno)); + goto close; } - fd = (int *)CMSG_DATA(cmsg); - if (*fd <= 0) { - WARN("no file descriptor received: %s", strerror(errno)); - ret = *fd; - goto out; + if (mlx5_pmd_interrupt_handler_install()) { + DRV_LOG(WARNING, "cannot register interrupt handler for mlx5 socket: %s", + strerror(errno)); + goto close; } - ret = *fd; -out: - close(socket_fd); - return ret; + return 0; +close: + remove(sun.sun_path); +error: + claim_zero(close(server_socket)); + server_socket = 0; + DRV_LOG(ERR, "Cannot initialize socket: %s", strerror(errno)); + return -errno; +} + +/** + * Un-Initialize the pmd socket + */ +RTE_FINI(mlx5_pmd_socket_uninit) +{ + if (!server_socket) + return; + mlx5_pmd_interrupt_handler_uninstall(); + claim_zero(close(server_socket)); + server_socket = 0; + MKSTR(path, "/var/tmp/dpdk_%s_%d", MLX5_DRIVER_NAME, getpid()); + claim_zero(remove(path)); }