[dpdk-dev] [v3, 1/3] telemetry: enable storing pointer value

Gowrishankar Muthukrishnan gmuthukrishn at marvell.com
Tue Aug 3 10:05:44 CEST 2021


At present, value of pointer variable or address is stored in
u64 type which may not properly work in non64 bit arch. Hence,
this patch adds new API to store it in void*. JSON encoding is
after converting to uintptr_t so, address value is correctly
casted as per arch as well. Once JSON5 support is available
at JSON clients, hex value of address can be encoded instead
of uintptr_t.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn at marvell.com>
---
 lib/telemetry/rte_telemetry.h  | 37 ++++++++++++++++++++++++++++++-
 lib/telemetry/telemetry.c      | 21 ++++++++++++++++--
 lib/telemetry/telemetry_data.c | 40 ++++++++++++++++++++++++++++++----
 lib/telemetry/telemetry_data.h |  2 ++
 lib/telemetry/telemetry_json.h | 32 +++++++++++++++++++++++++++
 lib/telemetry/version.map      |  2 ++
 6 files changed, 127 insertions(+), 7 deletions(-)

diff --git a/lib/telemetry/rte_telemetry.h b/lib/telemetry/rte_telemetry.h
index 8776998b54..6a420f918c 100644
--- a/lib/telemetry/rte_telemetry.h
+++ b/lib/telemetry/rte_telemetry.h
@@ -46,7 +46,8 @@ 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_CONTAINER, /** a container struct */
+	RTE_TEL_CONTAINER,  /** a container struct */
+	RTE_TEL_PTR_VAL,    /** a pointer value */
 };
 
 /**
@@ -137,6 +138,22 @@ __rte_experimental
 int
 rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x);
 
+/**
+ * Add a pointer value to an array.
+ * The array must have been started by rte_tel_data_start_array() with
+ * RTE_TEL_PTR_VAL as the type parameter.
+ *
+ * @param d
+ *   The data structure passed to the callback
+ * @param x
+ *   The pointer value to be returned in the array
+ * @return
+ *   0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_add_array_ptr(struct rte_tel_data *d, void *x);
+
 /**
  * Add a container to an array. A container is an existing telemetry data
  * array. The array the container is to be added to must have been started by
@@ -213,6 +230,24 @@ int
 rte_tel_data_add_dict_u64(struct rte_tel_data *d,
 		const char *name, uint64_t val);
 
+/**
+ * Add a pointer 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 ptr
+ *   The pointer value 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_ptr(struct rte_tel_data *d,
+		const char *name, void *ptr);
+
 /**
  * Add a container to a dictionary. A container is an existing telemetry data
  * array. The dict the container is to be added to must have been started by
diff --git a/lib/telemetry/telemetry.c b/lib/telemetry/telemetry.c
index 8665db8d03..5842b28740 100644
--- a/lib/telemetry/telemetry.c
+++ b/lib/telemetry/telemetry.c
@@ -157,8 +157,10 @@ container_to_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 && d->type != RTE_TEL_ARRAY_INT
-			&& d->type != RTE_TEL_ARRAY_STRING)
+	if (d->type != RTE_TEL_ARRAY_U64
+		&& d->type != RTE_TEL_ARRAY_INT
+		&& d->type != RTE_TEL_ARRAY_PTR
+		&& d->type != RTE_TEL_ARRAY_STRING)
 		return snprintf(out_buf, buf_len, "null");
 
 	used = rte_tel_json_empty_array(out_buf, buf_len, 0);
@@ -167,6 +169,11 @@ container_to_json(const struct rte_tel_data *d, char *out_buf, size_t buf_len)
 			used = rte_tel_json_add_array_u64(out_buf,
 				buf_len, used,
 				d->data.array[i].u64val);
+	if (d->type == RTE_TEL_ARRAY_PTR)
+		for (i = 0; i < d->data_len; i++)
+			used = rte_tel_json_add_array_ptr(out_buf,
+				buf_len, used,
+				d->data.array[i].ptrval);
 	if (d->type == RTE_TEL_ARRAY_INT)
 		for (i = 0; i < d->data_len; i++)
 			used = rte_tel_json_add_array_int(out_buf,
@@ -226,6 +233,11 @@ 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_PTR_VAL:
+				used = rte_tel_json_add_obj_ptr(cb_data_buf,
+						buf_len, used,
+						v->name, v->value.ptrval);
+				break;
 			case RTE_TEL_CONTAINER:
 			{
 				char temp[buf_len];
@@ -248,6 +260,7 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s)
 	case RTE_TEL_ARRAY_STRING:
 	case RTE_TEL_ARRAY_INT:
 	case RTE_TEL_ARRAY_U64:
+	case RTE_TEL_ARRAY_PTR:
 	case RTE_TEL_ARRAY_CONTAINER:
 		prefix_used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":",
 				MAX_CMD_LEN, cmd);
@@ -269,6 +282,10 @@ output_json(const char *cmd, const struct rte_tel_data *d, int s)
 				used = rte_tel_json_add_array_u64(cb_data_buf,
 						buf_len, used,
 						d->data.array[i].u64val);
+			else if (d->type == RTE_TEL_ARRAY_PTR)
+				used = rte_tel_json_add_array_ptr(cb_data_buf,
+						buf_len, used,
+						d->data.array[i].ptrval);
 			else if (d->type == RTE_TEL_ARRAY_CONTAINER) {
 				char temp[buf_len];
 				const struct container *rec_data =
diff --git a/lib/telemetry/telemetry_data.c b/lib/telemetry/telemetry_data.c
index 77b0fe09a5..9384f48589 100644
--- a/lib/telemetry/telemetry_data.c
+++ b/lib/telemetry/telemetry_data.c
@@ -15,6 +15,7 @@ rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)
 			RTE_TEL_ARRAY_INT,    /* RTE_TEL_INT_VAL = 1 */
 			RTE_TEL_ARRAY_U64,    /* RTE_TEL_u64_VAL = 2 */
 			RTE_TEL_ARRAY_CONTAINER, /* RTE_TEL_CONTAINER = 3 */
