get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 63603,
    "url": "http://patches.dpdk.org/api/patches/63603/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20191205173128.64543-2-ciara.power@intel.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20191205173128.64543-2-ciara.power@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20191205173128.64543-2-ciara.power@intel.com",
    "date": "2019-12-05T17:31:23",
    "name": "[RFC,1/6] process-info: introduce process-info library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "c88dc75b0448c8127c70e1ff89aa22f776ac6ecb",
    "submitter": {
        "id": 978,
        "url": "http://patches.dpdk.org/api/people/978/?format=api",
        "name": "Power, Ciara",
        "email": "ciara.power@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20191205173128.64543-2-ciara.power@intel.com/mbox/",
    "series": [
        {
            "id": 7741,
            "url": "http://patches.dpdk.org/api/series/7741/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=7741",
            "date": "2019-12-05T17:31:22",
            "name": "replace telemetry with process_info",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/7741/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/63603/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/63603/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 8F87CA04F2;\n\tThu,  5 Dec 2019 18:34:18 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 249E11BF8D;\n\tThu,  5 Dec 2019 18:34:13 +0100 (CET)",
            "from mga04.intel.com (mga04.intel.com [192.55.52.120])\n by dpdk.org (Postfix) with ESMTP id 3FB9C1BF7D\n for <dev@dpdk.org>; Thu,  5 Dec 2019 18:34:10 +0100 (CET)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n 05 Dec 2019 09:34:09 -0800",
            "from silpixa00399953.ir.intel.com (HELO\n silpixa00399953.ger.corp.intel.com) ([10.237.222.53])\n by orsmga002.jf.intel.com with ESMTP; 05 Dec 2019 09:34:08 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.69,282,1571727600\"; d=\"scan'208\";a=\"223711800\"",
        "From": "Ciara Power <ciara.power@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Bruce Richardson <bruce.richardson@intel.com>,\n Ciara Power <ciara.power@intel.com>",
        "Date": "Thu,  5 Dec 2019 17:31:23 +0000",
        "Message-Id": "<20191205173128.64543-2-ciara.power@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20191205173128.64543-1-ciara.power@intel.com>",
        "References": "<20191205173128.64543-1-ciara.power@intel.com>",
        "Subject": "[dpdk-dev] [RFC 1/6] process-info: introduce process-info library",
        "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": "From: Bruce Richardson <bruce.richardson@intel.com>\n\nThis patch introduces the process_info library. The library does socket\nand connection management on a local unix socket, and allows the calling\nof callback functions on receipt of a message from a connected client.\n\nSigned-off-by: Bruce Richardson <bruce.richardson@intel.com>\nSigned-off-by: Ciara Power <ciara.power@intel.com>\n\n---\nThe library is not yet initialised to run, this will come in a later\npatch integrating with the EAL library.\n---\n config/common_base                            |   5 +\n lib/Makefile                                  |   1 +\n lib/librte_process_info/Makefile              |  26 ++\n lib/librte_process_info/meson.build           |   8 +\n lib/librte_process_info/process_info.c        | 231 ++++++++++++++++++\n lib/librte_process_info/rte_process_info.h    |  25 ++\n .../rte_process_info_version.map              |   6 +\n lib/meson.build                               |   1 +\n mk/rte.app.mk                                 |   1 +\n 9 files changed, 304 insertions(+)\n create mode 100644 lib/librte_process_info/Makefile\n create mode 100644 lib/librte_process_info/meson.build\n create mode 100644 lib/librte_process_info/process_info.c\n create mode 100644 lib/librte_process_info/rte_process_info.h\n create mode 100644 lib/librte_process_info/rte_process_info_version.map",
    "diff": "diff --git a/config/common_base b/config/common_base\nindex 7dec7ed45..5f49b934f 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -1093,3 +1093,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y\n # Compile the eventdev application\n #\n CONFIG_RTE_APP_EVENTDEV=y\n+\n+#\n+# Compile the process_info library\n+#\n+CONFIG_RTE_LIBRTE_PROCESS_INFO=y\ndiff --git a/lib/Makefile b/lib/Makefile\nindex 46b91ae1a..466cd04ef 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -4,6 +4,7 @@\n include $(RTE_SDK)/mk/rte.vars.mk\n \n DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs\n+DIRS-$(CONFIG_RTE_LIBRTE_PROCESS_INFO) += librte_process_info\n DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal\n DEPDIRS-librte_eal := librte_kvargs\n DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci\ndiff --git a/lib/librte_process_info/Makefile b/lib/librte_process_info/Makefile\nnew file mode 100644\nindex 000000000..67b9a9f20\n--- /dev/null\n+++ b/lib/librte_process_info/Makefile\n@@ -0,0 +1,26 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright 2019 Intel Corporation\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# library name\n+LIB = librte_process_info.a\n+\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/\n+CFLAGS += -pthread\n+LDLIBS += -pthread\n+\n+EXPORT_MAP := rte_process_info_version.map\n+\n+LIBABIVER := 1\n+\n+# all source are stored in SRCS-y\n+SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := process_info.c\n+\n+# install includes\n+INCS := rte_process_info.h\n+SYMLINK-y-include := $(INCS)\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_process_info/meson.build b/lib/librte_process_info/meson.build\nnew file mode 100644\nindex 000000000..42850e816\n--- /dev/null\n+++ b/lib/librte_process_info/meson.build\n@@ -0,0 +1,8 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+includes = [global_inc]\n+includes += include_directories('../librte_eal/common/include/arch/' + arch_subdir)\n+\n+sources = files('process_info.c')\n+headers = files('rte_process_info.h')\ndiff --git a/lib/librte_process_info/process_info.c b/lib/librte_process_info/process_info.c\nnew file mode 100644\nindex 000000000..3959e24fa\n--- /dev/null\n+++ b/lib/librte_process_info/process_info.c\n@@ -0,0 +1,231 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#include <unistd.h>\n+#include <pthread.h>\n+#include <sys/socket.h>\n+#include <sys/un.h>\n+#include <dlfcn.h>\n+\n+#include <rte_string_fns.h>\n+#include <rte_common.h>\n+#include <rte_spinlock.h>\n+\n+#include \"rte_process_info.h\"\n+\n+#define MAX_CMD_LEN 56\n+\n+static int\n+list_commands(const char *cmd __rte_unused, const char *params __rte_unused,\n+\t\tchar *buffer, int buf_len);\n+\n+struct cmd_callback {\n+\tchar cmd[MAX_CMD_LEN];\n+\tprocess_info_cb fn;\n+};\n+\n+static int sock = -1;\n+static struct sockaddr_un sun;\n+static char process_info_log_error[1024];\n+static struct cmd_callback callbacks[PROCESS_INFO_MAX_CALLBACKS] = {\n+\t\t{ .cmd = \"/\", .fn = list_commands },\n+};\n+static int num_callbacks = 1;\n+static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER;\n+\n+/* we won't link against libbsd, so just always use DPDKs-specific version */\n+#ifndef strlcpy\n+#define strlcpy rte_strlcpy\n+#endif\n+\n+int\n+rte_process_info_register(const char *cmd, process_info_cb fn)\n+{\n+\tint i = 0;\n+\n+\tif (strlen(cmd) >= MAX_CMD_LEN || fn == NULL)\n+\t\treturn -EINVAL;\n+\tif (num_callbacks >= PROCESS_INFO_MAX_CALLBACKS)\n+\t\treturn -ENOENT;\n+\tif (cmd[0] != '/')\n+\t\treturn -EINVAL;\n+\n+\trte_spinlock_lock(&callback_sl);\n+\twhile (i < num_callbacks && strcmp(cmd, callbacks[i].cmd) > 0)\n+\t\ti++;\n+\tif (i != num_callbacks)\n+\t\tmemmove(callbacks + i + 1, callbacks + i,\n+\t\t\tsizeof(struct cmd_callback) * (num_callbacks - i));\n+\n+\tstrlcpy(callbacks[i].cmd, cmd, MAX_CMD_LEN);\n+\tcallbacks[i].fn = fn;\n+\tnum_callbacks++;\n+\trte_spinlock_unlock(&callback_sl);\n+\n+\treturn 0;\n+}\n+\n+static int\n+list_commands(const char *cmd __rte_unused, const char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tint i, used = 0;\n+\n+\tused += strlcpy(buffer, \"[\", buf_len);\n+\tfor (i = 0; i < num_callbacks; i++)\n+\t\tused += snprintf(buffer + used, buf_len - used, \"\\\"%s\\\",\",\n+\t\t\t\tcallbacks[i].cmd);\n+\tbuffer[used - 1] = ']';\n+\treturn used;\n+}\n+\n+static void\n+perform_command(process_info_cb fn, const char *cmd, const char *param, int s)\n+{\n+\tchar out_buf[1024 * 12];\n+\n+\tint used = snprintf(out_buf,\n+\t\t\tsizeof(out_buf), \"{\\\"%s\\\":\", cmd);\n+\tint ret = fn(cmd, param, out_buf + used, sizeof(out_buf) - used);\n+\tif (ret < 0) {\n+\t\tused += strlcpy(out_buf + used, \"null}\\n\",\n+\t\t\t\tsizeof(out_buf) - used);\n+\t\tif (write(s, out_buf, used) < 0)\n+\t\t\tperror(\"Error writing to socket\");\n+\t\treturn;\n+\t}\n+\tused += ret;\n+\tused += strlcpy(out_buf + used, \"}\\n\", sizeof(out_buf) - used);\n+\tif (write(s, out_buf, used) < 0)\n+\t\tperror(\"Error writing to socket\");\n+}\n+\n+static int\n+unknown_command(const char *cmd __rte_unused, const char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\treturn snprintf(buffer, buf_len, \"null\");\n+}\n+\n+static void *\n+client_handler(void *sock_id)\n+{\n+\tint s = (int)(uintptr_t)sock_id;\n+\tchar buffer[1024];\n+\n+\t/* receive data is not null terminated */\n+\tint bytes = read(s, buffer, sizeof(buffer));\n+\tbuffer[bytes] = 0;\n+\n+\twhile (bytes > 0) {\n+\t\tconst char *cmd = strtok(buffer, \",\");\n+\t\tconst char *param = strtok(NULL, \",\");\n+\t\tprocess_info_cb fn = unknown_command;\n+\t\tint i;\n+\n+\t\trte_spinlock_lock(&callback_sl);\n+\t\tfor (i = 0; i < num_callbacks; i++)\n+\t\t\tif (strcmp(cmd, callbacks[i].cmd) == 0) {\n+\t\t\t\tfn = callbacks[i].fn;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\trte_spinlock_unlock(&callback_sl);\n+\t\tperform_command(fn, cmd, param, s);\n+\n+\t\tbytes = read(s, buffer, sizeof(buffer));\n+\t\tbuffer[bytes] = 0;\n+\t}\n+\tclose(s);\n+\treturn NULL;\n+}\n+\n+static void *\n+socket_listener(void *unused __rte_unused)\n+{\n+\twhile (1) {\n+\t\tpthread_t th;\n+\t\tint s = accept(sock, NULL, NULL);\n+\t\tif (s < 0) {\n+\t\t\tsnprintf(process_info_log_error,\n+\t\t\t\t\tsizeof(process_info_log_error),\n+\t\t\t\t\t\"Error with accept, process_info thread\"\n+\t\t\t\t\t\" quitting\\n\");\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tpthread_create(&th, NULL, client_handler, (void *)(uintptr_t)s);\n+\t\tpthread_detach(th);\n+\t}\n+\treturn NULL;\n+}\n+\n+static inline char *\n+get_socket_path(const char *runtime_dir)\n+{\n+\tstatic char path[PATH_MAX];\n+\n+\tif (strlen(runtime_dir) == 0)\n+\t\tsnprintf(path, sizeof(path), \"/tmp/dpdk_process_info.%d\",\n+\t\t\t\tgetpid());\n+\telse\n+\t\tsnprintf(path, sizeof(path), \"%s/process_info.%d\",\n+\t\t\t\truntime_dir, getpid());\n+\treturn path;\n+}\n+\n+static void\n+unlink_socket(void)\n+{\n+\tif (sun.sun_path[0])\n+\t\tunlink(sun.sun_path);\n+}\n+\n+int\n+rte_process_info_init(const char *runtime_dir, const char **err_str)\n+{\n+\tpthread_t t;\n+\n+\tsock = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\tif (sock < 0) {\n+\t\tsnprintf(process_info_log_error, sizeof(process_info_log_error),\n+\t\t\t\t\"Error with socket creation, %s\",\n+\t\t\t\tstrerror(errno));\n+\t\t*err_str = process_info_log_error;\n+\t\treturn -1;\n+\t}\n+\n+\tsun.sun_family = AF_UNIX;\n+\tif (strlcpy(sun.sun_path, get_socket_path(runtime_dir),\n+\t\t\tsizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {\n+\t\tsnprintf(process_info_log_error, sizeof(process_info_log_error),\n+\t\t\t\t\"Error with socket binding, path too long\");\n+\t\tgoto error;\n+\t}\n+\tif (bind(sock, (void *)&sun, sizeof(sun)) < 0) {\n+\t\tsnprintf(process_info_log_error, sizeof(process_info_log_error),\n+\t\t\t\t\"Error binding socket: %s\",\n+\t\t\t\tstrerror(errno));\n+\t\tsun.sun_path[0] = 0;\n+\t\tgoto error;\n+\t}\n+\n+\tif (listen(sock, 1) < 0) {\n+\t\tsnprintf(process_info_log_error, sizeof(process_info_log_error),\n+\t\t\t\t\"Error calling listen for socket: %s\",\n+\t\t\t\tstrerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\tpthread_create(&t, NULL, socket_listener, NULL);\n+\tatexit(unlink_socket);\n+\n+\treturn 0;\n+\n+error:\n+\tclose(sock);\n+\tunlink_socket();\n+\tsock = -1;\n+\t*err_str = process_info_log_error;\n+\treturn -1;\n+}\ndiff --git a/lib/librte_process_info/rte_process_info.h b/lib/librte_process_info/rte_process_info.h\nnew file mode 100644\nindex 000000000..d8d86ef57\n--- /dev/null\n+++ b/lib/librte_process_info/rte_process_info.h\n@@ -0,0 +1,25 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#ifndef _RTE_PROCESS_INFO_H_\n+#define _RTE_PROCESS_INFO_H_\n+\n+#include <stdint.h>\n+#include <rte_compat.h>\n+\n+#define PROCESS_INFO_MAX_CALLBACKS 64\n+\n+/* callback returns json data in buffer, up to buf_len long.\n+ * returns length of buffer used on success, negative on error.\n+ */\n+typedef int (*process_info_cb)(const char *cmd, const char *params,\n+\t\tchar *buffer, int buf_len);\n+\n+__rte_experimental\n+int rte_process_info_register(const char *cmd, process_info_cb fn);\n+\n+__rte_experimental\n+int rte_process_info_init(const char *runtime_dir, const char **err_str);\n+\n+#endif\ndiff --git a/lib/librte_process_info/rte_process_info_version.map b/lib/librte_process_info/rte_process_info_version.map\nnew file mode 100644\nindex 000000000..7e6f68d5a\n--- /dev/null\n+++ b/lib/librte_process_info/rte_process_info_version.map\n@@ -0,0 +1,6 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\t\trte_process_info_init;\n+\t\trte_process_info_register;\n+\tlocal: *;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex 6ceb5e756..fe11a02c8 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -10,6 +10,7 @@\n # core libs which are widely reused, so their deps are kept to a minimum.\n libraries = [\n \t'kvargs', # eal depends on kvargs\n+\t'process_info', # basic info querying capability about dpdk processes\n \t'eal', # everything depends on eal\n \t'ring', 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core\n \t'cmdline',\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 05ea034b9..3c61cbb67 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -77,6 +77,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_HASH)           += -lrte_hash\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMBER)         += -lrte_member\n _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST)          += -lrte_vhost\n _LDLIBS-$(CONFIG_RTE_LIBRTE_KVARGS)         += -lrte_kvargs\n+_LDLIBS-$(CONFIG_RTE_LIBRTE_PROCESS_INFO)   += -lrte_process_info\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF)           += -lrte_mbuf\n _LDLIBS-$(CONFIG_RTE_LIBRTE_NET)            += -lrte_net\n _LDLIBS-$(CONFIG_RTE_LIBRTE_ETHER)          += -lrte_ethdev\n",
    "prefixes": [
        "RFC",
        "1/6"
    ]
}