On Fri, 20-01-17, 16:47, Slava Ovsiienko wrote: > Hi, Jack > > > -----Original Message----- > > From: Xiaoyu Min <jack...@mellanox.com> > > Sent: Thursday, January 16, 2020 12:14 > > To: jerinjac...@gmail.com; Ori Kam <or...@mellanox.com>; Slava Ovsiienko > > <viachesl...@mellanox.com>; Matan Azrad <ma...@mellanox.com>; Raslan > > Darawsheh <rasl...@mellanox.com>; Shahaf Shuler > > <shah...@mellanox.com>; Anatoly Burakov <anatoly.bura...@intel.com> > > Cc: dev@dpdk.org; Xueming(Steven) Li <xuemi...@mellanox.com> > > Subject: [PATCH 4/5] net/mlx5: add socket server for external tools > > > > From: Xueming Li <xuemi...@mellanox.com> > > > > Add pmd unix socket server to enable external tool applications to trigger > > flow dump. > > > > Socket path: > > /var/tmp/dpdk_mlx5_<pid> > > Socket format: > > io_raw: port_id of uint16 > > file: file descriptor of int > > > > Signed-off-by: Xueming Li <xuemi...@mellanox.com> > > Signed-off-by: Xiaoyu Min <jack...@mellanox.com> > > --- > > drivers/net/mlx5/Makefile | 1 + > > drivers/net/mlx5/meson.build | 1 + > > drivers/net/mlx5/mlx5.c | 2 + > > drivers/net/mlx5/mlx5.h | 5 + > > drivers/net/mlx5/mlx5_socket.c | 227 +++++++++++++++++++++++++++++++++ > > 5 files changed, 236 insertions(+) > > create mode 100644 drivers/net/mlx5/mlx5_socket.c > > > > diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index > > 6e5921b292..397e29dcbb 100644 > > --- a/drivers/net/mlx5/Makefile > > +++ b/drivers/net/mlx5/Makefile > > @@ -39,6 +39,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mp.c > > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c > > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c > > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_utils.c > > +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c > > > > ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y) > > INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE) diff --git > > a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index > > d7ef032afb..cb2fb90495 100644 > > --- a/drivers/net/mlx5/meson.build > > +++ b/drivers/net/mlx5/meson.build > > @@ -61,6 +61,7 @@ if build > > 'mlx5_vlan.c', > > 'mlx5_devx_cmds.c', > > 'mlx5_utils.c', > > + 'mlx5_socket.c', > > ) > > if (dpdk_conf.has('RTE_ARCH_X86_64') > > or dpdk_conf.has('RTE_ARCH_ARM64') > > diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index > > 50960c91ce..ffee39c1a0 100644 > > --- a/drivers/net/mlx5/mlx5.c > > +++ b/drivers/net/mlx5/mlx5.c > > @@ -2954,6 +2954,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv > > __rte_unused, > > struct mlx5_dev_config dev_config; > > int ret; > > > > + if (rte_eal_process_type() == RTE_PROC_PRIMARY) > > + mlx5_pmd_socket_init(); > > ret = mlx5_init_once(); > > if (ret) { > > DRV_LOG(ERR, "unable to init PMD global data: %s", diff --git > > a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index > > 047181b32e..ceb6de821e 100644 > > --- a/drivers/net/mlx5/mlx5.h > > +++ b/drivers/net/mlx5/mlx5.h > > @@ -990,6 +990,11 @@ void mlx5_mp_uninit_primary(void); int > > mlx5_mp_init_secondary(void); void mlx5_mp_uninit_secondary(void); > > > > +/* mlx5_socket.c */ > > + > > +int mlx5_pmd_socket_init(void); > > +void mlx5_pmd_socket_uninit(void); > > + > > /* mlx5_nl.c */ > > > > int mlx5_nl_init(int protocol); > > diff --git a/drivers/net/mlx5/mlx5_socket.c b/drivers/net/mlx5/mlx5_socket.c > > new file mode 100644 index 0000000000..e4c93c4312 > > --- /dev/null > > +++ b/drivers/net/mlx5/mlx5_socket.c > > @@ -0,0 +1,227 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright 2019 Mellanox Technologies, Ltd */ > > + > > +#ifndef _GNU_SOURCE > > +#define _GNU_SOURCE > > +#endif > > + > > +#include <sys/types.h> > > +#include <sys/socket.h> > > +#include <sys/un.h> > > +#include <fcntl.h> > > +#include <stdio.h> > > +#include <unistd.h> > > +#include <sys/stat.h> > > + > > +#include "rte_eal.h" > > +#include "mlx5_utils.h" > > +#include "mlx5.h" > > + > > +/* PMD socket service for tools. */ > > + > > +int server_socket; /* Unix socket for primary process. */ struct > > +rte_intr_handle server_intr_handle; /* Interrupt handler. */ > > + > > +static void > > +mlx5_pmd_make_path(struct sockaddr_un *addr, int pid) { > > + snprintf(addr->sun_path, sizeof(addr->sun_path), > > "/var/tmp/dpdk_%s_%d", > > + MLX5_DRIVER_NAME, pid); > > +} > > + > > +/** > > + * Handle server pmd socket interrupts. > > + */ > > +static void > > +mlx5_pmd_socket_handle(void *cb __rte_unused) { > > + int conn_sock; > > + int ret = -1; > > + struct cmsghdr *cmsg = NULL; > > + int data; > > + char buf[CMSG_SPACE(sizeof(int))] = { 0 }; > > + struct iovec io = { > > + .iov_base = &data, > > + .iov_len = sizeof(data), > > + }; > > + struct msghdr msg = { > > + .msg_iov = &io, > > + .msg_iovlen = 1, > > + .msg_control = buf, > > + .msg_controllen = sizeof(buf), > > + }; > > + uint16_t port_id; > > + int fd; > > + FILE *file = NULL; > > + struct rte_eth_dev *dev; > > + > > + /* Accept the connection from the client. */ > > + conn_sock = accept(server_socket, NULL, NULL); > > + if (conn_sock < 0) { > > + DRV_LOG(WARNING, "connection failed: %s", strerror(errno)); > > + return; > > + } > > + ret = recvmsg(conn_sock, &msg, MSG_WAITALL); > > + if (ret < 0) { > > + DRV_LOG(WARNING, "wrong message received: %s", > > + strerror(errno)); > > + goto error; > > + } > > + /* Receive file descriptor. */ > > + cmsg = CMSG_FIRSTHDR(&msg); > > + 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)); > I would add the port_id check here. > The message with wrong port_id may crash the server. Yes, you are right. I'll update it in v2.
> > > > + /* 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) > > + DRV_LOG(WARNING, "failed to send response %s", > > + strerror(errno)); > > +error: > > + if (conn_sock > 0) > > + close(conn_sock); > > + if (file) > > + fclose(file); > > +} > > + > > +/** > > + * Install interrupt handler. > > + * > > + * @param dev > > + * Pointer to Ethernet device. > > + * @return > > + * 0 on success, a negative errno value otherwise. > > + */ > > +static int > > +mlx5_pmd_interrupt_handler_install(void) > > +{ > > + 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 > > + * 0 on success, a negative value otherwise. > > + */ > > +int > > +mlx5_pmd_socket_init(void) > > +{ > > + struct sockaddr_un sun = { > > + .sun_family = AF_UNIX, > > + }; > > + int ret = -1; > > + int flags; > > + > > + 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) { > > + DRV_LOG(WARNING, "Failed to open mlx5 socket: %s", > > + strerror(errno)); > > + goto error; > > + } > > + 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) { > > + DRV_LOG(WARNING, > > + "cannot bind mlx5 socket: %s", strerror(errno)); > > + goto close; > > + } > > + ret = listen(server_socket, 0); > > + if (ret < 0) { > > + DRV_LOG(WARNING, "cannot listen on mlx5 socket: %s", > > + strerror(errno)); > > + goto close; > > + } > > + if (mlx5_pmd_interrupt_handler_install()) { > > + DRV_LOG(WARNING, "cannot register interrupt handler for > > mlx5 socket: %s", > > + strerror(errno)); > > + goto close; > > + } > > + 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 > > + */ > > +void __attribute__((destructor)) > > +mlx5_pmd_socket_uninit(void) > > +{ > > + if (!server_socket) > > + return; > > + mlx5_pmd_interrupt_handler_uninstall(); > > + MKSTR(path, "/var/tmp/dpdk_%s_%d", MLX5_DRIVER_NAME, > > getpid()); > I would move the MKSTR a couple lines below, after the close() call. OK, this seems make code more readable. I'll update it in v2. > > > + claim_zero(close(server_socket)); > > + server_socket = 0; > > + claim_zero(remove(path)); > > +} > > -- > > 2.24.1 > With best regards, Slava Thank you~ -Jack