Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/66943/?format=api
http://patches.dpdk.org/api/patches/66943/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200319171907.60891-5-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": "<20200319171907.60891-5-ciara.power@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/20200319171907.60891-5-ciara.power@intel.com", "date": "2020-03-19T17:18:59", "name": "[04/12] telemetry: introduce new telemetry functionality", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "20b9eb590e826124341caab7f7ccae16a3221563", "submitter": { "id": 978, "url": "http://patches.dpdk.org/api/people/978/?format=api", "name": "Power, Ciara", "email": "ciara.power@intel.com" }, "delegate": { "id": 24651, "url": "http://patches.dpdk.org/api/users/24651/?format=api", "username": "dmarchand", "first_name": "David", "last_name": "Marchand", "email": "david.marchand@redhat.com" }, "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200319171907.60891-5-ciara.power@intel.com/mbox/", "series": [ { "id": 8987, "url": "http://patches.dpdk.org/api/series/8987/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8987", "date": "2020-03-19T17:18:55", "name": "update and simplify telemetry library.", "version": 1, "mbox": "http://patches.dpdk.org/series/8987/mbox/" } ], "comments": "http://patches.dpdk.org/api/patches/66943/comments/", "check": "fail", "checks": "http://patches.dpdk.org/api/patches/66943/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 15848A0583;\n\tThu, 19 Mar 2020 18:35:59 +0100 (CET)", "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B4A7A1C0AD;\n\tThu, 19 Mar 2020 18:35:02 +0100 (CET)", "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n by dpdk.org (Postfix) with ESMTP id 283541C07D\n for <dev@dpdk.org>; Thu, 19 Mar 2020 18:35:01 +0100 (CET)", "from orsmga004.jf.intel.com ([10.7.209.38])\n by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 19 Mar 2020 10:35:00 -0700", "from silpixa00399953.ir.intel.com (HELO\n silpixa00399953.ger.corp.intel.com) ([10.237.222.53])\n by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:34:58 -0700" ], "IronPort-SDR": [ "\n JwoTLHjsh6+V1OseFk+WaohS0fUQ++C1b99awvyx+4nkowEust+XQkTWFGyFybJ+uR8M3GDUwE\n 1i1X30+/4+ug==", "\n 2hHjiUkxc73fZ25jhuRVw2ta9W+mo/gQ70PKddWDbnasIR8CTMEfKDo3kCfKwA3WRVjppqIcgt\n JV2vd7X0TnFQ==" ], "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.70,572,1574150400\"; d=\"scan'208\";a=\"391872635\"", "From": "Ciara Power <ciara.power@intel.com>", "To": "kevin.laatz@intel.com", "Cc": "dev@dpdk.org, reshma.pattan@intel.com,\n Bruce Richardson <bruce.richardson@intel.com>,\n Ciara Power <ciara.power@intel.com>", "Date": "Thu, 19 Mar 2020 17:18:59 +0000", "Message-Id": "<20200319171907.60891-5-ciara.power@intel.com>", "X-Mailer": "git-send-email 2.17.1", "In-Reply-To": "<20200319171907.60891-1-ciara.power@intel.com>", "References": "<20200319171907.60891-1-ciara.power@intel.com>", "Subject": "[dpdk-dev] [PATCH 04/12] telemetry: introduce new telemetry\n\tfunctionality", "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 a new telemetry connection socket and handling\nfunctionality. Like the existing telemetry implementation (which is\nunaffected by this change) it uses a unix socket, but unlike the\nexisting one it does not have a fixed list of commands - instead\nlibraries or applications can register telemetry commands and callbacks\nto provide a full-extensible solution for all kinds of telemetry across\nDPDK.\n\nSigned-off-by: Bruce Richardson <bruce.richardson@intel.com>\nSigned-off-by: Ciara Power <ciara.power@intel.com>\n---\n lib/librte_telemetry/Makefile | 4 +\n lib/librte_telemetry/meson.build | 6 +-\n lib/librte_telemetry/rte_telemetry.c | 3 +\n lib/librte_telemetry/rte_telemetry.h | 59 ++++\n .../rte_telemetry_version.map | 2 +\n lib/librte_telemetry/telemetry.c | 257 ++++++++++++++++++\n 6 files changed, 330 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_telemetry/telemetry.c", "diff": "diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile\nindex 17e651c41..b34fe90d4 100644\n--- a/lib/librte_telemetry/Makefile\n+++ b/lib/librte_telemetry/Makefile\n@@ -10,6 +10,9 @@ CFLAGS += -O3\n CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)\n CFLAGS += -DALLOW_EXPERIMENTAL_API\n CFLAGS += -I$(RTE_SDK)/lib/librte_metrics/\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 \n LDLIBS += -lrte_eal\n LDLIBS += -lrte_metrics\n@@ -22,6 +25,7 @@ EXPORT_MAP := rte_telemetry_version.map\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) := rte_telemetry.c\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser.c\n SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser_test.c\n+SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c\n \n # export include files\n SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h\ndiff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build\nindex b34661ac1..49c947120 100644\n--- a/lib/librte_telemetry/meson.build\n+++ b/lib/librte_telemetry/meson.build\n@@ -1,7 +1,11 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2018 Intel Corporation\n \n-sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c')\n+includes = [global_inc]\n+includes += include_directories('../librte_eal/common/include/arch/' + arch_subdir)\n+\n+sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',\n+\t'telemetry.c')\n headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h')\n cflags += '-DALLOW_EXPERIMENTAL_API'\n includes += include_directories('../librte_metrics')\ndiff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c\nindex 2fb8ffe87..45b6d9d94 100644\n--- a/lib/librte_telemetry/rte_telemetry.c\n+++ b/lib/librte_telemetry/rte_telemetry.c\n@@ -503,6 +503,9 @@ rte_telemetry_init(void)\n \t\treturn -EPERM;\n \t}\n \n+\tif (rte_telemetry_new_init() != 0)\n+\t\treturn -1;\n+\n \treturn 0;\n }\n \ndiff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h\nindex aedb31859..060613117 100644\n--- a/lib/librte_telemetry/rte_telemetry.h\n+++ b/lib/librte_telemetry/rte_telemetry.h\n@@ -3,10 +3,13 @@\n */\n \n #include <stdint.h>\n+#include <rte_compat.h>\n \n #ifndef _RTE_TELEMETRY_H_\n #define _RTE_TELEMETRY_H_\n \n+#define TELEMETRY_MAX_CALLBACKS 64\n+\n /**\n * @file\n * RTE Telemetry\n@@ -16,6 +19,33 @@\n * a JSON encoded response containing telemetry data.\n ***/\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * This telemetry callback is used when registering a command.\n+ * It handles getting and formatting stats to be returned to telemetry when\n+ * requested. Stats up to buf_len in length are put in the buffer.\n+ *\n+ * @return\n+ * Length of buffer used on success.\n+ * @return\n+ * Negative integer on error.\n+ */\n+typedef int (*telemetry_cb)(const char *cmd, const char *params,\n+\t\tchar *buffer, int buf_len);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Used for handling data received over a telemetry socket.\n+ *\n+ * @return\n+ * Void.\n+ */\n+typedef void * (*handler)(void *sock_id);\n+\n /**\n * @warning\n * @b EXPERIMENTAL: this API may change without prior notice\n@@ -66,4 +96,33 @@ __rte_experimental\n int32_t\n rte_telemetry_selftest(void);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Used when registering a command and callback function with telemetry.\n+ *\n+ * @return\n+ * 0 on success.\n+ * @return\n+ * -EINVAL for invalid parameters failure.\n+ * @return\n+ * -ENOENT if max callbacks limit has been reached.\n+ */\n+__rte_experimental\n+int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Initialize new version of Telemetry.\n+ *\n+ * @return\n+ * 0 on success.\n+ * @return\n+ * -1 on failure.\n+ */\n+__rte_experimental\n+int rte_telemetry_new_init(void);\n #endif\ndiff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map\nindex a80058c59..831bbd59a 100644\n--- a/lib/librte_telemetry/rte_telemetry_version.map\n+++ b/lib/librte_telemetry/rte_telemetry_version.map\n@@ -6,6 +6,8 @@ EXPERIMENTAL {\n \trte_telemetry_parse;\n \trte_telemetry_selftest;\n \trte_telemetry_set_metrics_fns;\n+\trte_telemetry_new_init;\n+\trte_telemetry_register_cmd;\n \n \tlocal: *;\n };\ndiff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c\nnew file mode 100644\nindex 000000000..1ad784f59\n--- /dev/null\n+++ b/lib/librte_telemetry/telemetry.c\n@@ -0,0 +1,257 @@\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+/* we won't link against libbsd, so just always use DPDKs-specific strlcpy */\n+#undef RTE_USE_LIBBSD\n+#include <rte_string_fns.h>\n+#include <rte_common.h>\n+#include <rte_spinlock.h>\n+\n+#include \"rte_telemetry.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+static void *\n+client_handler(void *socket);\n+\n+struct cmd_callback {\n+\tchar cmd[MAX_CMD_LEN];\n+\ttelemetry_cb fn;\n+};\n+\n+struct socket {\n+\tint sock;\n+\tchar path[sizeof(((struct sockaddr_un *)0)->sun_path)];\n+\thandler fn;\n+};\n+static struct socket v2_socket; /* socket for v2 telemetry */\n+static char telemetry_log_error[1024]; /* Will contain error on init failure */\n+/* list of command callbacks, with one command registered by default */\n+static struct cmd_callback callbacks[TELEMETRY_MAX_CALLBACKS] = {\n+\t\t{ .cmd = \"/\", .fn = list_commands },\n+};\n+static int num_callbacks = 1; /* How many commands are registered */\n+/* Used when accessing or modifying list of command callbacks */\n+static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER;\n+\n+int\n+rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn)\n+{\n+\tint i = 0;\n+\n+\tif (strlen(cmd) >= MAX_CMD_LEN || fn == NULL || cmd[0] != '/')\n+\t\treturn -EINVAL;\n+\tif (num_callbacks >= TELEMETRY_MAX_CALLBACKS)\n+\t\treturn -ENOENT;\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\t/* Move elements to keep the list alphabetical */\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, ret, used = 0;\n+\n+\tused += strlcpy(buffer, \"[\", buf_len);\n+\tfor (i = 0; i < num_callbacks; i++) {\n+\t\tret = snprintf(buffer + used, buf_len - used, \"\\\"%s\\\",\",\n+\t\t\t\tcallbacks[i].cmd);\n+\t\tif (ret + used >= buf_len)\n+\t\t\tbreak;\n+\t\tused += ret;\n+\t}\n+\tbuffer[used - 1] = ']';\n+\treturn used;\n+}\n+\n+static void\n+perform_command(telemetry_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+\twhile (bytes > 0) {\n+\t\tconst char *cmd = strtok(buffer, \",\");\n+\t\tconst char *param = strtok(NULL, \",\");\n+\t\ttelemetry_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 *socket)\n+{\n+\twhile (1) {\n+\t\tpthread_t th;\n+\t\tstruct socket *s = (struct socket *)socket;\n+\t\tint s_accepted = accept(s->sock, NULL, NULL);\n+\t\tif (s_accepted < 0) {\n+\t\t\tsnprintf(telemetry_log_error,\n+\t\t\t\t\tsizeof(telemetry_log_error),\n+\t\t\t\t\t\"Error with accept, telemetry thread quitting\\n\");\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tpthread_create(&th, NULL, s->fn, (void *)(uintptr_t)s_accepted);\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+\tsnprintf(path, sizeof(path), \"%s/dpdk_telemetry.%d\",\n+\t\t\tstrlen(runtime_dir) ? runtime_dir : \"/tmp\", getpid());\n+\treturn path;\n+}\n+\n+static void\n+unlink_sockets(void)\n+{\n+\tif (v2_socket.path[0])\n+\t\tunlink(v2_socket.path);\n+}\n+\n+static int\n+create_socket(char *path)\n+{\n+\tint sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\tif (sock < 0) {\n+\t\tsnprintf(telemetry_log_error, sizeof(telemetry_log_error),\n+\t\t\t\t\"Error with socket creation, %s\",\n+\t\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\tstruct sockaddr_un sun = {.sun_family = AF_UNIX};\n+\tstrlcpy(sun.sun_path, path, sizeof(sun.sun_path));\n+\tunlink(sun.sun_path);\n+\tif (bind(sock, (void *) &sun, sizeof(sun)) < 0) {\n+\t\tsnprintf(telemetry_log_error, sizeof(telemetry_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(telemetry_log_error, sizeof(telemetry_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+\treturn sock;\n+\n+error:\n+\tclose(sock);\n+\tunlink_sockets();\n+\treturn -1;\n+}\n+\n+static int\n+telemetry_v2_init(const char *runtime_dir, const char **err_str)\n+{\n+\tpthread_t t_new;\n+\n+\tv2_socket.fn = client_handler;\n+\tif (strlcpy(v2_socket.path, get_socket_path(runtime_dir),\n+\t\t\tsizeof(v2_socket.path)) >= sizeof(v2_socket.path)) {\n+\t\tsnprintf(telemetry_log_error, sizeof(telemetry_log_error),\n+\t\t\t\t\"Error with socket binding, path too long\");\n+\t\treturn -1;\n+\t}\n+\n+\tv2_socket.sock = create_socket(v2_socket.path);\n+\tif (v2_socket.sock < 0) {\n+\t\t*err_str = telemetry_log_error;\n+\t\treturn -1;\n+\t}\n+\tpthread_create(&t_new, NULL, socket_listener, &v2_socket);\n+\tatexit(unlink_sockets);\n+\n+\treturn 0;\n+}\n+\n+int32_t\n+rte_telemetry_new_init(void)\n+{\n+\tconst char *error_str;\n+\tif (telemetry_v2_init(rte_eal_get_runtime_dir(), &error_str) != 0) {\n+\t\tprintf(\"Error initialising telemetry - %s\", error_str);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n", "prefixes": [ "04/12" ] }{ "id": 66943, "url": "