From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by inbox.dpdk.org (Postfix) with ESMTP id C9AEBA00C2;
	Fri, 24 Apr 2020 15:03:18 +0200 (CEST)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id 2F59A1C2F3;
	Fri, 24 Apr 2020 15:02:17 +0200 (CEST)
Received: from mga02.intel.com (mga02.intel.com [134.134.136.20])
 by dpdk.org (Postfix) with ESMTP id 718451C23C
 for <dev@dpdk.org>; Fri, 24 Apr 2020 15:02:08 +0200 (CEST)
IronPort-SDR: ss0jWdajaawawF12XjBGKKFwiU+MzQagu65JoqAHIbqQcvK7MwwEzEDjrcfKaBh5lp2l3FCf0h
 yep06VIHOoWw==
X-Amp-Result: SKIPPED(no attachment in message)
X-Amp-File-Uploaded: False
Received: from orsmga007.jf.intel.com ([10.7.209.58])
 by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;
 24 Apr 2020 06:01:59 -0700
IronPort-SDR: pfZnLC2/OlNM1Xghf3wdvtQtE6wHSuwx2ZEDKW4J26WZYuScJr/UXobp7BNTpFcOOZFB/dSPnh
 CFyVDz9kX9OA==
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.73,311,1583222400"; d="scan'208";a="245228283"
Received: from silpixa00399953.ir.intel.com (HELO
 silpixa00399953.ger.corp.intel.com) ([10.237.222.53])
 by orsmga007.jf.intel.com with ESMTP; 24 Apr 2020 06:01:57 -0700
From: Ciara Power <ciara.power@intel.com>
To: dev@dpdk.org,
	kevin.laatz@intel.com
Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com,
 keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net,
 Bruce Richardson <bruce.richardson@intel.com>
Date: Fri, 24 Apr 2020 13:41:48 +0100
Message-Id: <20200424124159.45989-8-ciara.power@intel.com>
X-Mailer: git-send-email 2.17.1
In-Reply-To: <20200424124159.45989-1-ciara.power@intel.com>
References: <20200319171907.60891-1-ciara.power@intel.com>
 <20200424124159.45989-1-ciara.power@intel.com>
Subject: [dpdk-dev] [PATCH v4 07/18] telemetry: add functions for returning
	callback data
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>

From: Bruce Richardson <bruce.richardson@intel.com>

The functions added in this patch will help applications build
up data in reply to a telemetry request.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_telemetry/Makefile                 |   1 +
 lib/librte_telemetry/meson.build              |   2 +-
 lib/librte_telemetry/rte_telemetry.h          | 142 ++++++++++++++++++
 .../rte_telemetry_version.map                 |   9 ++
 lib/librte_telemetry/telemetry_data.c         | 130 ++++++++++++++++
 5 files changed, 283 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_telemetry/telemetry_data.c

diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile
index 270e1aac54..5457d1ed4f 100644
--- a/lib/librte_telemetry/Makefile
+++ b/lib/librte_telemetry/Makefile
@@ -24,6 +24,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) := rte_telemetry.c
 SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser.c
 SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += rte_telemetry_parser_test.c
 SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c
+SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry_data.c
 
 # export include files
 SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h
diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build
index 0cdae414a4..80926936a5 100644
--- a/lib/librte_telemetry/meson.build
+++ b/lib/librte_telemetry/meson.build
@@ -4,7 +4,7 @@
 includes = [global_inc]
 
 sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',
-	'telemetry.c')
+	'telemetry.c', 'telemetry_data.c')
 headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h')
 includes += include_directories('../librte_metrics')
 
diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h
index 66290a3fdf..f3ca3e4b3f 100644
--- a/lib/librte_telemetry/rte_telemetry.h
+++ b/lib/librte_telemetry/rte_telemetry.h
@@ -46,6 +46,148 @@ enum rte_tel_value_type {
 	RTE_TEL_U64_VAL,    /** an unsigned 64-bit int value */
 };
 
