get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 66948,
    "url": "http://patches.dpdk.org/api/patches/66948/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200319171907.60891-10-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-10-ciara.power@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200319171907.60891-10-ciara.power@intel.com",
    "date": "2020-03-19T17:19:04",
    "name": "[09/12] telemetry: introduce telemetry backward compatibility",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8e85e1215b6282e5ea5da55cebf849527418c1e2",
    "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-10-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/66948/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/66948/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 0DA89A0583;\n\tThu, 19 Mar 2020 18:37:09 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id E424A1C0CF;\n\tThu, 19 Mar 2020 18:35:12 +0100 (CET)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n by dpdk.org (Postfix) with ESMTP id 606201C0C4\n for <dev@dpdk.org>; Thu, 19 Mar 2020 18:35:10 +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:10 -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:35:08 -0700"
        ],
        "IronPort-SDR": [
            "\n emuATZEshyZuI/pwD5ngESu8wwsLIOtSyUOodsujtoImi7+eUqIxdM/yjSCWNVMuivuQGE7vYH\n OloA6QfNNDdw==",
            "\n y5rYNiXO+89EMfmtQr0NMOG2RpmvMlI6zvqs1o0epzmmU7N+u7R6CECvNDeOkD2xSEAWsq3o7/\n HL9g4XYhtnVA=="
        ],
        "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=\"391872719\"",
        "From": "Ciara Power <ciara.power@intel.com>",
        "To": "kevin.laatz@intel.com",
        "Cc": "dev@dpdk.org, reshma.pattan@intel.com, Ciara Power <ciara.power@intel.com>",
        "Date": "Thu, 19 Mar 2020 17:19:04 +0000",
        "Message-Id": "<20200319171907.60891-10-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 09/12] telemetry: introduce telemetry backward\n\tcompatibility",
        "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": "The new telemetry will now open a socket using the old telemetry path,\nto ensure backward compatibility. This is not yet initialised, as it\nwould clash with the existing telemetry, to be removed in a later patch.\nThis means that both old and new telemetry socket interfaces are\nhandled in a common way.\n\nSigned-off-by: Ciara Power <ciara.power@intel.com>\n---\n lib/librte_metrics/Makefile                   |   2 +-\n lib/librte_metrics/meson.build                |   1 +\n lib/librte_metrics/rte_metrics_telemetry.c    | 113 +++++++++\n lib/librte_telemetry/Makefile                 |   1 +\n lib/librte_telemetry/meson.build              |   4 +-\n lib/librte_telemetry/rte_telemetry.h          |   1 +\n lib/librte_telemetry/rte_telemetry_legacy.h   |  48 ++++\n .../rte_telemetry_version.map                 |   2 +\n lib/librte_telemetry/telemetry.c              |  32 +++\n lib/librte_telemetry/telemetry_legacy.c       | 226 ++++++++++++++++++\n 10 files changed, 427 insertions(+), 3 deletions(-)\n create mode 100644 lib/librte_telemetry/rte_telemetry_legacy.h\n create mode 100644 lib/librte_telemetry/telemetry_legacy.c",
    "diff": "diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile\nindex fa762ba37..c8b9b143d 100644\n--- a/lib/librte_metrics/Makefile\n+++ b/lib/librte_metrics/Makefile\n@@ -21,7 +21,7 @@ ifneq ($(JANSSON_LINK),)\n SRCS-y += rte_metrics_telemetry.c\n SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics_telemetry.h\n \n-LDLIBS += -lrte_ethdev\n+LDLIBS += -lrte_ethdev -lrte_telemetry\n LDLIBS += $(JANSSON_LINK)\n \n CFLAGS += $(JANSSON_CFLAGS)\ndiff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build\nindex d116857e2..1a7cbf29c 100644\n--- a/lib/librte_metrics/meson.build\n+++ b/lib/librte_metrics/meson.build\n@@ -11,4 +11,5 @@ if jansson.found()\n \tsources += files('rte_metrics_telemetry.c')\n \theaders = files('rte_metrics_telemetry.h')\n \tdeps += ['ethdev', 'telemetry']\n+\tincludes += include_directories('../librte_telemetry')\n endif\ndiff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c\nindex 31d505551..49de9d74b 100644\n--- a/lib/librte_metrics/rte_metrics_telemetry.c\n+++ b/lib/librte_metrics/rte_metrics_telemetry.c\n@@ -8,6 +8,7 @@\n #include <rte_string_fns.h>\n #ifdef RTE_LIBRTE_TELEMETRY\n #include <rte_telemetry_internal.h>\n+#include <rte_telemetry_legacy.h>\n #endif\n \n #include \"rte_metrics.h\"\n@@ -417,6 +418,112 @@ rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data)\n \treturn 0;\n }\n \n+static int\n+rte_metrics_tel_initial_metrics_setup(void)\n+{\n+\tint ret;\n+\trte_metrics_init(rte_socket_id());\n+\n+\tif (!tel_met_data.metrics_register_done) {\n+\t\tret = rte_metrics_tel_reg_all_ethdev(\n+\t\t\t&tel_met_data.metrics_register_done,\n+\t\t\ttel_met_data.reg_index);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+handle_ports_all_stats_values(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tstruct telemetry_encode_param ep;\n+\tint ret, used = 0;\n+\tchar *json_buffer = NULL;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tmemset(&ep, 0, sizeof(ep));\n+\tret = rte_metrics_tel_get_port_stats_ids(&ep);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = rte_metrics_tel_get_ports_stats_json(&ep, tel_met_data.reg_index,\n+\t\t\t&json_buffer);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n+static int\n+handle_global_stats_values(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tchar *json_buffer = NULL;\n+\tstruct telemetry_encode_param ep = { .type = GLOBAL_STATS };\n+\tint ret, used = 0;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = rte_metrics_tel_encode_json_format(&ep, &json_buffer);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"JSON encode function failed\");\n+\t\treturn ret;\n+\t}\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n+static int\n+handle_ports_stats_values_by_name(const char *cmd __rte_unused,\n+\t\tconst char *params,\n+\t\tchar *buffer, int buf_len)\n+{\n+\tchar *json_buffer = NULL;\n+\tstruct telemetry_encode_param ep;\n+\tint ret, used = 0;\n+\tjson_t *data;\n+\tjson_error_t error;\n+\n+\tret = rte_metrics_tel_initial_metrics_setup();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tdata = json_loads(params, 0, &error);\n+\tif (!data) {\n+\t\tMETRICS_LOG_WARN(\"Could not load JSON object from data passed in : %s\",\n+\t\t\t\terror.text);\n+\t\treturn -EPERM;\n+\t} else if (!json_is_object(data)) {\n+\t\tMETRICS_LOG_WARN(\"JSON Request data is not a JSON object\");\n+\t\tjson_decref(data);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = rte_metrics_tel_extract_data(&ep, data);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"Extract data function failed\");\n+\t\treturn ret;\n+\t}\n+\n+\tret = rte_metrics_tel_encode_json_format(&ep, &json_buffer);\n+\tif (ret < 0) {\n+\t\tMETRICS_LOG_ERR(\"JSON encode function failed\");\n+\t\treturn ret;\n+\t}\n+\tused += strlcpy(buffer, json_buffer, buf_len);\n+\treturn used;\n+}\n+\n RTE_INIT(metrics_ctor)\n {\n #ifdef RTE_LIBRTE_TELEMETRY\n@@ -428,6 +535,12 @@ RTE_INIT(metrics_ctor)\n \t\t.extract_data = rte_metrics_tel_extract_data\n \t};\n \trte_telemetry_set_metrics_fns(&fns); /* assign them to telemetry lib */\n+\trte_telemetry_legacy_register(\"ports_all_stat_values\", DATA_NOT_REQ,\n+\t\t\thandle_ports_all_stats_values);\n+\trte_telemetry_legacy_register(\"global_stat_values\", DATA_NOT_REQ,\n+\t\t\thandle_global_stats_values);\n+\trte_telemetry_legacy_register(\"ports_stats_values_by_name\", DATA_REQ,\n+\t\t\thandle_ports_stats_values_by_name);\n #endif\n \tmetrics_log_level = rte_log_register(\"lib.metrics\");\n \tif (metrics_log_level >= 0)\ndiff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile\nindex b34fe90d4..e2af886b6 100644\n--- a/lib/librte_telemetry/Makefile\n+++ b/lib/librte_telemetry/Makefile\n@@ -26,6 +26,7 @@ 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+SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry_legacy.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 49c947120..caca32b2e 100644\n--- a/lib/librte_telemetry/meson.build\n+++ b/lib/librte_telemetry/meson.build\n@@ -4,8 +4,8 @@\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+sources = files('rte_telemetry.c','rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',\n+\t'telemetry.c', 'telemetry_legacy.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.h b/lib/librte_telemetry/rte_telemetry.h\nindex 060613117..13ce235cb 100644\n--- a/lib/librte_telemetry/rte_telemetry.h\n+++ b/lib/librte_telemetry/rte_telemetry.h\n@@ -125,4 +125,5 @@ int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn);\n  */\n __rte_experimental\n int rte_telemetry_new_init(void);\n+\n #endif\ndiff --git a/lib/librte_telemetry/rte_telemetry_legacy.h b/lib/librte_telemetry/rte_telemetry_legacy.h\nnew file mode 100644\nindex 000000000..66c4981b3\n--- /dev/null\n+++ b/lib/librte_telemetry/rte_telemetry_legacy.h\n@@ -0,0 +1,48 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _RTE_TELEMETRY_LEGACY_H_\n+#define _RTE_TELEMETRY_LEGACY_H_\n+\n+#include <rte_compat.h>\n+#include \"rte_telemetry.h\"\n+\n+enum rte_telemetry_legacy_data_req {\n+\tDATA_NOT_REQ = 0,\n+\tDATA_REQ\n+};\n+\n+extern int num_legacy_callbacks;\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Used for handling data received over the legacy telemetry socket.\n+ *\n+ * @return\n+ * Void.\n+ */\n+void *legacy_client_handler(void *sock_id);\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\n+ * telemetry legacy support.\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_legacy_register(const char *cmd,\n+\t\tenum rte_telemetry_legacy_data_req data_req,\n+\t\ttelemetry_cb fn);\n+\n+#endif\ndiff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map\nindex 831bbd59a..2db0a5a44 100644\n--- a/lib/librte_telemetry/rte_telemetry_version.map\n+++ b/lib/librte_telemetry/rte_telemetry_version.map\n@@ -8,6 +8,8 @@ EXPERIMENTAL {\n \trte_telemetry_set_metrics_fns;\n \trte_telemetry_new_init;\n \trte_telemetry_register_cmd;\n+\trte_telemetry_legacy_init;\n+\trte_telemetry_legacy_register;\n \n \tlocal: *;\n };\ndiff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c\nindex 1ad784f59..e77672b48 100644\n--- a/lib/librte_telemetry/telemetry.c\n+++ b/lib/librte_telemetry/telemetry.c\n@@ -15,6 +15,7 @@\n #include <rte_spinlock.h>\n \n #include \"rte_telemetry.h\"\n+#include \"rte_telemetry_legacy.h\"\n \n #define MAX_CMD_LEN 56\n \n@@ -36,6 +37,7 @@ struct socket {\n \thandler fn;\n };\n static struct socket v2_socket; /* socket for v2 telemetry */\n+static struct socket v1_socket; /* socket for v1 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@@ -182,6 +184,8 @@ unlink_sockets(void)\n {\n \tif (v2_socket.path[0])\n \t\tunlink(v2_socket.path);\n+\tif (v1_socket.path[0])\n+\t\tunlink(v1_socket.path);\n }\n \n static int\n@@ -221,6 +225,34 @@ create_socket(char *path)\n \treturn -1;\n }\n \n+static int __rte_unused /* will be used in future commit */\n+telemetry_legacy_init(const char *runtime_dir, const char **err_str)\n+{\n+\tpthread_t t_old;\n+\n+\tif (num_legacy_callbacks == 1) {\n+\t\t*err_str = \"No legacy callbacks - error creating legacy socket\";\n+\t\treturn -1;\n+\t}\n+\n+\tv1_socket.fn = legacy_client_handler;\n+\tif ((size_t) snprintf(v1_socket.path, sizeof(v1_socket.path),\n+\t\t\t\"%s/telemetry\", runtime_dir)\n+\t\t\t>= sizeof(v1_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+\tv1_socket.sock = create_socket(v1_socket.path);\n+\tif (v1_socket.sock < 0) {\n+\t\t*err_str = telemetry_log_error;\n+\t\treturn -1;\n+\t}\n+\tpthread_create(&t_old, NULL, socket_listener, &v1_socket);\n+\n+\treturn 0;\n+}\n+\n static int\n telemetry_v2_init(const char *runtime_dir, const char **err_str)\n {\ndiff --git a/lib/librte_telemetry/telemetry_legacy.c b/lib/librte_telemetry/telemetry_legacy.c\nnew file mode 100644\nindex 000000000..e7c01525b\n--- /dev/null\n+++ b/lib/librte_telemetry/telemetry_legacy.c\n@@ -0,0 +1,226 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <unistd.h>\n+#include <sys/socket.h>\n+#include <sys/un.h>\n+#include <pthread.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_legacy.h\"\n+\n+#define MAX_LEN 128\n+#define BUF_SIZE 1024\n+#define CLIENTS_UNREG_ACTION \"\\\"action\\\":2\"\n+#define CLIENTS_CMD \"\\\"command\\\":\\\"clients\\\"\"\n+#define CLIENTS_DATA \"\\\"data\\\":{\\\"client_path\\\":\\\"\"\n+#define STATS_ACTION \"\\\"action\\\":0\"\n+#define DATA_REQ_LABEL \"\\\"data\\\":\"\n+#define TELEMETRY_LEGACY_MAX_CALLBACKS 4\n+\n+\n+static int\n+register_client(const char *cmd __rte_unused,\n+\t\tconst char *params __rte_unused,\n+\t\tchar *buffer, int buf_len);\n+\n+struct json_command {\n+\tchar action[MAX_LEN];\n+\tchar cmd[MAX_LEN];\n+\tchar data[MAX_LEN];\n+\ttelemetry_cb fn;\n+\n+};\n+\n+struct json_command callbacks[TELEMETRY_LEGACY_MAX_CALLBACKS] = {\n+\t\t{\n+\t\t\t.action = \"\\\"action\\\":1\",\n+\t\t\t.cmd = CLIENTS_CMD,\n+\t\t\t.data = CLIENTS_DATA,\n+\t\t\t.fn = register_client\n+\t\t}\n+};\n+int num_legacy_callbacks = 1;\n+static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER;\n+\n+int\n+rte_telemetry_legacy_register(const char *cmd, enum\n+\t\trte_telemetry_legacy_data_req data_req, telemetry_cb fn)\n+{\n+\tif (fn == NULL)\n+\t\treturn -EINVAL;\n+\tif (num_legacy_callbacks >= (int) RTE_DIM(callbacks))\n+\t\treturn -ENOENT;\n+\n+\trte_spinlock_lock(&callback_sl);\n+\tstrlcpy(callbacks[num_legacy_callbacks].action, STATS_ACTION, MAX_LEN);\n+\tsnprintf(callbacks[num_legacy_callbacks].cmd, MAX_LEN,\n+\t\t\t\"\\\"command\\\":\\\"%s\\\"\", cmd);\n+\tsnprintf(callbacks[num_legacy_callbacks].data, MAX_LEN,\n+\t\t\tdata_req ? \"%s{\\\"\" : \"%snull\",\n+\t\t\tDATA_REQ_LABEL);\n+\tcallbacks[num_legacy_callbacks].fn = fn;\n+\tnum_legacy_callbacks++;\n+\trte_spinlock_unlock(&callback_sl);\n+\n+\treturn 0;\n+}\n+\n+static int\n+register_client(const char *cmd __rte_unused, const char *params,\n+\t\tchar *buffer __rte_unused, int buf_len __rte_unused)\n+{\n+\tpthread_t th;\n+\tchar data[BUF_SIZE];\n+\tint fd;\n+\tstruct sockaddr_un addrs;\n+\n+\tstrlcpy(data, strchr(params, ':'), sizeof(data));\n+\tmemcpy(data, &data[strlen(\":\\\"\")], strlen(data));\n+\t*strchr(data, '\\\"') = 0;\n+\n+\tfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\taddrs.sun_family = AF_UNIX;\n+\tstrlcpy(addrs.sun_path, data, sizeof(addrs.sun_path));\n+\n+\tif (connect(fd, (struct sockaddr *)&addrs, sizeof(addrs)) == -1) {\n+\t\tperror(\"\\nClient connection error\\n\");\n+\t\treturn -1;\n+\t}\n+\tpthread_create(&th, NULL, &legacy_client_handler,\n+\t\t\t(void *)(uintptr_t)fd);\n+\treturn 0;\n+}\n+\n+static int\n+send_error_response(int s, int err)\n+{\n+\tconst char *desc;\n+\tchar out_buf[100000];\n+\n+\tswitch (err) {\n+\tcase -ENOMEM:\n+\t\tdesc = \"Memory Allocation Error\";\n+\t\tbreak;\n+\tcase -EINVAL:\n+\t\tdesc = \"Invalid Argument 404\";\n+\t\tbreak;\n+\tcase -EPERM:\n+\t\tdesc = \"Unknown\";\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Default case keeps behaviour of Telemetry library */\n+\t\tprintf(\"\\nInvalid error type: %d\\n\", err);\n+\t\treturn -EINVAL;\n+\t}\n+\tint used = snprintf(out_buf, sizeof(out_buf), \"{\\\"status_code\\\": \"\n+\t\t\t\"\\\"Status Error: %s\\\", \\\"data\\\": null}\", desc);\n+\tif (write(s, out_buf, used) < 0) {\n+\t\tperror(\"Error writing to socket\");\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static void\n+perform_command(telemetry_cb fn, const char *param, int s)\n+{\n+\tchar out_buf[100000];\n+\tint ret, used = 0;\n+\n+\tret = fn(\"\", param, out_buf, sizeof(out_buf));\n+\tif (ret < 0) {\n+\t\tret = send_error_response(s, ret);\n+\t\tif (ret < 0)\n+\t\t\tprintf(\"\\nCould not send error response\\n\");\n+\t\treturn;\n+\t}\n+\tused += ret;\n+\tif (write(s, out_buf, used) < 0)\n+\t\tperror(\"Error writing to socket\");\n+}\n+\n+static int\n+parse_client_request(char *buffer, int buf_len, int s)\n+{\n+\tint i;\n+\tchar *data = buffer + buf_len;\n+\ttelemetry_cb fn = NULL;\n+\tconst char *valid_sep = \",}\";\n+\tif (buffer[0] != '{' || buffer[buf_len - 1] != '}')\n+\t\treturn -EPERM;\n+\n+\tif (strstr(buffer, CLIENTS_UNREG_ACTION) && strstr(buffer, CLIENTS_CMD)\n+\t\t\t&& strstr(buffer, CLIENTS_DATA))\n+\t\treturn 0;\n+\n+\tfor (i = 0; i < num_legacy_callbacks; i++) {\n+\t\tchar *action_ptr = strstr(buffer, callbacks[i].action);\n+\t\tchar *cmd_ptr = strstr(buffer, callbacks[i].cmd);\n+\t\tchar *data_ptr = strstr(buffer, callbacks[i].data);\n+\t\tif (!action_ptr || !cmd_ptr || !data_ptr)\n+\t\t\tcontinue;\n+\n+\t\tchar action_sep = action_ptr[strlen(callbacks[i].action)];\n+\t\tchar cmd_sep = cmd_ptr[strlen(callbacks[i].cmd)];\n+\t\tif (!(strchr(valid_sep, action_sep) && strchr(valid_sep,\n+\t\t\t\tcmd_sep)))\n+\t\t\treturn -EPERM;\n+\t\tchar data_sep;\n+\n+\t\tif (!strchr(data_ptr, '{'))\n+\t\t\tdata_sep = data_ptr[strlen(callbacks[i].data)];\n+\t\telse {\n+\t\t\tchar *data_end = strchr(data_ptr, '}');\n+\t\t\tdata = data_ptr + strlen(DATA_REQ_LABEL);\n+\t\t\tdata_sep = data_end[1];\n+\t\t\tdata_end[1] = 0;\n+\t\t}\n+\t\tif (!strchr(valid_sep, data_sep))\n+\t\t\treturn -EPERM;\n+\t\tfn = callbacks[i].fn;\n+\t\tbreak;\n+\t}\n+\n+\tif (!fn)\n+\t\treturn -EINVAL;\n+\tperform_command(fn, data, s);\n+\treturn 0;\n+}\n+\n+void *\n+legacy_client_handler(void *sock_id)\n+{\n+\tint s = (int)(uintptr_t)sock_id;\n+\tint ret;\n+\tchar buffer_recv[BUF_SIZE];\n+\t/* receive data is not null terminated */\n+\tint bytes = read(s, buffer_recv, sizeof(buffer_recv));\n+\tbuffer_recv[bytes] = 0;\n+\n+\twhile (bytes > 0) {\n+\t\tint i, j;\n+\t\tchar buffer[BUF_SIZE];\n+\t\tfor (i = 0, j = 0; buffer_recv[i] != '\\0'; i++) {\n+\t\t\tbuffer[j] = buffer_recv[i];\n+\t\t\tj += !isspace(buffer_recv[i]);\n+\t\t}\n+\t\tbuffer[j] = 0;\n+\t\tret = parse_client_request(buffer, j, s);\n+\t\tif (ret < 0) {\n+\t\t\tret = send_error_response(s, ret);\n+\t\t\tif (ret < 0)\n+\t\t\t\tprintf(\"\\nCould not send error response\\n\");\n+\t\t}\n+\t\tbytes = read(s, buffer_recv, sizeof(buffer_recv));\n+\t\tbuffer_recv[bytes] = 0;\n+\t}\n+\tclose(s);\n+\treturn NULL;\n+}\n",
    "prefixes": [
        "09/12"
    ]
}