+			RTE_TEL_ARRAY_PTR,    /* RTE_TEL_PTR_VAL = 4 */
 	};
 	d->type = array_types[type];
 	d->data_len = 0;
@@ -75,6 +76,17 @@ rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x)
 	return 0;
 }
 
+int
+rte_tel_data_add_array_ptr(struct rte_tel_data *d, void *x)
+{
+	if (d->type != RTE_TEL_ARRAY_PTR)
+		return -EINVAL;
+	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
+		return -ENOSPC;
+	d->data.array[d->data_len++].ptrval = x;
+	return 0;
+}
+
 int
 rte_tel_data_add_array_container(struct rte_tel_data *d,
 		struct rte_tel_data *val, int keep)
@@ -82,7 +94,8 @@ rte_tel_data_add_array_container(struct rte_tel_data *d,
 	if (d->type != RTE_TEL_ARRAY_CONTAINER ||
 			(val->type != RTE_TEL_ARRAY_U64
 			&& val->type != RTE_TEL_ARRAY_INT
-			&& val->type != RTE_TEL_ARRAY_STRING))
+			&& val->type != RTE_TEL_ARRAY_STRING
+			&& val->type != RTE_TEL_ARRAY_PTR))
 		return -EINVAL;
 	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
 		return -ENOSPC;
@@ -147,15 +160,34 @@ rte_tel_data_add_dict_u64(struct rte_tel_data *d,
 	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
 }
 
