On Mon, Dec 19, 2022 at 03:06:46PM +0800, Huisong Li wrote:
> Sometimes displaying a unsigned integer value as hexadecimal encoded style
> is more expected for human consumption, such as, offload capability and
> device flag. This patch introduces two APIs to add unsigned integer value
> as hexadecimal encoded string to array or dictionary. And user can choose
> whether the stored value is padding to the specified width.
>
> Signed-off-by: Huisong Li <lihuisong@huawei.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
> Acked-by: Chengwen Feng <fengchengwen@huawei.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
@@ -10,6 +10,7 @@ extern "C" {
#endif
#include <stdint.h>
+#include <rte_compat.h>
/** Maximum length for string used in object. */
#define RTE_TEL_MAX_STRING_LEN 128
@@ -153,6 +154,28 @@ int
rte_tel_data_add_array_container(struct rte_tel_data *d,
struct rte_tel_data *val, int keep);
+/**
+ * Convert a unsigned integer to hexadecimal encoded strings and add this 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 val
+ * The number to be returned in the array as a hexadecimal encoded strings.
+ * @param display_bitwidth
+ * The display bit width of the 'val'. If 'display_bitwidth' is zero, the
+ * value is stored in the array as no-padding zero hexadecimal encoded string,
+ * or the value is stored as padding zero to specified hexadecimal width.
+ * @return
+ * 0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_add_array_uint_hex(struct rte_tel_data *d, uint64_t val,
+ uint8_t display_bitwidth);
+
/**
* Add a string value to a dictionary.
* The dict must have been started by rte_tel_data_start_dict().
@@ -231,6 +254,30 @@ int
rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,
struct rte_tel_data *val, int keep);
+/**
+ * Convert a unsigned integer to hexadecimal encoded strings and add this string
+ * to an 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 of the value is to be stored in the dict
+ * Must contain only alphanumeric characters or the symbols: '_' or '/'
+ * @param val
+ * The number to be stored in the dict as a hexadecimal encoded strings.
+ * @param display_bitwidth
+ * The display bit width of the 'val'. If 'display_bitwidth' is zero, the
+ * value is stored in the array as no-padding zero hexadecimal encoded string,
+ * or the value is stored as padding zero to specified hexadecimal width.
+ * @return
+ * 0 on success, negative errno on error
+ */
+__rte_experimental
+int
+rte_tel_data_add_dict_uint_hex(struct rte_tel_data *d, const char *name,
+ uint64_t val, uint8_t display_bitwidth);
+
/**
* This telemetry callback is used when registering a telemetry command.
* It handles getting and formatting information to be returned to telemetry
@@ -4,6 +4,7 @@
#include <errno.h>
#include <stdlib.h>
+#include <inttypes.h>
#undef RTE_USE_LIBBSD
#include <stdbool.h>
@@ -12,6 +13,8 @@
#include "telemetry_data.h"
+#define RTE_TEL_UINT_HEX_STR_BUF_LEN 64
+
int
rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)
{
@@ -97,6 +100,60 @@ rte_tel_data_add_array_container(struct rte_tel_data *d,
return 0;
}
+/* To suppress compiler warning about format string. */
+#if defined(RTE_TOOLCHAIN_GCC)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#elif defined(RTE_TOOLCHAIN_CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+
+static int
+rte_tel_uint_to_hex_encoded_str(char *buf, size_t buf_len, uint64_t val,
+ uint8_t display_bitwidth)
+{
+#define RTE_TEL_HEX_FORMAT_LEN 16
+
+ uint8_t spec_hex_width = (display_bitwidth + 3) / 4;
+ char format[RTE_TEL_HEX_FORMAT_LEN];
+
+ if (display_bitwidth != 0) {
+ if (snprintf(format, RTE_TEL_HEX_FORMAT_LEN, "0x%%0%u" PRIx64,
+ spec_hex_width) >= RTE_TEL_HEX_FORMAT_LEN)
+ return -EINVAL;
+
+ if (snprintf(buf, buf_len, format, val) >= (int)buf_len)
+ return -EINVAL;
+ } else {
+ if (snprintf(buf, buf_len, "0x%" PRIx64, val) >= (int)buf_len)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#if defined(RTE_TOOLCHAIN_GCC)
+#pragma GCC diagnostic pop
+#elif defined(RTE_TOOLCHAIN_CLANG)
+#pragma clang diagnostic pop
+#endif
+
+int
+rte_tel_data_add_array_uint_hex(struct rte_tel_data *d, uint64_t val,
+ uint8_t display_bitwidth)
+{
+ char hex_str[RTE_TEL_UINT_HEX_STR_BUF_LEN];
+ int ret;
+
+ ret = rte_tel_uint_to_hex_encoded_str(hex_str,
+ RTE_TEL_UINT_HEX_STR_BUF_LEN, val, display_bitwidth);
+ if (ret != 0)
+ return ret;
+
+ return rte_tel_data_add_array_string(d, hex_str);
+}
+
static bool
valid_name(const char *name)
{
@@ -204,6 +261,22 @@ rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,
return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
}
+int
+rte_tel_data_add_dict_uint_hex(struct rte_tel_data *d, const char *name,
+ uint64_t val, uint8_t display_bitwidth)
+{
+ char hex_str[RTE_TEL_UINT_HEX_STR_BUF_LEN];
+ int ret;
+
+ ret = rte_tel_uint_to_hex_encoded_str(hex_str,
+ RTE_TEL_UINT_HEX_STR_BUF_LEN, val, display_bitwidth);
+ if (ret != 0)
+ return ret;
+
+
+ return rte_tel_data_add_dict_string(d, name, hex_str);
+}
+
struct rte_tel_data *
rte_tel_data_alloc(void)
{
@@ -1,3 +1,12 @@
+EXPERIMENTAL {
+ global:
+
+ rte_tel_data_add_array_uint_hex;
+ rte_tel_data_add_dict_uint_hex;
+
+ local: *;
+};
+
DPDK_23 {
global: