get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/85395/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 85395,
    "url": "https://patches.dpdk.org/api/patches/85395/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20201218073851.93609-7-chenbo.xia@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20201218073851.93609-7-chenbo.xia@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201218073851.93609-7-chenbo.xia@intel.com",
    "date": "2020-12-18T07:38:48",
    "name": "[6/9] vfio_user: add client APIs of device attach/detach",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "a1a8ea7359337d64920105b7ec4528b2f2e16dd5",
    "submitter": {
        "id": 1276,
        "url": "https://patches.dpdk.org/api/people/1276/?format=api",
        "name": "Chenbo Xia",
        "email": "chenbo.xia@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20201218073851.93609-7-chenbo.xia@intel.com/mbox/",
    "series": [
        {
            "id": 14361,
            "url": "https://patches.dpdk.org/api/series/14361/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14361",
            "date": "2020-12-18T07:38:42",
            "name": "Introduce vfio-user library",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/14361/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/85395/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/85395/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 20FD1A09F6;\n\tFri, 18 Dec 2020 08:56:19 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 18A2CCA6E;\n\tFri, 18 Dec 2020 08:54:31 +0100 (CET)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n by dpdk.org (Postfix) with ESMTP id F3C13CAB6\n for <dev@dpdk.org>; Fri, 18 Dec 2020 08:54:29 +0100 (CET)",
            "from fmsmga008.fm.intel.com ([10.253.24.58])\n by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 17 Dec 2020 23:54:29 -0800",
            "from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123])\n by fmsmga008.fm.intel.com with ESMTP; 17 Dec 2020 23:54:26 -0800"
        ],
        "IronPort-SDR": [
            "\n kmZzsObGkg2g1GXqXsYptxO188F8VymJp7U9Bv2OS+Bsge6Qll5BhLtpMsxrXkgNvIssrd0+5f\n Ggic49pRBEeQ==",
            "\n YwUA+YdVrjVHWKFMStXHqhV915aAAVY3NOsjwHm0qriTTpSOaNxjVRxC+H+PlJoS31zrPwAN3r\n sCUSmEB1Gj1A=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9838\"; a=\"260126178\"",
            "E=Sophos;i=\"5.78,429,1599548400\"; d=\"scan'208\";a=\"260126178\"",
            "E=Sophos;i=\"5.78,429,1599548400\"; d=\"scan'208\";a=\"340270408\""
        ],
        "X-ExtLoop1": "1",
        "From": "Chenbo Xia <chenbo.xia@intel.com>",
        "To": "dev@dpdk.org,\n\tthomas@monjalon.net,\n\tdavid.marchand@redhat.com",
        "Cc": "stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com,\n miao.li@intel.com, jingjing.wu@intel.com",
        "Date": "Fri, 18 Dec 2020 15:38:48 +0800",
        "Message-Id": "<20201218073851.93609-7-chenbo.xia@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20201218073851.93609-1-chenbo.xia@intel.com>",
        "References": "<20201218073851.93609-1-chenbo.xia@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 6/9] vfio_user: add client APIs of device\n\tattach/detach",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch implements two APIs, rte_vfio_user_attach_dev() and\nrte_vfio_user_detach_dev() for vfio-user client to connect to\nor disconnect from a vfio-user device on server side.\n\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\nSigned-off-by: Xiuchun Lu <xiuchun.lu@intel.com>\n---\n lib/librte_vfio_user/meson.build        |   3 +-\n lib/librte_vfio_user/rte_vfio_user.h    |  30 +++\n lib/librte_vfio_user/version.map        |   2 +\n lib/librte_vfio_user/vfio_user_client.c | 279 ++++++++++++++++++++++++\n lib/librte_vfio_user/vfio_user_client.h |  25 +++\n 5 files changed, 338 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_vfio_user/vfio_user_client.c\n create mode 100644 lib/librte_vfio_user/vfio_user_client.h",
    "diff": "diff --git a/lib/librte_vfio_user/meson.build b/lib/librte_vfio_user/meson.build\nindex b7363f61c6..5761f0edd1 100644\n--- a/lib/librte_vfio_user/meson.build\n+++ b/lib/librte_vfio_user/meson.build\n@@ -6,5 +6,6 @@ if not is_linux\n \treason = 'only supported on Linux'\n endif\n \n-sources = files('vfio_user_base.c', 'vfio_user_server.c')\n+sources = files('vfio_user_base.c', 'vfio_user_server.c',\n+\t'vfio_user_client.c')\n headers = files('rte_vfio_user.h')\ndiff --git a/lib/librte_vfio_user/rte_vfio_user.h b/lib/librte_vfio_user/rte_vfio_user.h\nindex 6c12b0b6ed..b09d83e224 100644\n--- a/lib/librte_vfio_user/rte_vfio_user.h\n+++ b/lib/librte_vfio_user/rte_vfio_user.h\n@@ -225,4 +225,34 @@ __rte_experimental\n int rte_vfio_user_set_irq_info(const char *sock_addr,\n \tstruct rte_vfio_user_irq_info *irq);\n \n+/**\n+ *  Below APIs are for vfio-user client (device consumer) to use:\n+ *\t*rte_vfio_user_attach_dev\n+ *\t*rte_vfio_user_detach_dev\n+ */\n+\n+/**\n+ * Attach to a vfio-user device.\n+ *\n+ * @param sock_addr\n+ *   Unix domain socket address\n+ * @return\n+ *   - >=0: Success, device attached. Returned value is the device ID.\n+ *   - <0: Failure on device attach\n+ */\n+__rte_experimental\n+int rte_vfio_user_attach_dev(const char *sock_addr);\n+\n+/**\n+ * Detach from a vfio-user device.\n+ *\n+ * @param dev_id\n+ *   Device ID of the vfio-user device\n+ * @return\n+ *   - 0: Success, device detached\n+ *   - <0: Failure on device detach\n+ */\n+__rte_experimental\n+int rte_vfio_user_detach_dev(int dev_id);\n+\n #endif\ndiff --git a/lib/librte_vfio_user/version.map b/lib/librte_vfio_user/version.map\nindex 621a51a9fc..a0cda2b49c 100644\n--- a/lib/librte_vfio_user/version.map\n+++ b/lib/librte_vfio_user/version.map\n@@ -10,6 +10,8 @@ EXPERIMENTAL {\n \trte_vfio_user_set_dev_info;\n \trte_vfio_user_set_reg_info;\n \trte_vfio_user_set_irq_info;\n+\trte_vfio_user_attach_dev;\n+\trte_vfio_user_detach_dev;\n \n \tlocal: *;\n };\ndiff --git a/lib/librte_vfio_user/vfio_user_client.c b/lib/librte_vfio_user/vfio_user_client.c\nnew file mode 100644\nindex 0000000000..85b2e8cb46\n--- /dev/null\n+++ b/lib/librte_vfio_user/vfio_user_client.c\n@@ -0,0 +1,279 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <unistd.h>\n+#include <string.h>\n+#include <pthread.h>\n+#include <fcntl.h>\n+#include <sys/un.h>\n+#include <sys/socket.h>\n+\n+#include \"vfio_user_client.h\"\n+#include \"rte_vfio_user.h\"\n+\n+#define REPLY_USEC 1000\n+#define RECV_MAX_TRY 50\n+\n+static struct vfio_user_client_devs vfio_client_devs = {\n+\t.cl_num = 0,\n+\t.mutex = PTHREAD_MUTEX_INITIALIZER,\n+};\n+\n+/* Check if the sock_addr exists. If not, alloc and return index */\n+static int vfio_user_client_allocate(const char *sock_addr)\n+{\n+\tuint32_t i, count = 0;\n+\tint index = -1;\n+\n+\tif (sock_addr == NULL)\n+\t\treturn -1;\n+\n+\tif (vfio_client_devs.cl_num == 0)\n+\t\treturn 0;\n+\n+\tfor (i = 0; i < MAX_VFIO_USER_CLIENT; i++) {\n+\t\tstruct vfio_user_client *cl = vfio_client_devs.cl[i];\n+\n+\t\tif (!cl) {\n+\t\t\tif (index == -1)\n+\t\t\t\tindex = i;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(cl->sock.sock_addr, sock_addr))\n+\t\t\treturn -1;\n+\n+\t\tcount++;\n+\t\tif (count == vfio_client_devs.cl_num)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn index;\n+}\n+\n+static struct vfio_user_client *\n+vfio_user_client_create_dev(const char *sock_addr)\n+{\n+\tstruct vfio_user_client *cl;\n+\tstruct vfio_user_socket *sock;\n+\tint fd, idx;\n+\tstruct sockaddr_un un;\n+\n+\tpthread_mutex_lock(&vfio_client_devs.mutex);\n+\tif (vfio_client_devs.cl_num == MAX_VFIO_USER_CLIENT) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to create client:\"\n+\t\t\t\" client num reaches max\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tidx = vfio_user_client_allocate(sock_addr);\n+\tif (idx < 0) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to create client:\"\n+\t\t\t\"socket addr exists\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tcl = malloc(sizeof(*cl));\n+\tif (!cl) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to alloc client\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tsock = &cl->sock;\n+\tsock->sock_addr = strdup(sock_addr);\n+\tif (!sock->sock_addr) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to copy sock_addr\\n\");\n+\t\tgoto err_dup;\n+\t}\n+\n+\tfd = socket(AF_UNIX, SOCK_STREAM, 0);\n+\tif (fd < 0) {\n+\t\tVFIO_USER_LOG(ERR, \"Client failed to create socket: %s\\n\",\n+\t\t\tstrerror(errno));\n+\t\tgoto err_sock;\n+\t}\n+\n+\tif (fcntl(fd, F_SETFL, O_NONBLOCK)) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to set nonblocking mode for client \"\n+\t\t\t\"socket, fd: %d (%s)\\n\", fd, strerror(errno));\n+\t\tgoto err_ctl;\n+\t}\n+\n+\tmemset(&un, 0, sizeof(un));\n+\tun.sun_family = AF_UNIX;\n+\tstrncpy(un.sun_path, sock->sock_addr, sizeof(un.sun_path));\n+\tun.sun_path[sizeof(un.sun_path) - 1] = '\\0';\n+\n+\tif (connect(fd, &un, sizeof(un)) < 0) {\n+\t\tVFIO_USER_LOG(ERR, \"Client connect error, %s\\n\",\n+\t\t\tstrerror(errno));\n+\t\tgoto err_ctl;\n+\t}\n+\n+\tsock->sock_fd = fd;\n+\tsock->dev_id = idx;\n+\n+\tvfio_client_devs.cl[idx] = cl;\n+\tvfio_client_devs.cl_num++;\n+\n+\tpthread_mutex_unlock(&vfio_client_devs.mutex);\n+\n+\treturn cl;\n+\n+err_ctl:\n+\tclose(fd);\n+err_sock:\n+\tfree(sock->sock_addr);\n+err_dup:\n+\tfree(sock);\n+err:\n+\tpthread_mutex_unlock(&vfio_client_devs.mutex);\n+\treturn NULL;\n+}\n+\n+static int vfio_user_client_destroy_dev(int dev_id)\n+{\n+\tstruct vfio_user_client *cl;\n+\tstruct vfio_user_socket *sock;\n+\tint ret = 0;\n+\n+\tpthread_mutex_lock(&vfio_client_devs.mutex);\n+\tif (vfio_client_devs.cl_num == 0) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to destroy client:\"\n+\t\t\t\" no client exists\\n\");\n+\t\tret = -EINVAL;\n+\t\tgoto err;\n+\t}\n+\n+\tcl = vfio_client_devs.cl[dev_id];\n+\tif (!cl) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to destroy client:\"\n+\t\t\t\" wrong device ID(%d)\\n\", dev_id);\n+\t\tret = -EINVAL;\n+\t\tgoto err;\n+\t}\n+\n+\tsock = &cl->sock;\n+\tfree(sock->sock_addr);\n+\tclose(sock->sock_fd);\n+\n+\tfree(cl);\n+\tvfio_client_devs.cl[dev_id] = NULL;\n+\tvfio_client_devs.cl_num--;\n+\n+err:\n+\tpthread_mutex_unlock(&vfio_client_devs.mutex);\n+\treturn ret;\n+}\n+\n+static inline void vfio_user_client_fill_hdr(VFIO_USER_MSG *msg, uint16_t cmd,\n+\tuint32_t sz)\n+{\n+\tstatic uint16_t\tmsg_id;\n+\n+\tmsg->msg_id = msg_id++;\n+\tmsg->cmd = cmd;\n+\tmsg->size = sz;\n+\tmsg->flags = VFIO_USER_TYPE_CMD;\n+\tmsg->err = 0;\n+}\n+\n+static int vfio_user_client_send_recv(int sock_fd, VFIO_USER_MSG *msg)\n+{\n+\tuint16_t cmd = msg->cmd;\n+\tuint16_t id = msg->msg_id;\n+\tuint8_t try_recv = 0;\n+\tint ret;\n+\n+\tret = vfio_user_send_msg(sock_fd, msg);\n+\tif (ret < 0) {\n+\t\tVFIO_USER_LOG(ERR, \"Send error for %s\\n\",\n+\t\t\tvfio_user_msg_str[cmd]);\n+\t\treturn -1;\n+\t}\n+\n+\tVFIO_USER_LOG(INFO, \"Send request %s\\n\", vfio_user_msg_str[cmd]);\n+\n+\tmemset(msg, 0, sizeof(*msg));\n+\n+\twhile (try_recv < RECV_MAX_TRY) {\n+\t\tret = vfio_user_recv_msg(sock_fd, msg);\n+\t\tif (!ret) {\n+\t\t\tVFIO_USER_LOG(ERR, \"Peer closed\\n\");\n+\t\t\treturn -1;\n+\t\t} else if (ret > 0) {\n+\t\t\tif (id != msg->msg_id)\n+\t\t\t\tcontinue;\n+\t\t\telse\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tusleep(REPLY_USEC);\n+\t\ttry_recv++;\n+\t}\n+\n+\tif (cmd != msg->cmd) {\n+\t\tVFIO_USER_LOG(ERR, \"Request and reply mismatch\\n\");\n+\t\tret = -1;\n+\t} else\n+\t\tret = 0;\n+\n+\tVFIO_USER_LOG(INFO, \"Recv reply %s\\n\", vfio_user_msg_str[cmd]);\n+\n+\treturn ret;\n+}\n+\n+int rte_vfio_user_attach_dev(const char *sock_addr)\n+{\n+\tstruct vfio_user_client *dev;\n+\tVFIO_USER_MSG msg;\n+\tuint32_t sz = VFIO_USER_MSG_HDR_SIZE + sizeof(struct vfio_user_version)\n+\t\t- VFIO_USER_MAX_VERSION_DATA;\n+\tstruct vfio_user_version *ver = &msg.payload.ver;\n+\tint ret;\n+\n+\tif (!sock_addr)\n+\t\treturn -EINVAL;\n+\n+\tdev = vfio_user_client_create_dev(sock_addr);\n+\tif (!dev) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to attach the device \"\n+\t\t\t\"with sock_addr %s\\n\", sock_addr);\n+\t\treturn -1;\n+\t}\n+\n+\tmemset(&msg, 0, sizeof(VFIO_USER_MSG));\n+\tvfio_user_client_fill_hdr(&msg, VFIO_USER_VERSION, sz);\n+\tver->major = VFIO_USER_VERSION_MAJOR;\n+\tver->minor = VFIO_USER_VERSION_MINOR;\n+\n+\tret = vfio_user_client_send_recv(dev->sock.sock_fd, &msg);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (msg.flags & VFIO_USER_ERROR) {\n+\t\tVFIO_USER_LOG(ERR, \"Failed to negotiate version: %s\\n\",\n+\t\t\t\tmsg.err ? strerror(msg.err) : \"Unknown error\");\n+\t\treturn msg.err ? -(int)msg.err : -1;\n+\t}\n+\n+\tif (vfio_user_check_msg_fdnum(&msg, 0) != 0)\n+\t\treturn -1;\n+\n+\treturn dev->sock.dev_id;\n+}\n+\n+int rte_vfio_user_detach_dev(int dev_id)\n+{\n+\tint ret;\n+\n+\tif (dev_id < 0)\n+\t\treturn -EINVAL;\n+\n+\tret = vfio_user_client_destroy_dev(dev_id);\n+\tif (ret)\n+\t\tVFIO_USER_LOG(ERR, \"Failed to detach the device (ID:%d)\\n\",\n+\t\t\tdev_id);\n+\n+\treturn ret;\n+}\ndiff --git a/lib/librte_vfio_user/vfio_user_client.h b/lib/librte_vfio_user/vfio_user_client.h\nnew file mode 100644\nindex 0000000000..d489e62037\n--- /dev/null\n+++ b/lib/librte_vfio_user/vfio_user_client.h\n@@ -0,0 +1,25 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _VFIO_USER_CLIENT_H\n+#define _VFIO_USER_CLIENT_H\n+\n+#include <stdint.h>\n+\n+#include \"vfio_user_base.h\"\n+\n+#define MAX_VFIO_USER_CLIENT 1024\n+\n+struct vfio_user_client {\n+\tstruct vfio_user_socket sock;\n+\tuint8_t rsvd[16];\t/* Reserved for future use */\n+};\n+\n+struct vfio_user_client_devs {\n+\tstruct vfio_user_client *cl[MAX_VFIO_USER_CLIENT];\n+\tuint32_t cl_num;\n+\tpthread_mutex_t mutex;\n+};\n+\n+#endif\n",
    "prefixes": [
        "6/9"
    ]
}