From: Chenbo Xia <chenbo.xia@intel.com> To: dev@dpdk.org, thomas@monjalon.net, david.marchand@redhat.com Cc: stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com, miao.li@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com Subject: [dpdk-dev] [PATCH v2 6/9] vfio_user: add client APIs of device attach/detach Date: Thu, 14 Jan 2021 14:14:08 +0800 Message-ID: <20210114061411.39166-7-chenbo.xia@intel.com> (raw) In-Reply-To: <20210114061411.39166-1-chenbo.xia@intel.com> This patch implements two APIs, rte_vfio_user_attach_dev() and rte_vfio_user_detach_dev() for vfio-user client to connect to or disconnect from a vfio-user device on server side. Signed-off-by: Chenbo Xia <chenbo.xia@intel.com> Signed-off-by: Xiuchun Lu <xiuchun.lu@intel.com> --- lib/librte_vfio_user/meson.build | 3 +- lib/librte_vfio_user/rte_vfio_user.h | 32 +++ lib/librte_vfio_user/version.map | 2 + lib/librte_vfio_user/vfio_user_client.c | 281 ++++++++++++++++++++++++ lib/librte_vfio_user/vfio_user_client.h | 26 +++ 5 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 lib/librte_vfio_user/vfio_user_client.c create mode 100644 lib/librte_vfio_user/vfio_user_client.h diff --git a/lib/librte_vfio_user/meson.build b/lib/librte_vfio_user/meson.build index b7363f61c6..5761f0edd1 100644 --- a/lib/librte_vfio_user/meson.build +++ b/lib/librte_vfio_user/meson.build @@ -6,5 +6,6 @@ if not is_linux reason = 'only supported on Linux' endif -sources = files('vfio_user_base.c', 'vfio_user_server.c') +sources = files('vfio_user_base.c', 'vfio_user_server.c', + 'vfio_user_client.c') headers = files('rte_vfio_user.h') diff --git a/lib/librte_vfio_user/rte_vfio_user.h b/lib/librte_vfio_user/rte_vfio_user.h index 472ca15529..adafa552e2 100644 --- a/lib/librte_vfio_user/rte_vfio_user.h +++ b/lib/librte_vfio_user/rte_vfio_user.h @@ -234,4 +234,36 @@ int rte_vfio_user_set_irq_info(const char *sock_addr, struct rte_vfio_user_irq_info *irq); +/** + * Below APIs are for vfio-user client (device consumer) to use: + * *rte_vfio_user_attach_dev + * *rte_vfio_user_detach_dev + */ + +/** + * Attach to a vfio-user device. + * + * @param sock_addr + * Unix domain socket address + * @return + * - >=0: Success, device attached. Returned value is the device ID. + * - <0: Failure on device attach + */ +__rte_experimental +int +rte_vfio_user_attach_dev(const char *sock_addr); + +/** + * Detach from a vfio-user device. + * + * @param dev_id + * Device ID of the vfio-user device + * @return + * - 0: Success, device detached + * - <0: Failure on device detach + */ +__rte_experimental +int +rte_vfio_user_detach_dev(int dev_id); + #endif diff --git a/lib/librte_vfio_user/version.map b/lib/librte_vfio_user/version.map index 621a51a9fc..a0cda2b49c 100644 --- a/lib/librte_vfio_user/version.map +++ b/lib/librte_vfio_user/version.map @@ -10,6 +10,8 @@ EXPERIMENTAL { rte_vfio_user_set_dev_info; rte_vfio_user_set_reg_info; rte_vfio_user_set_irq_info; + rte_vfio_user_attach_dev; + rte_vfio_user_detach_dev; local: *; }; diff --git a/lib/librte_vfio_user/vfio_user_client.c b/lib/librte_vfio_user/vfio_user_client.c new file mode 100644 index 0000000000..f288cf70f5 --- /dev/null +++ b/lib/librte_vfio_user/vfio_user_client.c @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/un.h> +#include <sys/socket.h> + +#include "vfio_user_client.h" +#include "rte_vfio_user.h" + +#define REPLY_USEC 1000 +#define RECV_MAX_TRY 50 + +static struct vfio_user_client_devs vfio_client_devs = { + .cl_num = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, +}; + +/* Check if the sock_addr exists. If not, alloc and return index */ +static int +vfio_user_client_allocate(const char *sock_addr) +{ + uint32_t i, count = 0; + int index = -1; + + if (sock_addr == NULL) + return -1; + + if (vfio_client_devs.cl_num == 0) + return 0; + + for (i = 0; i < MAX_VFIO_USER_CLIENT; i++) { + struct vfio_user_client *cl = vfio_client_devs.cl[i]; + + if (!cl) { + if (index == -1) + index = i; + continue; + } + + if (!strcmp(cl->sock.sock_addr, sock_addr)) + return -1; + + count++; + if (count == vfio_client_devs.cl_num) + break; + } + + return index; +} + +static struct vfio_user_client * +vfio_user_client_create_dev(const char *sock_addr) +{ + struct vfio_user_client *cl; + struct vfio_user_socket *sock; + int fd, idx; + struct sockaddr_un un = { 0 }; + + pthread_mutex_lock(&vfio_client_devs.mutex); + if (vfio_client_devs.cl_num == MAX_VFIO_USER_CLIENT) { + VFIO_USER_LOG(ERR, "Failed to create client:" + " client num reaches max\n"); + goto err; + } + + idx = vfio_user_client_allocate(sock_addr); + if (idx < 0) { + VFIO_USER_LOG(ERR, "Failed to alloc a slot for client\n"); + goto err; + } + + cl = malloc(sizeof(*cl)); + if (!cl) { + VFIO_USER_LOG(ERR, "Failed to alloc client\n"); + goto err; + } + + sock = &cl->sock; + sock->sock_addr = strdup(sock_addr); + if (!sock->sock_addr) { + VFIO_USER_LOG(ERR, "Failed to copy sock_addr\n"); + goto err_dup; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + VFIO_USER_LOG(ERR, "Client failed to create socket: %s\n", + strerror(errno)); + goto err_sock; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK)) { + VFIO_USER_LOG(ERR, "Failed to set nonblocking mode for client " + "socket, fd: %d (%s)\n", fd, strerror(errno)); + goto err_ctl; + } + + un.sun_family = AF_UNIX; + strncpy(un.sun_path, sock->sock_addr, sizeof(un.sun_path)); + un.sun_path[sizeof(un.sun_path) - 1] = '\0'; + + if (connect(fd, &un, sizeof(un)) < 0) { + VFIO_USER_LOG(ERR, "Client connect error, %s\n", + strerror(errno)); + goto err_ctl; + } + + sock->sock_fd = fd; + sock->dev_id = idx; + cl->msg_id = 0; + + vfio_client_devs.cl[idx] = cl; + vfio_client_devs.cl_num++; + + pthread_mutex_unlock(&vfio_client_devs.mutex); + + return cl; + +err_ctl: + close(fd); +err_sock: + free(sock->sock_addr); +err_dup: + free(sock); +err: + pthread_mutex_unlock(&vfio_client_devs.mutex); + return NULL; +} + +static int +vfio_user_client_destroy_dev(int dev_id) +{ + struct vfio_user_client *cl; + struct vfio_user_socket *sock; + int ret = 0; + + pthread_mutex_lock(&vfio_client_devs.mutex); + if (vfio_client_devs.cl_num == 0) { + VFIO_USER_LOG(ERR, "Failed to destroy client:" + " no client exists\n"); + ret = -EINVAL; + goto err; + } + + cl = vfio_client_devs.cl[dev_id]; + if (!cl) { + VFIO_USER_LOG(ERR, "Failed to destroy client:" + " wrong device ID(%d)\n", dev_id); + ret = -EINVAL; + goto err; + } + + sock = &cl->sock; + free(sock->sock_addr); + close(sock->sock_fd); + + free(cl); + vfio_client_devs.cl[dev_id] = NULL; + vfio_client_devs.cl_num--; + +err: + pthread_mutex_unlock(&vfio_client_devs.mutex); + return ret; +} + +static inline void +vfio_user_client_fill_hdr(struct vfio_user_msg *msg, uint16_t cmd, + uint32_t sz, uint16_t msg_id) +{ + msg->msg_id = msg_id; + msg->cmd = cmd; + msg->size = sz; + msg->flags = VFIO_USER_TYPE_CMD; + msg->err = 0; +} + +static int +vfio_user_client_send_recv(int sock_fd, struct vfio_user_msg *msg) +{ + uint16_t cmd = msg->cmd; + uint16_t id = msg->msg_id; + uint8_t try_recv = 0; + int ret; + + ret = vfio_user_send_msg(sock_fd, msg); + if (ret < 0) { + VFIO_USER_LOG(ERR, "Send error for %s\n", + vfio_user_msg_str[cmd]); + return -1; + } + + VFIO_USER_LOG(INFO, "Send request %s\n", vfio_user_msg_str[cmd]); + + memset(msg, 0, sizeof(*msg)); + + while (try_recv < RECV_MAX_TRY) { + ret = vfio_user_recv_msg(sock_fd, msg); + if (!ret) { + VFIO_USER_LOG(ERR, "Peer closed\n"); + return -1; + } else if (ret > 0) { + if (id != msg->msg_id) + continue; + else + break; + } + usleep(REPLY_USEC); + try_recv++; + } + + if (cmd != msg->cmd) { + VFIO_USER_LOG(ERR, "Request and reply mismatch\n"); + ret = -1; + } else + ret = 0; + + VFIO_USER_LOG(INFO, "Recv reply %s\n", vfio_user_msg_str[cmd]); + + return ret; +} + +int +rte_vfio_user_attach_dev(const char *sock_addr) +{ + struct vfio_user_client *dev; + struct vfio_user_msg msg = { 0 }; + uint32_t sz = VFIO_USER_MSG_HDR_SIZE + sizeof(struct vfio_user_version) + - VFIO_USER_MAX_VERSION_DATA; + struct vfio_user_version *ver = &msg.payload.ver; + int ret; + + if (!sock_addr) + return -EINVAL; + + dev = vfio_user_client_create_dev(sock_addr); + if (!dev) { + VFIO_USER_LOG(ERR, "Failed to attach the device " + "with sock_addr %s\n", sock_addr); + return -1; + } + + vfio_user_client_fill_hdr(&msg, VFIO_USER_VERSION, sz, dev->msg_id++); + ver->major = VFIO_USER_VERSION_MAJOR; + ver->minor = VFIO_USER_VERSION_MINOR; + + ret = vfio_user_client_send_recv(dev->sock.sock_fd, &msg); + if (ret) + return ret; + + if (msg.flags & VFIO_USER_ERROR) { + VFIO_USER_LOG(ERR, "Failed to negotiate version: %s\n", + msg.err ? strerror(msg.err) : "Unknown error"); + return msg.err ? -(int)msg.err : -1; + } + + if (vfio_user_check_msg_fdnum(&msg, 0) != 0) + return -1; + + return dev->sock.dev_id; +} + +int +rte_vfio_user_detach_dev(int dev_id) +{ + int ret; + + if (dev_id < 0) + return -EINVAL; + + ret = vfio_user_client_destroy_dev(dev_id); + if (ret) + VFIO_USER_LOG(ERR, "Failed to detach the device (ID:%d)\n", + dev_id); + + return ret; +} diff --git a/lib/librte_vfio_user/vfio_user_client.h b/lib/librte_vfio_user/vfio_user_client.h new file mode 100644 index 0000000000..47401a43cc --- /dev/null +++ b/lib/librte_vfio_user/vfio_user_client.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#ifndef _VFIO_USER_CLIENT_H +#define _VFIO_USER_CLIENT_H + +#include <stdint.h> + +#include "vfio_user_base.h" + +#define MAX_VFIO_USER_CLIENT 1024 + +struct vfio_user_client { + struct vfio_user_socket sock; + uint16_t msg_id; + uint8_t rsvd[16]; /* Reserved for future use */ +}; + +struct vfio_user_client_devs { + struct vfio_user_client *cl[MAX_VFIO_USER_CLIENT]; + uint32_t cl_num; + pthread_mutex_t mutex; +}; + +#endif -- 2.17.1
next prev parent reply other threads:[~2021-01-14 6:20 UTC|newest] Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-12-18 7:38 [dpdk-dev] [PATCH 0/9] Introduce vfio-user library Chenbo Xia 2020-12-18 7:38 ` [dpdk-dev] [PATCH 1/9] lib: introduce " Chenbo Xia 2020-12-18 17:13 ` Stephen Hemminger 2020-12-19 6:12 ` Xia, Chenbo 2020-12-18 17:17 ` Stephen Hemminger 2020-12-19 6:25 ` Xia, Chenbo 2020-12-18 7:38 ` [dpdk-dev] [PATCH 2/9] vfio_user: implement lifecycle related APIs Chenbo Xia 2021-01-05 8:34 ` Xing, Beilei 2021-01-05 9:58 ` Xia, Chenbo 2020-12-18 7:38 ` [dpdk-dev] [PATCH 3/9] vfio_user: implement device and region " Chenbo Xia 2021-01-06 5:51 ` Xing, Beilei 2021-01-06 7:50 ` Xia, Chenbo 2020-12-18 7:38 ` [dpdk-dev] [PATCH 4/9] vfio_user: implement DMA table and socket address API Chenbo Xia 2020-12-18 7:38 ` [dpdk-dev] [PATCH 5/9] vfio_user: implement interrupt related APIs Chenbo Xia 2020-12-30 1:04 ` Wu, Jingjing 2020-12-30 2:31 ` Xia, Chenbo 2020-12-18 7:38 ` [dpdk-dev] [PATCH 6/9] vfio_user: add client APIs of device attach/detach Chenbo Xia 2020-12-18 7:38 ` [dpdk-dev] [PATCH 7/9] vfio_user: add client APIs of DMA/IRQ/region Chenbo Xia 2021-01-07 2:41 ` Xing, Beilei 2021-01-07 7:26 ` Xia, Chenbo 2020-12-18 7:38 ` [dpdk-dev] [PATCH 8/9] test/vfio_user: introduce functional test Chenbo Xia 2020-12-18 7:38 ` [dpdk-dev] [PATCH 9/9] doc: add vfio-user library guide Chenbo Xia 2021-01-06 5:07 ` Xing, Beilei 2021-01-06 7:43 ` Xia, Chenbo 2020-12-18 9:37 ` [dpdk-dev] [PATCH 0/9] Introduce vfio-user library David Marchand 2020-12-18 14:07 ` Thanos Makatos 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 " Chenbo Xia 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 1/9] lib: introduce " Chenbo Xia 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 2/9] vfio_user: implement lifecycle related APIs Chenbo Xia 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 3/9] vfio_user: implement device and region " Chenbo Xia 2021-01-14 18:48 ` David Christensen 2021-01-19 3:22 ` Xia, Chenbo 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 4/9] vfio_user: implement DMA table and socket address API Chenbo Xia 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 5/9] vfio_user: implement interrupt related APIs Chenbo Xia 2021-01-14 6:14 ` Chenbo Xia [this message] 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 7/9] vfio_user: add client APIs of DMA/IRQ/region Chenbo Xia 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 8/9] test/vfio_user: introduce functional test Chenbo Xia 2021-01-14 19:03 ` David Christensen 2021-01-19 3:27 ` Xia, Chenbo 2021-01-19 18:26 ` David Christensen 2021-01-14 6:14 ` [dpdk-dev] [PATCH v2 9/9] doc: add vfio-user library guide Chenbo Xia 2021-01-15 7:58 ` [dpdk-dev] [PATCH v2 0/9] Introduce vfio-user library David Marchand 2021-01-19 3:13 ` Xia, Chenbo
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210114061411.39166-7-chenbo.xia@intel.com \ --to=chenbo.xia@intel.com \ --cc=beilei.xing@intel.com \ --cc=cunming.liang@intel.com \ --cc=david.marchand@redhat.com \ --cc=dev@dpdk.org \ --cc=jingjing.wu@intel.com \ --cc=miao.li@intel.com \ --cc=stephen@networkplumber.org \ --cc=thomas@monjalon.net \ --cc=xiuchun.lu@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
DPDK patches and discussions This inbox may be cloned and mirrored by anyone: git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \ dev@dpdk.org public-inbox-index dev Example config snippet for mirrors. Newsgroup available over NNTP: nntp://inbox.dpdk.org/inbox.dpdk.dev AGPL code for this site: git clone https://public-inbox.org/public-inbox.git