--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 Intel Corporation
+ */
+
+#include <string.h>
+
+#include "../../lib/librte_telemetry/telemetry_json.h"
+#include "test.h"
+
+static int
+test_basic_array(void)
+{
+       const char *expected = "[\"meaning of life\",42]";
+       char buf[1024];
+       int used = 0;
+
+       printf("%s: ", __func__);
+       used = rte_tel_json_empty_array(buf, sizeof(buf), used);
+       if (used != 2 || strcmp(buf, "[]"))
+               return -1;
+
+       used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
+               "meaning of life");
+       used = rte_tel_json_add_array_int(buf, sizeof(buf), used, 42);
+
+       printf("buf = '%s', expected = '%s'\n", buf, expected);
+       if (used != (int)strlen(expected))
+               return -1;
+       return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_basic_obj(void)
+{
+       const char *expected = "{\"weddings\":4,\"funerals\":1}";
+       char buf[1024];
+       int used = 0;
+
+       used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+               "weddings", 4);
+       used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+               "funerals", 1);
+
+       printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+       if (used != (int)strlen(expected))
+               return -1;
+       return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_overflow_array(void)
+{
+       static const char * const strs[] = {"Arsenal", "Chelsea", "Liverpool",
+                       "Spurs"};
+       const char *expected = "[\"Arsenal\",\"Chelsea\"]";
+       char buf[25];
+       int i, used = 0;
+
+       for (i = 0; i < (int)RTE_DIM(strs); i++)
+               used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
+                               strs[i]);
+
+       printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+       if (buf[used - 1] != ']')
+               return -1;
+       if (used != (int)strlen(expected))
+               return -1;
+       return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_overflow_obj(void)
+{
+       static const char * const names[] = {"Italy", "Wales", "Scotland",
+                       "Ireland", "England", "France"};
+       const int vals[RTE_DIM(names)] = {20, 61, 10, 40, 55, 35};
+       const char *expected = "{\"Italy\":20,\"Wales\":61}";
+       char buf[25];
+       int i, used = 0;
+
+       for (i = 0; i < (int)RTE_DIM(names); i++)
+               used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+                               names[i], vals[i]);
+
+       printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+       if (buf[used - 1] != '}')
+               return -1;
+       if (used != (int)strlen(expected))
+               return -1;
+       return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_large_array_element(void)
+{
+       static const char str[] = "A really long string to overflow buffer";
+       /* buffer should be unmodified so initial value and expected are same */
+       const char *expected = "ABC";
+       char buf[sizeof(str) - 5] = "ABC";
+       int used = 0;
+
+       used = rte_tel_json_add_array_string(buf, sizeof(buf), used, str);
+       printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+
+       return strlen(buf) != 0;
+}
+
+static int
+test_large_obj_element(void)
+{
+       static const char str[] = "A really long string to overflow buffer";
+       /* buffer should be unmodified so initial value and expected are same */
+       const char *expected = "XYZ";
+       char buf[sizeof(str) - 5] = "XYZ";
+       int used = 0;
+
+       used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, str, 0);
+       printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+
+       return strlen(buf) != 0;
+}
+
+static int
+test_telemetry_json(void)
+{
+       if (test_basic_array() < 0 ||
+                       test_basic_obj() < 0 ||
+                       test_overflow_array() < 0 ||
+                       test_overflow_obj() < 0 ||
+                       test_large_array_element() < 0 ||
++                      test_large_obj_element() < 0)
+               return -1;
+       return 0;
+}
+
+REGISTER_TEST_COMMAND(telemetry_json_autotest, test_telemetry_json);
 
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef _RTE_TELEMETRY_JSON_H_
+#define _RTE_TELEMETRY_JSON_H_
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <rte_common.h>
+
+/**
+ * @file
+ * Internal Telemetry Utility functions
+ *
+ * This file contains small inline functions to make it easier for applications
+ * to build up valid JSON responses to telemetry requests.
+ *
+ ***/
+
+/**
+ * @internal
+ * Copies a value into a buffer if the buffer has enough available space.
+ * Nothing written to buffer if an overflow ocurs.
+ * This function is not for use for values larger than 1k.
+ */
+__rte_format_printf(3, 4)
+static inline int
+__json_snprintf(char *buf, const int len, const char *format, ...)
+{
+       char tmp[1024];
+       va_list ap;
+       int ret;
+
+       va_start(ap, format);
+       ret = vsnprintf(tmp, sizeof(tmp), format, ap);
+       va_end(ap);
+       if (ret > 0 && ret < (int)sizeof(tmp) && ret < len) {
+               strcpy(buf, tmp);
+               return ret;
+       }
+       return 0; /* nothing written or modified */
+}
+
+/* Copies an empty array into the provided buffer. */
+static inline int
+rte_tel_json_empty_array(char *buf, const int len, const int used)
+{
+       return used + __json_snprintf(buf + used, len - used, "[]");
+}
+
+/* Copies an empty object into the provided buffer. */
+static inline int
+rte_tel_json_empty_obj(char *buf, const int len, const int used)
+{
+       return used + __json_snprintf(buf + used, len - used, "{}");
+}
+
+/* Copies a string into the provided buffer, in JSON format. */
+static inline int
+rte_tel_json_str(char *buf, const int len, const int used, const char *str)
+{
+       return used + __json_snprintf(buf + used, len - used, "\"%s\"", str);
+}
+
+/* Appends a string into the JSON array in the provided buffer. */
+static inline int
+rte_tel_json_add_array_string(char *buf, const int len, const int used,
+               const char *str)
+{
+       int ret, end = used - 1; /* strip off final delimiter */
+       if (used <= 2) /* assume empty, since minimum is '[]' */
+               return __json_snprintf(buf, len, "[\"%s\"]", str);
+
+       ret = __json_snprintf(buf + end, len - end, ",\"%s\"]", str);
+       return ret == 0 ? used : end + ret;
+}
+
+/* Appends an integer into the JSON array in the provided buffer. */
+static inline int
+rte_tel_json_add_array_int(char *buf, const int len, const int used, int val)
+{
+       int ret, end = used - 1; /* strip off final delimiter */
+       if (used <= 2) /* assume empty, since minimum is '[]' */
+               return __json_snprintf(buf, len, "[%d]", val);
+
+       ret = __json_snprintf(buf + end, len - end, ",%d]", val);
+       return ret == 0 ? used : end + ret;
+}
+
+/* Appends a uint64_t into the JSON array in the provided buffer. */
+static inline int
+rte_tel_json_add_array_u64(char *buf, const int len, const int used,
+               uint64_t val)
+{
+       int ret, end = used - 1; /* strip off final delimiter */
+       if (used <= 2) /* assume empty, since minimum is '[]' */
+               return __json_snprintf(buf, len, "[%"PRIu64"]", val);
+
+       ret = __json_snprintf(buf + end, len - end, ",%"PRIu64"]", val);
+       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_u64(char *buf, const int len, const int used,
+               const char *name, uint64_t val)
+{
+       int ret, end = used - 1;
+       if (used <= 2) /* assume empty, since minimum is '{}' */
+               return __json_snprintf(buf, len, "{\"%s\":%"PRIu64"}", name,
+                               val);
+
+       ret = __json_snprintf(buf + end, len - end, ",\"%s\":%"PRIu64"}",
+                       name, val);
+       return ret == 0 ? used : end + ret;
+}
+
+/**
+ * Add a new element with int value to the JSON object stored in the
+ * provided buffer.
+ */
+static inline int
+rte_tel_json_add_obj_int(char *buf, const int len, const int used,
+               const char *name, int val)
+{
+       int ret, end = used - 1;
+       if (used <= 2) /* assume empty, since minimum is '{}' */
+               return __json_snprintf(buf, len, "{\"%s\":%d}", name,
+                               val);
+
+       ret = __json_snprintf(buf + end, len - end, ",\"%s\":%d}",
+                       name, val);
+       return ret == 0 ? used : end + ret;
+}
+
+/**
+ * Add a new element with string value to the JSON object stored in the
+ * provided buffer.
+ */
+static inline int
+rte_tel_json_add_obj_str(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_*/