+int
+rte_tel_data_add_dict_ptr(struct rte_tel_data *d,
+		const char *name, void *ptr)
+{
+	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_PTR_VAL;
+	e->value.ptrval = ptr;
+	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_container(struct rte_tel_data *d, const char *name,
 		struct rte_tel_data *val, int keep)
 {
 	struct tel_dict_entry *e = &d->data.dict[d->data_len];
 
-	if (d->type != RTE_TEL_DICT || (val->type != RTE_TEL_ARRAY_U64
-			&& val->type != RTE_TEL_ARRAY_INT
-			&& val->type != RTE_TEL_ARRAY_STRING))
+	if (d->type != RTE_TEL_DICT ||
+		(val->type != RTE_TEL_ARRAY_U64
+		 && val->type != RTE_TEL_ARRAY_INT
+		 && val->type != RTE_TEL_ARRAY_STRING
+		 && val->type != RTE_TEL_ARRAY_PTR))
 		return -EINVAL;
 	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
 		return -ENOSPC;
diff --git a/lib/telemetry/telemetry_data.h b/lib/telemetry/telemetry_data.h
index adb84a09f1..bb361e3bcc 100644
--- a/lib/telemetry/telemetry_data.h
+++ b/lib/telemetry/telemetry_data.h
@@ -16,6 +16,7 @@ enum tel_container_types {
 	RTE_TEL_ARRAY_INT,    /** array of signed, 32-bit int values */
 	RTE_TEL_ARRAY_U64,    /** array of unsigned 64-bit int values */
 	RTE_TEL_ARRAY_CONTAINER, /** array of container structs */
+	RTE_TEL_ARRAY_PTR,    /** array of pointer values */
 };
 
 struct container {
@@ -31,6 +32,7 @@ union tel_value {
 	char sval[RTE_TEL_MAX_STRING_LEN];
 	int ival;
 	uint64_t u64val;
+	void *ptrval;
 	struct container container;
 };
 
diff --git a/lib/telemetry/telemetry_json.h b/lib/telemetry/telemetry_json.h
index ad270b9b30..b41329902f 100644
--- a/lib/telemetry/telemetry_json.h
+++ b/lib/telemetry/telemetry_json.h
@@ -102,6 +102,20 @@ rte_tel_json_add_array_u64(char *buf, const int len, const int used,
 	return ret == 0 ? used : end + ret;
 }
 
+/* Appends a pointer value into the JSON array in the provided buffer. */
+static inline int
+rte_tel_json_add_array_ptr(char *buf, const int len, const int used, void *ptr)
+{
+	int ret, end = used - 1; /* strip off final delimiter */
+	if (used <= 2)		 /* assume empty, since minimum is '[]' */
+		return __json_snprintf(buf, len, "[%" PRIuPTR "]",
+				       (uintptr_t)ptr);
+
+	ret = __json_snprintf(buf + end, len - end, ",%" PRIuPTR "]",
+			      (uintptr_t)ptr);
+	return ret == 0 ? used : end + ret;
+}
+
 /*
  * Add a new element with raw JSON value to the JSON array stored in the
  * provided buffer.
@@ -136,6 +150,24 @@ rte_tel_json_add_obj_u64(char *buf, const int len, const int used,
 	return ret == 0 ? used : end + ret;
 }
 
+/**
+ * Add a new element with uint64_t value to the JSON object stored in the
+ * provided buffer.
+ */
+static inline int
+rte_tel_json_add_obj_ptr(char *buf, const int len, const int used,
+			 const char *name, void *ptr)
+{
+	int ret, end = used - 1;
+	if (used <= 2) /* assume empty, since minimum is '{}' */
+		return __json_snprintf(buf, len, "{\"%s\":%" PRIuPTR "}", name,
+				       (uintptr_t)ptr);
+
+	ret = __json_snprintf(buf + end, len - end, ",\"%s\":%" PRIuPTR "}",
+			      name, (uintptr_t)ptr);
+	return ret == 0 ? used : end + ret;
+}
+
 /**
  * Add a new element with int value to the JSON object stored in the
  * provided buffer.
diff --git a/lib/telemetry/version.map b/lib/telemetry/version.map
index bde80ce29b..d919340bc6 100644
--- a/lib/telemetry/version.map
+++ b/lib/telemetry/version.map
@@ -5,10 +5,12 @@ EXPERIMENTAL {
 	rte_tel_data_add_array_int;
 	rte_tel_data_add_array_string;
 	rte_tel_data_add_array_u64;
+	rte_tel_data_add_array_ptr;
 	rte_tel_data_add_dict_container;
 	rte_tel_data_add_dict_int;
 	rte_tel_data_add_dict_string;
 	rte_tel_data_add_dict_u64;
+	rte_tel_data_add_dict_ptr;
 	rte_tel_data_alloc;
 	rte_tel_data_free;
 	rte_tel_data_start_array;
-- 
2.25.1



More information about the dev mailing list