+/**
+ * Start an array of the specified type for returning from a callback
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param type
+ *   The type of the array of data
+ * @return
+ *   0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type);
+
+/**
+ * Start a dictionary of values for returning from a callback
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @return
+ *   0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_start_dict(struct rte_tel_data *d);
+
+/**
+ * Set a string for returning from a callback
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param str
+ *   The string to be returned in the data structure
+ * @return
+ *   0 on success, negative errno on error, E2BIG on string truncation
+ */
+__rte_experimental
+int
+rte_tel_data_string(struct rte_tel_data *d, const char *str);
+
+/**
+ * Add a string to an array.
+ * The array must have been started by rte_tel_data_start_array() with
+ * RTE_TEL_STRING_VAL as the type parameter.
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param str
+ *   The string to be returned in the array
+ * @return
+ *   0 on success, negative errno on error, E2BIG on string truncation
+ */
+__rte_experimental
+int
+rte_tel_data_add_array_string(struct rte_tel_data *d, const char *str);
+
+/**
+ * Add an int to an array.
+ * The array must have been started by rte_tel_data_start_array() with
+ * RTE_TEL_INT_VAL as the type parameter.
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param x
+ *   The number to be returned in the array
+ * @return
+ *   0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_add_array_int(struct rte_tel_data *d, int x);
+
+/**
+ * Add a uint64_t to an array.
+ * The array must have been started by rte_tel_data_start_array() with
+ * RTE_TEL_U64_VAL as the type parameter.
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param x
+ *   The number to be returned in the array
+ * @return
+ *   0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x);
+
+/**
+ * Add a string value 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 name
+ *   The name the value is to be stored under in the dict
+ * @param val
+ *   The string to be stored in the dict
+ * @return
+ *   0 on success, negative errno on error, E2BIG on string truncation of
+ *   either name or value.
+ */
+__rte_experimental
+int
+rte_tel_data_add_dict_string(struct rte_tel_data *d, const char *name,
+		const char *val);
+
+/**
+ * Add an int value 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 name
+ *   The name the value is to be stored under in the dict
+ * @param val
+ *   The number to be stored in the dict
+ * @return
+ *   0 on success, negative errno on error, E2BIG on string truncation of name.
+ */
+__rte_experimental
+int
+rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int val);
+
+/**
+ * Add a uint64_t value 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 name
+ *   The name the value is to be stored under in the dict
+ * @param val
+ *   The number to be stored in the dict
+ * @return
+ *   0 on success, negative errno on error, E2BIG on string truncation of name.
+ */
+__rte_experimental
+int
+rte_tel_data_add_dict_u64(struct rte_tel_data *d,
+		const char *name, uint64_t val);
+
 /**
  * This telemetry callback is used when registering a telemetry command.
  * It handles getting and formatting information to be returned to telemetry
diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map
index 831bbd59ad..e433ce58b7 100644
--- a/lib/librte_telemetry/rte_telemetry_version.map
+++ b/lib/librte_telemetry/rte_telemetry_version.map
@@ -8,6 +8,15 @@ EXPERIMENTAL {
 	rte_telemetry_set_metrics_fns;
 	rte_telemetry_new_init;
 	rte_telemetry_register_cmd;
+	rte_tel_data_add_array_int;
+	rte_tel_data_add_array_string;
+	rte_tel_data_add_array_u64;
+	rte_tel_data_add_dict_int;
+	rte_tel_data_add_dict_string;
+	rte_tel_data_add_dict_u64;
+	rte_tel_data_start_array;
+	rte_tel_data_start_dict;
+	rte_tel_data_string;
 
 	local: *;
 };
diff --git a/lib/librte_telemetry/telemetry_data.c b/lib/librte_telemetry/telemetry_data.c
new file mode 100644
index 0000000000..f424bbd48f
--- /dev/null
+++ b/lib/librte_telemetry/telemetry_data.c
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#undef RTE_USE_LIBBSD
+#include <rte_string_fns.h>
+
+#include "telemetry_data.h"
+
+int
+rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)
+{
+	enum tel_container_types array_types[] = {
+			RTE_TEL_ARRAY_STRING, /* RTE_TEL_STRING_VAL = 0 */
+			RTE_TEL_ARRAY_INT,    /* RTE_TEL_INT_VAL = 1 */
+			RTE_TEL_ARRAY_U64,    /* RTE_TEL_u64_VAL = 2 */
+	};
+	d->type = array_types[type];
+	d->data_len = 0;
+	return 0;
+}
+
+int
+rte_tel_data_start_dict(struct rte_tel_data *d)
+{
+	d->type = RTE_TEL_DICT;
+	d->data_len = 0;
+	return 0;
+}
+
+int
+rte_tel_data_string(struct rte_tel_data *d, const char *str)
+{
+	d->type = RTE_TEL_STRING;
+	d->data_len = strlcpy(d->data.str, str, sizeof(d->data.str));
+	if (d->data_len >= RTE_TEL_MAX_SINGLE_STRING_LEN) {
+		d->data_len = RTE_TEL_MAX_SINGLE_STRING_LEN - 1;
+		return E2BIG; /* not necessarily and error, just truncation */
+	}
+	return 0;
+}
+
+int
+rte_tel_data_add_array_string(struct rte_tel_data *d, const char *str)
+{
+	if (d->type != RTE_TEL_ARRAY_STRING)
+		return -EINVAL;
+	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
+		return -ENOSPC;
+	const size_t bytes = strlcpy(d->data.array[d->data_len++].sval,
+			str, RTE_TEL_MAX_STRING_LEN);
+	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
+}
+
+int
+rte_tel_data_add_array_int(struct rte_tel_data *d, int x)
+{
+	if (d->type != RTE_TEL_ARRAY_INT)
+		return -EINVAL;
+	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
+		return -ENOSPC;
+	d->data.array[d->data_len++].ival = x;
+	return 0;
+}
+
+int
+rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x)
+{
+	if (d->type != RTE_TEL_ARRAY_U64)
+		return -EINVAL;
+	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
+		return -ENOSPC;
+	d->data.array[d->data_len++].u64val = x;
+	return 0;
+}
+
+int
+rte_tel_data_add_dict_string(struct rte_tel_data *d, const char *name,
+		const char *val)
+{
+	struct tel_dict_entry *e = &d->data.dict[d->data_len];
+	size_t nbytes, vbytes;
+
+	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_STRING_VAL;
+	vbytes = strlcpy(e->value.sval, val, RTE_TEL_MAX_STRING_LEN);
+	nbytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
+	if (vbytes >= RTE_TEL_MAX_STRING_LEN ||
+			nbytes >= RTE_TEL_MAX_STRING_LEN)
+		return E2BIG;
+	return 0;
+}
+
+int
+rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int 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_INT_VAL;
+	e->value.ival = val;
+	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_u64(struct rte_tel_data *d,
+		const char *name, uint64_t 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_U64_VAL;
+	e->value.u64val = val;
+	const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
+	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
+}
-- 
2.17.1