From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1BF74A00BE; Fri, 12 Jun 2020 12:54:33 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id BB08C2C54; Fri, 12 Jun 2020 12:54:29 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 1FE262C38 for ; Fri, 12 Jun 2020 12:54:24 +0200 (CEST) IronPort-SDR: GsZYy3M6bOMvh2gcSRpjAi/4ekQLX+A02WZxrbgL9gPNzSzA0BXrIvGpBbNrPP/q79HMtrWKW6 mUXsDTs7sInA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2020 03:54:24 -0700 IronPort-SDR: 3r48xHQy7/V98tV9UDrlicFSze5aG/K0q1uCSXGC0pRDtC6AVMxEK0gBEfN/X0wiryAwdvKYg3 ySA8eWblIrkA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,503,1583222400"; d="scan'208";a="448264478" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga005.jf.intel.com with ESMTP; 12 Jun 2020 03:54:22 -0700 From: Ciara Power To: kevin.laatz@intel.com, thomas@monjalon.net, ferruh.yigit@intel.com, arybchenko@solarflare.com Cc: keith.wiles@intel.com, dev@dpdk.org, Ciara Power Date: Fri, 12 Jun 2020 11:53:43 +0100 Message-Id: <20200612105344.15383-2-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200612105344.15383-1-ciara.power@intel.com> References: <20200612105344.15383-1-ciara.power@intel.com> Subject: [dpdk-dev] [RFC 1/2] telemetry: support some recursive data objects X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Dict data objects now support uint64_t array data object values. Only one level of recursion supported. Signed-off-by: Ciara Power --- lib/librte_telemetry/rte_telemetry.h | 27 +++++++++++++++ .../rte_telemetry_version.map | 2 ++ lib/librte_telemetry/telemetry.c | 34 +++++++++++++++++++ lib/librte_telemetry/telemetry_data.c | 18 ++++++++++ lib/librte_telemetry/telemetry_data.h | 3 ++ lib/librte_telemetry/telemetry_json.h | 17 ++++++++++ 6 files changed, 101 insertions(+) diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h index 2c3c96cf7..dc18c34d0 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -44,6 +44,7 @@ enum rte_tel_value_type { RTE_TEL_STRING_VAL, /** a string value */ RTE_TEL_INT_VAL, /** a signed 32-bit int value */ RTE_TEL_U64_VAL, /** an unsigned 64-bit int value */ + RTE_TEL_DATA_VAL, /** a rte_tel_data pointer value */ }; /** @@ -188,6 +189,22 @@ int rte_tel_data_add_dict_u64(struct rte_tel_data *d, const char *name, uint64_t val); +/** + * Add a data object pointer to a dictionary. + * The dict must have been started by rte_tel_data_start_dict(). + * + * @param d + * The data structure passed to the callback + * @param x + * The data pointer to be returned in the dictionary + * @return + * 0 on success, negative errno on error + */ +__rte_experimental +int +rte_tel_data_add_dict_data(struct rte_tel_data *d, const char *name, + struct rte_tel_data *val); + /** * This telemetry callback is used when registering a telemetry command. * It handles getting and formatting information to be returned to telemetry @@ -253,4 +270,14 @@ int rte_telemetry_init(const char *runtime_dir, rte_cpuset_t *cpuset, const char **err_str); +/** + * Get the size of the rte_tel_data struct. + * + * @return + * size_t of the struct + */ +__rte_experimental +size_t +rte_tel_get_data_size(void); + #endif diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map index 86433c21d..c5425eff6 100644 --- a/lib/librte_telemetry/rte_telemetry_version.map +++ b/lib/librte_telemetry/rte_telemetry_version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_tel_data_add_array_int; rte_tel_data_add_array_string; rte_tel_data_add_array_u64; + rte_tel_data_add_dict_data; rte_tel_data_add_dict_int; rte_tel_data_add_dict_string; rte_tel_data_add_dict_u64; @@ -13,6 +14,7 @@ EXPERIMENTAL { rte_telemetry_init; rte_telemetry_legacy_register; rte_telemetry_register_cmd; + rte_tel_get_data_size; local: *; }; diff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c index 7b6f8a79e..b3a5f4296 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -47,6 +47,12 @@ static int num_callbacks; /* How many commands are registered */ /* Used when accessing or modifying list of command callbacks */ static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER; +size_t +rte_tel_get_data_size(void) +{ + return DATA_STRUCT_SIZE; +} + int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn, const char *help) { @@ -120,6 +126,23 @@ command_help(const char *cmd __rte_unused, const char *params, return 0; } +static int +recursive_data_json(const struct rte_tel_data *d, char *out_buf, size_t buf_len) +{ + size_t used = 0; + unsigned int i; + + if (d->type != RTE_TEL_ARRAY_U64) + return snprintf(out_buf, buf_len, "null"); + + used = rte_tel_json_empty_array(out_buf, buf_len, 0); + for (i = 0; i < d->data_len; i++) + used = rte_tel_json_add_array_u64(out_buf, + buf_len, used, + d->data.array[i].u64val); + return used; +} + static void output_json(const char *cmd, const struct rte_tel_data *d, int s) { @@ -166,6 +189,17 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s) buf_len, used, v->name, v->value.u64val); break; + case RTE_TEL_DATA_VAL: + { + char temp[buf_len]; + if (recursive_data_json(v->value.dataval, + temp, buf_len) != 0) + used = rte_tel_json_add_obj_json( + cb_data_buf, + buf_len, used, + v->name, temp); + free(v->value.dataval); + } } } used += prefix_used; diff --git a/lib/librte_telemetry/telemetry_data.c b/lib/librte_telemetry/telemetry_data.c index f424bbd48..46ce7f9b0 100644 --- a/lib/librte_telemetry/telemetry_data.c +++ b/lib/librte_telemetry/telemetry_data.c @@ -128,3 +128,21 @@ rte_tel_data_add_dict_u64(struct rte_tel_data *d, const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN); return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG; } + +int +rte_tel_data_add_dict_data(struct rte_tel_data *d, const char *name, + struct rte_tel_data *val) +{ + struct tel_dict_entry *e = &d->data.dict[d->data_len]; + + if (d->type != RTE_TEL_DICT) + return -EINVAL; + if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) + return -ENOSPC; + + d->data_len++; + e->type = RTE_TEL_DATA_VAL; + e->value.dataval = val; + const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN); + return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG; +} diff --git a/lib/librte_telemetry/telemetry_data.h b/lib/librte_telemetry/telemetry_data.h index ff3a371a3..226d961e0 100644 --- a/lib/librte_telemetry/telemetry_data.h +++ b/lib/librte_telemetry/telemetry_data.h @@ -8,6 +8,8 @@ #include #include "rte_telemetry.h" +#define DATA_STRUCT_SIZE sizeof(struct rte_tel_data) + enum tel_container_types { RTE_TEL_NULL, /** null, used as error value */ RTE_TEL_STRING, /** basic string type, no included data */ @@ -25,6 +27,7 @@ union tel_value { char sval[RTE_TEL_MAX_STRING_LEN]; int ival; uint64_t u64val; + struct rte_tel_data *dataval; }; struct tel_dict_entry { diff --git a/lib/librte_telemetry/telemetry_json.h b/lib/librte_telemetry/telemetry_json.h index a2ce4899e..415cfe7c6 100644 --- a/lib/librte_telemetry/telemetry_json.h +++ b/lib/librte_telemetry/telemetry_json.h @@ -155,4 +155,21 @@ rte_tel_json_add_obj_str(char *buf, const int len, const int used, return ret == 0 ? used : end + ret; } +/** + * Add a new element with raw JSON value to the JSON object stored in the + * provided buffer. + */ +static inline int +rte_tel_json_add_obj_json(char *buf, const int len, const int used, + const char *name, const char *val) +{ + int ret, end = used - 1; + if (used <= 2) /* assume empty, since minimum is '{}' */ + return __json_snprintf(buf, len, "{\"%s\":%s}", name, val); + + ret = __json_snprintf(buf + end, len - end, ",\"%s\":%s}", + name, val); + return ret == 0 ? used : end + ret; +} + #endif /*_RTE_TELEMETRY_JSON_H_*/ -- 2.17.1