From: Kevin Laatz <kevin.laatz@intel.com>
To: dev@dpdk.org
Cc: harry.van.haaren@intel.com, stephen@networkplumber.org,
gaetan.rivet@6wind.com, shreyansh.jain@nxp.com,
thomas@monjalon.net, mattias.ronnblom@ericsson.com,
bruce.richardson@intel.com, Ciara Power <ciara.power@intel.com>,
Brian Archbold <brian.archbold@intel.com>,
Kevin Laatz <kevin.laatz@intel.com>
Subject: [dpdk-dev] [PATCH v4 09/13] telemetry: add tests for telemetry api
Date: Thu, 11 Oct 2018 17:58:33 +0100 [thread overview]
Message-ID: <20181011165837.81030-10-kevin.laatz@intel.com> (raw)
In-Reply-To: <20181011165837.81030-1-kevin.laatz@intel.com>
From: Ciara Power <ciara.power@intel.com>
This patch adds all tests for the Telemetry API.
The tests added include a parser test, selftest, and socket
messaging tests.
The parser tests pass valid and invalid messages to the parser
to ensure the correct return values are received.
The selftest tests basic functions in the Telemetry API such as
registering, unregistering, and initialisation.
The socket messaging tests pass messages through the socket and
validates the return message, to ensure the Telemetry API is
responding correctly.
Signed-off-by: Ciara Power <ciara.power@intel.com>
Signed-off-by: Brian Archbold <brian.archbold@intel.com>
Signed-off-by: Kevin Laatz <kevin.laatz@intel.com>
---
lib/librte_telemetry/Makefile | 1 +
lib/librte_telemetry/meson.build | 4 +-
lib/librte_telemetry/rte_telemetry.c | 653 ++++++++++++++++++++++
lib/librte_telemetry/rte_telemetry.h | 12 +
lib/librte_telemetry/rte_telemetry_internal.h | 3 +
lib/librte_telemetry/rte_telemetry_parser_test.c | 534 ++++++++++++++++++
lib/librte_telemetry/rte_telemetry_parser_test.h | 39 ++
lib/librte_telemetry/rte_telemetry_socket_tests.h | 36 ++
lib/librte_telemetry/rte_telemetry_version.map | 1 +
9 files changed, 1281 insertions(+), 2 deletions(-)
create mode 100644 lib/librte_telemetry/rte_telemetry_parser_test.c
create mode 100644 lib/librte_telemetry/rte_telemetry_parser_test.h
create mode 100644 lib/librte_telemetry/rte_telemetry_socket_tests.h
diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile
index 95c7296..1a05069 100644
--- a/lib/librte_telemetry/Makefile
+++ b/lib/librte_telemetry/Makefile
@@ -22,6 +22,7 @@ LIBABIVER := 1
# library source files
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
# 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 7450f96..57dd83d 100644
--- a/lib/librte_telemetry/meson.build
+++ b/lib/librte_telemetry/meson.build
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2018 Intel Corporation
-sources = files('rte_telemetry.c', 'rte_telemetry_parser.c')
-headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h')
+sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c')
+headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h', 'rte_telemetry_parser_test.h')
deps += ['metrics', 'ethdev']
cflags += '-DALLOW_EXPERIMENTAL_API'
jansson = cc.find_library('jansson', required: true)
diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c
index 5f59f16..4fdd1d7 100644
--- a/lib/librte_telemetry/rte_telemetry.c
+++ b/lib/librte_telemetry/rte_telemetry.c
@@ -18,13 +18,32 @@
#include "rte_telemetry.h"
#include "rte_telemetry_internal.h"
#include "rte_telemetry_parser.h"
+#include "rte_telemetry_parser_test.h"
+#include "rte_telemetry_socket_tests.h"
#define BUF_SIZE 1024
#define ACTION_POST 1
#define SLEEP_TIME 10
+#define SELFTEST_VALID_CLIENT "/var/run/dpdk/valid_client"
+#define SELFTEST_INVALID_CLIENT "/var/run/dpdk/invalid_client"
+#define SOCKET_TEST_CLIENT_PATH "/var/run/dpdk/client"
+
static telemetry_impl *static_telemetry;
+struct telemetry_message_test {
+ char *test_name;
+ int (*test_func_ptr)(struct telemetry_impl *telemetry, int fd);
+};
+
+struct json_data {
+ char *status_code;
+ char *data;
+ int port;
+ char *stat_name;
+ int stat_value;
+};
+
static void
rte_telemetry_get_runtime_dir(char *socket_path, size_t size)
{
@@ -640,6 +659,7 @@ static int32_t
rte_telemetry_initial_accept(struct telemetry_impl *telemetry)
{
uint16_t pid;
+ int ret;
RTE_ETH_FOREACH_DEV(pid) {
telemetry->reg_index = rte_telemetry_reg_ethdev_to_metrics(pid);
@@ -652,6 +672,18 @@ rte_telemetry_initial_accept(struct telemetry_impl *telemetry)
}
telemetry->metrics_register_done = 1;
+ ret = rte_telemetry_socket_messaging_testing(telemetry->reg_index,
+ telemetry->server_fd);
+ if (ret < 0)
+ return -1;
+
+ ret = rte_telemetry_parser_test(telemetry);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Parser Tests Failed");
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - All Parser Tests Passed");
return 0;
}
@@ -1134,6 +1166,627 @@ rte_telemetry_parse_client_message(struct telemetry_impl *telemetry, char *buf)
return -1;
}
+int32_t
+rte_telemetry_dummy_client_socket(const char *valid_client_path)
+{
+ int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ struct sockaddr_un addr = {0};
+
+ if (sockfd < 0) {
+ TELEMETRY_LOG_ERR("Test socket creation failure");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strlcpy(addr.sun_path, valid_client_path, sizeof(addr.sun_path));
+ unlink(valid_client_path);
+
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ TELEMETRY_LOG_ERR("Test socket binding failure");
+ return -1;
+ }
+
+ if (listen(sockfd, 1) < 0) {
+ TELEMETRY_LOG_ERR("Listen failure");
+ return -1;
+ }
+
+ return sockfd;
+}
+
+int32_t
+rte_telemetry_selftest(void)
+{
+ const char *invalid_client_path = SELFTEST_INVALID_CLIENT;
+ const char *valid_client_path = SELFTEST_VALID_CLIENT;
+ int ret, sockfd;
+
+ TELEMETRY_LOG_INFO("Selftest");
+
+ ret = rte_telemetry_init();
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Valid initialisation test failed");
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Valid initialisation test passed");
+
+ ret = rte_telemetry_init();
+ if (ret != -EALREADY) {
+ TELEMETRY_LOG_ERR("Invalid initialisation test failed");
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Invalid initialisation test passed");
+
+ ret = rte_telemetry_unregister_client(static_telemetry,
+ invalid_client_path);
+ if (ret != -EPERM) {
+ TELEMETRY_LOG_ERR("Invalid unregister test failed");
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Invalid unregister test passed");
+
+ sockfd = rte_telemetry_dummy_client_socket(valid_client_path);
+ if (sockfd < 0) {
+ TELEMETRY_LOG_ERR("Test socket creation failed");
+ return -1;
+ }
+
+ ret = rte_telemetry_register_client(static_telemetry, valid_client_path);
+ if (ret != 0) {
+ TELEMETRY_LOG_ERR("Valid register test failed: %i", ret);
+ return -1;
+ }
+
+ accept(sockfd, NULL, NULL);
+ TELEMETRY_LOG_INFO("Success - Valid register test passed");
+
+ ret = rte_telemetry_register_client(static_telemetry, valid_client_path);
+ if (ret != -EINVAL) {
+ TELEMETRY_LOG_ERR("Invalid register test failed: %i", ret);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Invalid register test passed");
+
+ ret = rte_telemetry_unregister_client(static_telemetry,
+ invalid_client_path);
+ if (ret != -1) {
+ TELEMETRY_LOG_ERR("Invalid unregister test failed: %i", ret);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Invalid unregister test passed");
+
+ ret = rte_telemetry_unregister_client(static_telemetry, valid_client_path);
+ if (ret != 0) {
+ TELEMETRY_LOG_ERR("Valid unregister test failed: %i", ret);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Valid unregister test passed");
+
+ ret = rte_telemetry_cleanup();
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Cleanup test failed");
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Valid cleanup test passed");
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_socket_messaging_testing(int index, int socket)
+{
+ struct telemetry_impl *telemetry = calloc(1, sizeof(telemetry_impl));
+ int fd, bad_send_fd, send_fd, bad_fd, bad_recv_fd, recv_fd, ret;
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Could not initialize Telemetry API");
+ return -1;
+ }
+
+ telemetry->server_fd = socket;
+ telemetry->reg_index = index;
+ TELEMETRY_LOG_INFO("Beginning Telemetry socket message Selftest");
+ rte_telemetry_socket_test_setup(telemetry, &send_fd, &recv_fd);
+ TELEMETRY_LOG_INFO("Register valid client test");
+
+ ret = rte_telemetry_socket_register_test(telemetry, &fd, send_fd,
+ recv_fd);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Register valid client test failed!");
+ free(telemetry);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Register valid client test passed!");
+
+ TELEMETRY_LOG_INFO("Register invalid/same client test");
+ ret = rte_telemetry_socket_test_setup(telemetry, &bad_send_fd,
+ &bad_recv_fd);
+ ret = rte_telemetry_socket_register_test(telemetry, &bad_fd,
+ bad_send_fd, bad_recv_fd);
+ if (!ret) {
+ TELEMETRY_LOG_ERR("Register invalid/same client test failed!");
+ free(telemetry);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Register invalid/same client test passed!");
+
+ ret = rte_telemetry_json_socket_message_test(telemetry, fd);
+ if (ret < 0) {
+ free(telemetry);
+ return -1;
+ }
+
+ free(telemetry);
+ return 0;
+}
+
+int32_t
+rte_telemetry_socket_register_test(struct telemetry_impl *telemetry, int *fd,
+ int send_fd, int recv_fd)
+{
+ int ret;
+ char good_req_string[BUF_SIZE];
+
+ snprintf(good_req_string, sizeof(good_req_string),
+ "{\"action\":1,\"command\":\"clients\",\"data\":{\"client_path\""
+ ":\"%s\"}}", SOCKET_TEST_CLIENT_PATH);
+
+ listen(recv_fd, 1);
+
+ ret = send(send_fd, good_req_string, strlen(good_req_string), 0);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not send message over socket");
+ return -1;
+ }
+
+ rte_telemetry_run(telemetry);
+
+ if (telemetry->register_fail_count != 0)
+ return -1;
+
+ *fd = accept(recv_fd, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_socket_test_setup(struct telemetry_impl *telemetry, int *send_fd,
+ int *recv_fd)
+{
+ int ret;
+ const char *client_path = SOCKET_TEST_CLIENT_PATH;
+ char socket_path[BUF_SIZE];
+ struct sockaddr_un addr = {0};
+ struct sockaddr_un addrs = {0};
+ *send_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ *recv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ listen(telemetry->server_fd, 5);
+ addr.sun_family = AF_UNIX;
+ rte_telemetry_get_runtime_dir(socket_path, sizeof(socket_path));
+ strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
+
+ ret = connect(*send_fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not connect socket");
+ return -1;
+ }
+
+ telemetry->accept_fd = accept(telemetry->server_fd, NULL, NULL);
+
+ addrs.sun_family = AF_UNIX;
+ strlcpy(addrs.sun_path, client_path, sizeof(addrs.sun_path));
+ unlink(client_path);
+
+ ret = bind(*recv_fd, (struct sockaddr *)&addrs, sizeof(addrs));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not bind socket");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int32_t
+rte_telemetry_stat_parse(char *buf, struct json_data *json_data_struct)
+{
+ json_error_t error;
+ json_t *root = json_loads(buf, 0, &error);
+ int arraylen, i;
+ json_t *status, *dataArray, *port, *stats, *name, *value, *dataArrayObj,
+ *statsArrayObj;
+
+ stats = NULL;
+ port = NULL;
+ name = NULL;
+
+ if (buf == NULL) {
+ TELEMETRY_LOG_ERR("JSON message is NULL");
+ return -EINVAL;
+ }
+
+ if (root == NULL) {
+ TELEMETRY_LOG_ERR("Could not load JSON object from data passed in : %s",
+ error.text);
+ return -EPERM;
+ } else if (!json_is_object(root)) {
+ TELEMETRY_LOG_ERR("JSON Request is not a JSON object");
+ json_decref(root);
+ return -EINVAL;
+ }
+
+ status = json_object_get(root, "status_code");
+ if (!status) {
+ TELEMETRY_LOG_ERR("Request does not have status field");
+ return -EINVAL;
+ } else if (!json_is_string(status)) {
+ TELEMETRY_LOG_ERR("Status value is not a string");
+ return -EINVAL;
+ }
+
+ json_data_struct->status_code = strdup(json_string_value(status));
+
+ dataArray = json_object_get(root, "data");
+ if (dataArray == NULL) {
+ TELEMETRY_LOG_ERR("Request does not have data field");
+ return -EINVAL;
+ }
+
+ arraylen = json_array_size(dataArray);
+ if (arraylen == 0) {
+ json_data_struct->data = "null";
+ return -EINVAL;
+ }
+
+ for (i = 0; i < arraylen; i++) {
+ dataArrayObj = json_array_get(dataArray, i);
+ port = json_object_get(dataArrayObj, "port");
+ stats = json_object_get(dataArrayObj, "stats");
+ }
+
+ if (port == NULL) {
+ TELEMETRY_LOG_ERR("Request does not have port field");
+ return -EINVAL;
+ }
+
+ if (!json_is_integer(port)) {
+ TELEMETRY_LOG_ERR("Port value is not an integer");
+ return -EINVAL;
+ }
+
+ json_data_struct->port = json_integer_value(port);
+
+ if (stats == NULL) {
+ TELEMETRY_LOG_ERR("Request does not have stats field");
+ return -EINVAL;
+ }
+
+ arraylen = json_array_size(stats);
+ for (i = 0; i < arraylen; i++) {
+ statsArrayObj = json_array_get(stats, i);
+ name = json_object_get(statsArrayObj, "name");
+ value = json_object_get(statsArrayObj, "value");
+ }
+
+ if (name == NULL) {
+ TELEMETRY_LOG_ERR("Request does not have name field");
+ return -EINVAL;
+ }
+
+ if (!json_is_string(name)) {
+ TELEMETRY_LOG_ERR("Stat name value is not a string");
+ return -EINVAL;
+ }
+
+ json_data_struct->stat_name = strdup(json_string_value(name));
+
+ if (value == NULL) {
+ TELEMETRY_LOG_ERR("Request does not have value field");
+ return -EINVAL;
+ }
+
+ if (!json_is_integer(value)) {
+ TELEMETRY_LOG_ERR("Stat value is not an integer");
+ return -EINVAL;
+ }
+
+ json_data_struct->stat_value = json_integer_value(value);
+
+ return 0;
+}
+
+static void
+rte_telemetry_free_test_data(struct json_data *data)
+{
+ free(data->status_code);
+ free(data->stat_name);
+ free(data);
+}
+
+int32_t
+rte_telemetry_valid_json_test(struct telemetry_impl *telemetry, int fd)
+{
+ int ret;
+ int port = 0;
+ int value = 0;
+ int fail_count = 0;
+ int buffer_read = 0;
+ char buf[BUF_SIZE];
+ struct json_data *data_struct;
+ errno = 0;
+ const char *status = "Status OK: 200";
+ const char *name = "rx_good_packets";
+ const char *valid_json_message = "{\"action\":0,\"command\":"
+ "\"ports_stats_values_by_name\",\"data\":{\"ports\""
+ ":[0],\"stats\":[\"rx_good_packets\"]}}";
+
+ ret = send(fd, valid_json_message, strlen(valid_json_message), 0);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not send message over socket");
+ return -1;
+ }
+
+ rte_telemetry_run(telemetry);
+ buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
+
+ if (buffer_read == -1) {
+ TELEMETRY_LOG_ERR("Read error");
+ return -1;
+ }
+
+ buf[buffer_read] = '\0';
+ data_struct = calloc(1, sizeof(struct json_data));
+ ret = rte_telemetry_stat_parse(buf, data_struct);
+
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not parse stats");
+ fail_count++;
+ }
+
+ if (strcmp(data_struct->status_code, status) != 0) {
+ TELEMETRY_LOG_ERR("Status code is invalid");
+ fail_count++;
+ }
+
+ if (data_struct->port != port) {
+ TELEMETRY_LOG_ERR("Port is invalid");
+ fail_count++;
+ }
+
+ if (strcmp(data_struct->stat_name, name) != 0) {
+ TELEMETRY_LOG_ERR("Stat name is invalid");
+ fail_count++;
+ }
+
+ if (data_struct->stat_value != value) {
+ TELEMETRY_LOG_ERR("Stat value is invalid");
+ fail_count++;
+ }
+
+ rte_telemetry_free_test_data(data_struct);
+ if (fail_count > 0)
+ return -1;
+
+ TELEMETRY_LOG_INFO("Success - Passed valid JSON message test passed");
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_invalid_json_test(struct telemetry_impl *telemetry, int fd)
+{
+ int ret;
+ char buf[BUF_SIZE];
+ int fail_count = 0;
+ const char *invalid_json = "{]";
+ const char *status = "Status Error: Unknown";
+ const char *data = "null";
+ struct json_data *data_struct;
+ int buffer_read = 0;
+ errno = 0;
+
+ ret = send(fd, invalid_json, strlen(invalid_json), 0);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not send message over socket");
+ return -1;
+ }
+
+ rte_telemetry_run(telemetry);
+ buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
+
+ if (buffer_read == -1) {
+ TELEMETRY_LOG_ERR("Read error");
+ return -1;
+ }
+
+ buf[buffer_read] = '\0';
+
+ data_struct = calloc(1, sizeof(struct json_data));
+ ret = rte_telemetry_stat_parse(buf, data_struct);
+
+ if (ret < 0)
+ TELEMETRY_LOG_ERR("Could not parse stats");
+
+ if (strcmp(data_struct->status_code, status) != 0) {
+ TELEMETRY_LOG_ERR("Status code is invalid");
+ fail_count++;
+ }
+
+ if (strcmp(data_struct->data, data) != 0) {
+ TELEMETRY_LOG_ERR("Data status is invalid");
+ fail_count++;
+ }
+
+ rte_telemetry_free_test_data(data_struct);
+ if (fail_count > 0)
+ return -1;
+
+ TELEMETRY_LOG_INFO("Success - Passed invalid JSON message test");
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_json_contents_test(struct telemetry_impl *telemetry, int fd)
+{
+ int ret;
+ char buf[BUF_SIZE];
+ int fail_count = 0;
+ char *status = "Status Error: Invalid Argument 404";
+ char *data = "null";
+ struct json_data *data_struct;
+ const char *invalid_contents = "{\"action\":0,\"command\":"
+ "\"ports_stats_values_by_name\",\"data\":{\"ports\""
+ ":[0],\"stats\":[\"some_invalid_param\","
+ "\"another_invalid_param\"]}}";
+ int buffer_read = 0;
+ errno = 0;
+
+ ret = send(fd, invalid_contents, strlen(invalid_contents), 0);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not send message over socket");
+ return -1;
+ }
+
+ rte_telemetry_run(telemetry);
+ buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
+
+ if (buffer_read == -1) {
+ TELEMETRY_LOG_ERR("Read error");
+ return -1;
+ }
+
+ buf[buffer_read] = '\0';
+ data_struct = calloc(1, sizeof(struct json_data));
+ ret = rte_telemetry_stat_parse(buf, data_struct);
+
+ if (ret < 0)
+ TELEMETRY_LOG_ERR("Could not parse stats");
+
+ if (strcmp(data_struct->status_code, status) != 0) {
+ TELEMETRY_LOG_ERR("Status code is invalid");
+ fail_count++;
+ }
+
+ if (strcmp(data_struct->data, data) != 0) {
+ TELEMETRY_LOG_ERR("Data status is invalid");
+ fail_count++;
+ }
+
+ rte_telemetry_free_test_data(data_struct);
+ if (fail_count > 0)
+ return -1;
+
+ TELEMETRY_LOG_INFO("Success - Passed invalid JSON content test");
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_json_empty_test(struct telemetry_impl *telemetry, int fd)
+{
+ int ret;
+ char buf[BUF_SIZE];
+ int fail_count = 0;
+ const char *status = "Status Error: Invalid Argument 404";
+ char *data = "null";
+ struct json_data *data_struct;
+ const char *empty_json = "{}";
+ int buffer_read = 0;
+ errno = 0;
+
+ ret = (send(fd, empty_json, strlen(empty_json), 0));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not send message over socket");
+ return -1;
+ }
+
+ rte_telemetry_run(telemetry);
+ buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
+
+ if (buffer_read == -1) {
+ TELEMETRY_LOG_ERR("Read error");
+ return -1;
+ }
+
+ buf[buffer_read] = '\0';
+ data_struct = calloc(1, sizeof(struct json_data));
+ ret = rte_telemetry_stat_parse(buf, data_struct);
+
+ if (ret < 0)
+ TELEMETRY_LOG_ERR("Could not parse stats");
+
+ if (strcmp(data_struct->status_code, status) != 0) {
+ TELEMETRY_LOG_ERR("Status code is invalid");
+ fail_count++;
+ }
+
+ if (strcmp(data_struct->data, data) != 0) {
+ TELEMETRY_LOG_ERR("Data status is invalid");
+ fail_count++;
+ }
+
+ rte_telemetry_free_test_data(data_struct);
+
+ if (fail_count > 0)
+ return -1;
+
+ TELEMETRY_LOG_INFO("Success - Passed JSON empty message test");
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_json_socket_message_test(struct telemetry_impl *telemetry, int fd)
+{
+ uint16_t i;
+ int ret, fail_count;
+
+ fail_count = 0;
+ struct telemetry_message_test socket_json_tests[] = {
+ {.test_name = "Invalid JSON test",
+ .test_func_ptr = rte_telemetry_invalid_json_test},
+ {.test_name = "Valid JSON test",
+ .test_func_ptr = rte_telemetry_valid_json_test},
+ {.test_name = "JSON contents test",
+ .test_func_ptr = rte_telemetry_json_contents_test},
+ {.test_name = "JSON empty tests",
+ .test_func_ptr = rte_telemetry_json_empty_test}
+ };
+
+#define NUM_TESTS RTE_DIM(socket_json_tests)
+
+ for (i = 0; i < NUM_TESTS; i++) {
+ TELEMETRY_LOG_INFO("%s", socket_json_tests[i].test_name);
+ ret = (socket_json_tests[i].test_func_ptr)
+ (telemetry, fd);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("%s failed",
+ socket_json_tests[i].test_name);
+ fail_count++;
+ }
+ }
+
+ if (fail_count > 0) {
+ TELEMETRY_LOG_ERR("Failed %i JSON socket message test(s)",
+ fail_count);
+ return -1;
+ }
+
+ TELEMETRY_LOG_INFO("Success - All JSON tests passed");
+
+ return 0;
+}
+
int telemetry_log_level;
RTE_INIT(rte_telemetry_register);
diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h
index d3b0d8d..958723b 100644
--- a/lib/librte_telemetry/rte_telemetry.h
+++ b/lib/librte_telemetry/rte_telemetry.h
@@ -33,4 +33,16 @@ rte_telemetry_init(void);
int32_t
rte_telemetry_cleanup(void);
+/**
+ * Runs various tests to ensure telemetry initialisation and register/unregister
+ * functions are working correctly.
+ *
+ * @return
+ * 0 on success when all tests have passed
+ * @return
+ * -1 on failure when the test has failed
+ */
+int32_t
+rte_telemetry_selftest(void);
+
#endif
diff --git a/lib/librte_telemetry/rte_telemetry_internal.h b/lib/librte_telemetry/rte_telemetry_internal.h
index 0082cb2..de7afda 100644
--- a/lib/librte_telemetry/rte_telemetry_internal.h
+++ b/lib/librte_telemetry/rte_telemetry_internal.h
@@ -75,4 +75,7 @@ int32_t
rte_telemetry_send_ports_stats_values(uint32_t *metric_ids, int num_metric_ids,
uint32_t *port_ids, int num_port_ids, struct telemetry_impl *telemetry);
+int32_t
+rte_telemetry_socket_messaging_testing(int index, int socket);
+
#endif
diff --git a/lib/librte_telemetry/rte_telemetry_parser_test.c b/lib/librte_telemetry/rte_telemetry_parser_test.c
new file mode 100644
index 0000000..9bf66a2
--- /dev/null
+++ b/lib/librte_telemetry/rte_telemetry_parser_test.c
@@ -0,0 +1,534 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <jansson.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_tailq.h>
+#include <rte_string_fns.h>
+
+#include "rte_telemetry_parser.h"
+
+enum choices {
+ INV_ACTION_VAL,
+ INV_COMMAND_VAL,
+ INV_DATA_VAL,
+ INV_ACTION_FIELD,
+ INV_COMMAND_FIELD,
+ INV_DATA_FIELD,
+ INV_JSON_FORMAT,
+ VALID_REQ
+};
+
+
+#define TEST_CLIENT "/var/run/dpdk/test_client"
+
+int32_t
+rte_telemetry_create_test_socket(struct telemetry_impl *telemetry,
+ const char *test_client_path)
+{
+ int ret, sockfd;
+ struct sockaddr_un addr = {0};
+ struct telemetry_client *client;
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+ sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ TELEMETRY_LOG_ERR("Test socket creation failure");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strlcpy(addr.sun_path, test_client_path, sizeof(addr.sun_path));
+ unlink(test_client_path);
+
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ TELEMETRY_LOG_ERR("Test socket binding failure");
+ return -1;
+ }
+
+ if (listen(sockfd, 1) < 0) {
+ TELEMETRY_LOG_ERR("Listen failure");
+ return -1;
+ }
+
+ ret = rte_telemetry_register_client(telemetry, test_client_path);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Register dummy client failed: %i", ret);
+ return -1;
+ }
+
+ ret = accept(sockfd, NULL, NULL);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Socket accept failed");
+ return -1;
+ }
+
+ TAILQ_FOREACH(client, &telemetry->client_list_head, client_list)
+ telemetry->request_client = client;
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_format_port_stat_ids(int *port_ids, int num_port_ids,
+ const char * const *stat_names, int num_stat_names, json_t **data)
+{
+
+ int ret;
+ json_t *stat_names_json_array = NULL;
+ json_t *port_ids_json_array = NULL;
+ uint32_t i;
+
+ if (num_port_ids < 0) {
+ TELEMETRY_LOG_ERR("Port Ids Count invalid");
+ goto fail;
+ }
+
+ *data = json_object();
+ if (*data == NULL) {
+ TELEMETRY_LOG_ERR("Data json object creation failed");
+ goto fail;
+ }
+
+ port_ids_json_array = json_array();
+ if (port_ids_json_array == NULL) {
+ TELEMETRY_LOG_ERR("port_ids_json_array creation failed");
+ goto fail;
+ }
+
+ for (i = 0; i < (uint32_t)num_port_ids; i++) {
+ ret = json_array_append(port_ids_json_array,
+ json_integer(port_ids[i]));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("JSON array creation failed");
+ goto fail;
+ }
+ }
+
+ ret = json_object_set_new(*data, "ports", port_ids_json_array);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting 'ports' value in data object failed");
+ goto fail;
+ }
+
+ if (stat_names) {
+ if (num_stat_names < 0) {
+ TELEMETRY_LOG_ERR("Stat Names Count invalid");
+ goto fail;
+ }
+
+ stat_names_json_array = json_array();
+ if (stat_names_json_array == NULL) {
+ TELEMETRY_LOG_ERR("stat_names_json_array creation failed");
+ goto fail;
+ }
+
+ uint32_t i;
+ for (i = 0; i < (uint32_t)num_stat_names; i++) {
+ ret = json_array_append(stat_names_json_array,
+ json_string(stat_names[i]));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("JSON array creation failed");
+ goto fail;
+ }
+ }
+
+ ret = json_object_set_new(*data, "stats", stat_names_json_array);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting 'stats' value in data object failed");
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ if (*data)
+ json_decref(*data);
+ if (stat_names_json_array)
+ json_decref(stat_names_json_array);
+ if (port_ids_json_array)
+ json_decref(port_ids_json_array);
+ return -1;
+}
+
+int32_t
+rte_telemetry_create_json_request(int action, char *command,
+ const char *client_path, int *port_ids, int num_port_ids,
+ const char * const *stat_names, int num_stat_names, char **request,
+ int inv_choice)
+{
+ int ret;
+ json_t *root = json_object();
+ json_t *data;
+
+ if (root == NULL) {
+ TELEMETRY_LOG_ERR("Could not create root json object");
+ goto fail;
+ }
+
+ if (inv_choice == INV_ACTION_FIELD) {
+ ret = json_object_set_new(root, "ac--on", json_integer(action));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting invalid action field in root object failed");
+ goto fail;
+ }
+ } else {
+ ret = json_object_set_new(root, "action", json_integer(action));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting valid action field in root object failed");
+ goto fail;
+ }
+ }
+
+ if (inv_choice == INV_COMMAND_FIELD) {
+ ret = json_object_set_new(root, "co---nd", json_string(command));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting invalid command field in root object failed");
+ goto fail;
+ }
+ } else {
+ ret = json_object_set_new(root, "command", json_string(command));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting valid command field in root object failed");
+ goto fail;
+ }
+ }
+
+ data = json_null();
+ if (client_path) {
+ data = json_object();
+ if (data == NULL) {
+ TELEMETRY_LOG_ERR("Data json object creation failed");
+ goto fail;
+ }
+
+ ret = json_object_set_new(data, "client_path",
+ json_string(client_path));
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting valid client_path field in data object failed");
+ goto fail;
+ }
+
+ } else if (port_ids) {
+ ret = rte_telemetry_format_port_stat_ids(port_ids, num_port_ids,
+ stat_names, num_stat_names, &data);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Formatting Port/Stat arrays failed");
+ goto fail;
+ }
+
+ }
+
+ if (inv_choice == INV_DATA_FIELD) {
+ ret = json_object_set_new(root, "d--a", data);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting invalid data field in data object failed");
+ goto fail;
+ }
+ } else {
+ ret = json_object_set_new(root, "data", data);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Setting valid data field in data object failed");
+ goto fail;
+ }
+ }
+
+ *request = json_dumps(root, 0);
+ if (*request == NULL) {
+ TELEMETRY_LOG_ERR("Converting JSON root object to char* failed");
+ goto fail;
+ }
+
+ json_decref(root);
+ return 0;
+
+fail:
+ if (root)
+ json_decref(root);
+ return -1;
+}
+
+int32_t
+rte_telemetry_send_get_ports_and_stats_request(struct telemetry_impl *telemetry,
+ int action_choice, char *command_choice, int inv_choice)
+{
+ int ret;
+ char *request;
+ char *client_path_data = NULL;
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+
+ if (inv_choice == INV_ACTION_VAL)
+ action_choice = -1;
+ else if (inv_choice == INV_COMMAND_VAL)
+ command_choice = "INVALID_COMMAND";
+ else if (inv_choice == INV_DATA_VAL)
+ client_path_data = "INVALID_DATA";
+
+ ret = rte_telemetry_create_json_request(action_choice, command_choice,
+ client_path_data, NULL, -1, NULL, -1, &request, inv_choice);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not create JSON Request");
+ return -1;
+ }
+
+ if (inv_choice == INV_JSON_FORMAT)
+ request++;
+
+ ret = rte_telemetry_parse(telemetry, request);
+ if (ret < 0) {
+ TELEMETRY_LOG_WARN("Could not parse JSON Request");
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_send_get_ports_details_request(struct telemetry_impl *telemetry,
+ int action_choice, int *port_ids, int num_port_ids, int inv_choice)
+{
+ int ret;
+ char *request;
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+ char *command = "ports_details";
+
+ if (inv_choice == INV_ACTION_VAL)
+ action_choice = -1;
+ else if (inv_choice == INV_COMMAND_VAL)
+ command = "INVALID_COMMAND";
+ else if (inv_choice == INV_DATA_VAL)
+ port_ids = NULL;
+
+
+ ret = rte_telemetry_create_json_request(action_choice, command, NULL,
+ port_ids, num_port_ids, NULL, -1, &request, inv_choice);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not create JSON Request");
+ return -1;
+ }
+
+ if (inv_choice == INV_JSON_FORMAT)
+ request++;
+
+ ret = rte_telemetry_parse(telemetry, request);
+ if (ret < 0) {
+ TELEMETRY_LOG_WARN("Could not parse JSON Request");
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_send_stats_values_by_name_request(struct telemetry_impl
+ *telemetry, int action_choice, int *port_ids, int num_port_ids,
+ const char * const *stat_names, int num_stat_names,
+ int inv_choice)
+{
+ int ret;
+ char *request;
+ char *command = "ports_stats_values_by_name";
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+ if (inv_choice == INV_ACTION_VAL)
+ action_choice = -1;
+ else if (inv_choice == INV_COMMAND_VAL)
+ command = "INVALID_COMMAND";
+ else if (inv_choice == INV_DATA_VAL) {
+ port_ids = NULL;
+ stat_names = NULL;
+ }
+
+ ret = rte_telemetry_create_json_request(action_choice, command, NULL,
+ port_ids, num_port_ids, stat_names, num_stat_names, &request,
+ inv_choice);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not create JSON Request");
+ return -1;
+ }
+
+ if (inv_choice == INV_JSON_FORMAT)
+ request++;
+
+ ret = rte_telemetry_parse(telemetry, request);
+ if (ret < 0) {
+ TELEMETRY_LOG_WARN("Could not parse JSON Request");
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_send_unreg_request(struct telemetry_impl *telemetry,
+ int action_choice, const char *client_path, int inv_choice)
+{
+ int ret;
+ char *request;
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+ char *command = "clients";
+
+ if (inv_choice == INV_ACTION_VAL)
+ action_choice = -1;
+ else if (inv_choice == INV_COMMAND_VAL)
+ command = "INVALID_COMMAND";
+ else if (inv_choice == INV_DATA_VAL)
+ client_path = NULL;
+
+ ret = rte_telemetry_create_json_request(action_choice, command,
+ client_path, NULL, -1, NULL, -1, &request, inv_choice);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not create JSON Request");
+ return -1;
+ }
+
+ if (inv_choice == INV_JSON_FORMAT)
+ request++;
+
+ ret = rte_telemetry_parse(telemetry, request);
+ if (ret < 0) {
+ TELEMETRY_LOG_WARN("Could not parse JSON Request");
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t
+rte_telemetry_parser_test(struct telemetry_impl *telemetry)
+{
+ int ret;
+ const char *client_path = TEST_CLIENT;
+
+ if (telemetry == NULL) {
+ TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
+ return -EINVAL;
+ }
+
+ ret = rte_telemetry_create_test_socket(telemetry, client_path);
+ if (ret < 0) {
+ TELEMETRY_LOG_ERR("Could not create test request client socket");
+ return -1;
+ }
+
+ int port_ids[] = {0, 1};
+ int num_port_ids = RTE_DIM(port_ids);
+
+ static const char * const stat_names[] = {"tx_good_packets",
+ "rx_good_packets"};
+ int num_stat_names = RTE_DIM(stat_names);
+
+ static const char * const test_types[] = {
+ "INVALID ACTION VALUE TESTS",
+ "INVALID COMMAND VALUE TESTS",
+ "INVALID DATA VALUE TESTS",
+ "INVALID ACTION FIELD TESTS",
+ "INVALID COMMAND FIELD TESTS",
+ "INVALID DATA FIELD TESTS",
+ "INVALID JSON FORMAT TESTS",
+ "VALID TESTS"
+ };
+
+
+#define NUM_TEST_TYPES (sizeof(test_types)/sizeof(const char * const))
+
+ uint32_t i;
+ for (i = 0; i < NUM_TEST_TYPES; i++) {
+ TELEMETRY_LOG_INFO("%s", test_types[i]);
+
+ ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
+ ACTION_GET, "ports", i);
+ if (ret != 0 && i == VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports valid test failed");
+ return -EPERM;
+ } else if (ret != -1 && i != VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports invalid test failed");
+ return -EPERM;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Get ports test passed");
+
+ ret = rte_telemetry_send_get_ports_details_request(telemetry,
+ ACTION_GET, port_ids, num_port_ids, i);
+ if (ret != 0 && i == VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports details valid");
+ return -EPERM;
+ } else if (ret != -1 && i != VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports details invalid");
+ return -EPERM;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Get ports details test passed");
+
+ ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
+ ACTION_GET, "port_stats", i);
+ if (ret != 0 && i == VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get port stats valid test");
+ return -EPERM;
+ } else if (ret != -1 && i != VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports stats invalid test failed");
+ return -EPERM;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Get ports stats test passed");
+
+ ret = rte_telemetry_send_stats_values_by_name_request(telemetry,
+ ACTION_GET, port_ids, num_port_ids, stat_names,
+ num_stat_names, i);
+ if (ret != 0 && i == VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports stats values by name valid test failed");
+ return -EPERM;
+ } else if (ret != -1 && i != VALID_REQ) {
+ TELEMETRY_LOG_ERR("Get ports stats values by name invalid test failed");
+ return -EPERM;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Get ports stats values by name test passed");
+
+ ret = rte_telemetry_send_unreg_request(telemetry, ACTION_DELETE,
+ client_path, i);
+ if (ret != 0 && i == VALID_REQ) {
+ TELEMETRY_LOG_ERR("Deregister valid test failed");
+ return -EPERM;
+ } else if (ret != -1 && i != VALID_REQ) {
+ TELEMETRY_LOG_ERR("Deregister invalid test failed");
+ return -EPERM;
+ }
+
+ TELEMETRY_LOG_INFO("Success - Deregister test passed");
+ }
+
+ return 0;
+}
diff --git a/lib/librte_telemetry/rte_telemetry_parser_test.h b/lib/librte_telemetry/rte_telemetry_parser_test.h
new file mode 100644
index 0000000..6ada852
--- /dev/null
+++ b/lib/librte_telemetry/rte_telemetry_parser_test.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _RTE_TELEMETRY_PARSER_TEST_H_
+#define _RTE_TELEMETRY_PARSER_TEST_H_
+
+int32_t
+rte_telemetry_parser_test(struct telemetry_impl *telemetry);
+
+int32_t
+rte_telemetry_format_port_stat_ids(int *port_ids, int num_port_ids,
+ const char * const stat_names, int num_stat_names, json_t **data);
+
+int32_t
+rte_telemetry_create_json_request(int action, char *command,
+ const char *client_path, int *port_ids, int num_port_ids,
+ const char * const stat_names, int num_stat_names, char **request,
+ int inv_choice);
+
+int32_t
+rte_telemetry_send_get_ports_and_stats_request(struct telemetry_impl *telemetry,
+ int action_choice, char *command_choice, int inv_choice);
+
+int32_t
+rte_telemetry_send_get_ports_details_request(struct telemetry_impl *telemetry,
+ int action_choice, int *port_ids, int num_port_ids, int inv_choice);
+
+int32_t
+rte_telemetry_send_stats_values_by_name_request(struct telemetry_impl
+ *telemetry, int action_choice, int *port_ids, int num_port_ids,
+ const char * const stat_names, int num_stat_names,
+ int inv_choice);
+
+int32_t
+rte_telemetry_send_unreg_request(int action_choice, const char *client_path,
+ int inv_choice);
+
+#endif
diff --git a/lib/librte_telemetry/rte_telemetry_socket_tests.h b/lib/librte_telemetry/rte_telemetry_socket_tests.h
new file mode 100644
index 0000000..db9167c
--- /dev/null
+++ b/lib/librte_telemetry/rte_telemetry_socket_tests.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdbool.h>
+
+#include "rte_telemetry_internal.h"
+
+#ifndef _RTE_TELEMETRY_SOCKET_TESTING_H_
+#define _RTE_TELEMETRY_SOCKET_TESTING_H_
+
+int32_t
+rte_telemetry_json_socket_message_test(struct telemetry_impl *telemetry,
+ int fd);
+
+int32_t
+rte_telemetry_invalid_json_test(struct telemetry_impl *telemetry, int fd);
+
+int32_t
+rte_telemetry_valid_json_test(struct telemetry_impl *telemetry, int fd);
+
+int32_t
+rte_telemetry_json_contents_test(struct telemetry_impl *telemetry, int fd);
+
+int32_t
+rte_telemetry_json_empty_test(struct telemetry_impl *telemetry, int fd);
+
+int32_t
+rte_telemetry_socket_register_test(struct telemetry_impl *telemetry, int *fd,
+ int send_fd, int recv_fd);
+
+int32_t
+rte_telemetry_socket_test_setup(struct telemetry_impl *telemetry, int *send_fd,
+ int *recv_fd);
+
+#endif
diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map
index 992d227..98459fc 100644
--- a/lib/librte_telemetry/rte_telemetry_version.map
+++ b/lib/librte_telemetry/rte_telemetry_version.map
@@ -2,5 +2,6 @@ DPDK_18.11 {
global:
rte_telemetry_init;
+ rte_telemetry_selftest;
local: *;
};
--
2.9.5
next prev parent reply other threads:[~2018-10-11 16:58 UTC|newest]
Thread overview: 219+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-23 12:08 [dpdk-dev] [PATCH 00/11] introduce telemetry library Ciara Power
2018-08-23 12:08 ` [dpdk-dev] [PATCH 01/11] telemetry: initial telemetry infrastructure Ciara Power
2018-08-23 23:17 ` Stephen Hemminger
2018-08-23 23:17 ` Stephen Hemminger
2018-08-23 23:18 ` Stephen Hemminger
2018-08-23 23:19 ` Stephen Hemminger
2018-08-23 23:22 ` Stephen Hemminger
2018-08-28 17:12 ` Van Haaren, Harry
2018-08-24 13:03 ` Shreyansh Jain
2018-08-28 16:50 ` Van Haaren, Harry
2018-08-28 11:46 ` Gaëtan Rivet
2018-08-28 16:54 ` Van Haaren, Harry
2018-08-29 8:23 ` Gaëtan Rivet
2018-08-23 12:08 ` [dpdk-dev] [PATCH 02/11] telemetry: add initial connection socket Ciara Power
2018-08-28 16:40 ` Gaëtan Rivet
2018-08-28 17:03 ` Van Haaren, Harry
2018-09-07 9:48 ` Burakov, Anatoly
2018-08-23 12:08 ` [dpdk-dev] [PATCH 03/11] telemetry: add client feature and sockets Ciara Power
2018-08-23 23:27 ` Stephen Hemminger
2018-08-28 15:26 ` Hunt, David
2018-08-28 17:09 ` Van Haaren, Harry
2018-08-23 12:08 ` [dpdk-dev] [PATCH 04/11] telemetry: add parser for client socket messages Ciara Power
2018-08-30 23:57 ` Gaëtan Rivet
2018-08-23 12:08 ` [dpdk-dev] [PATCH 05/11] telemetry: update metrics before sending stats Ciara Power
2018-08-23 12:08 ` [dpdk-dev] [PATCH 06/11] telemetry: format json response when " Ciara Power
2018-08-23 12:08 ` [dpdk-dev] [PATCH 07/11] telemetry: add tests for telemetry api Ciara Power
2018-08-23 23:15 ` Stephen Hemminger
2018-08-23 12:08 ` [dpdk-dev] [PATCH 08/11] telemetry: add vdev kvargs for selftest Ciara Power
2018-08-23 12:08 ` [dpdk-dev] [PATCH 09/11] doc: add telemetry documentation Ciara Power
2018-09-25 8:53 ` Kovacevic, Marko
2018-08-23 12:08 ` [dpdk-dev] [PATCH 10/11] usertools: add client python script for telemetry Ciara Power
2018-08-23 12:08 ` [dpdk-dev] [PATCH 11/11] telemetry: add collectd plugin patch Ciara Power
2018-09-18 9:52 ` Thomas Monjalon
2018-09-19 11:09 ` Laatz, Kevin
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 00/10] introduce telemetry library Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 01/10] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-04 14:13 ` Gaëtan Rivet
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 02/10] telemetry: add initial connection socket Kevin Laatz
2018-10-03 18:40 ` Mattias Rönnblom
2018-10-03 19:36 ` Thomas Monjalon
2018-10-03 19:49 ` Mattias Rönnblom
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 03/10] telemetry: add client feature and sockets Kevin Laatz
2018-10-03 19:06 ` Mattias Rönnblom
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 04/10] telemetry: add parser for client socket messages Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 05/10] telemetry: update metrics before sending stats Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 06/10] telemetry: format json response when " Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 07/10] telemetry: add tests for telemetry api Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 08/10] telemetry: add ability to disable selftest Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 09/10] doc: add telemetry documentation Kevin Laatz
2018-10-03 17:36 ` [dpdk-dev] [PATCH v2 10/10] usertools: add client python script for telemetry Kevin Laatz
2018-10-04 13:00 ` [dpdk-dev] [PATCH v2 00/10] introduce telemetry library Van Haaren, Harry
2018-10-04 13:25 ` Van Haaren, Harry
2018-10-04 15:16 ` Gaëtan Rivet
2018-10-04 15:53 ` Thomas Monjalon
2018-10-05 22:05 ` Gaëtan Rivet
2018-10-09 10:33 ` Van Haaren, Harry
2018-10-09 11:41 ` Thomas Monjalon
2018-10-09 14:56 ` Bruce Richardson
2018-10-09 17:07 ` Thomas Monjalon
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 00/12] " Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 01/12] eal: add param register infrastructure Kevin Laatz
2018-10-10 12:28 ` Thomas Monjalon
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 02/12] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 03/12] telemetry: add initial connection socket Kevin Laatz
2018-10-10 12:24 ` Thomas Monjalon
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 04/12] telemetry: add client feature and sockets Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 05/12] telemetry: add parser for client socket messages Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 06/12] telemetry: update metrics before sending stats Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 07/12] telemetry: format json response when " Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 08/12] telemetry: add tests for telemetry api Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 09/12] telemetry: add ability to disable selftest Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 10/12] doc: add telemetry documentation Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 11/12] usertools: add client python script for telemetry Kevin Laatz
2018-10-10 10:51 ` [dpdk-dev] [PATCH v3 12/12] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 00/13] introduce telemetry library Kevin Laatz
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 01/13] eal: add param register infrastructure Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-16 13:42 ` Thomas Monjalon
2018-10-16 14:20 ` Laatz, Kevin
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 02/13] eal: make get runtime dir function public Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 03/13] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 04/13] telemetry: add initial connection socket Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 05/13] telemetry: add client feature and sockets Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 06/13] telemetry: add parser for client socket messages Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 07/13] telemetry: update metrics before sending stats Kevin Laatz
2018-10-16 0:45 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 08/13] telemetry: format json response when " Kevin Laatz
2018-10-16 0:46 ` Van Haaren, Harry
2018-10-11 16:58 ` Kevin Laatz [this message]
2018-10-16 0:46 ` [dpdk-dev] [PATCH v4 09/13] telemetry: add tests for telemetry api Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 10/13] telemetry: add ability to disable selftest Kevin Laatz
2018-10-16 0:47 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 11/13] doc: add telemetry documentation Kevin Laatz
2018-10-16 0:47 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 12/13] usertools: add client python script for telemetry Kevin Laatz
2018-10-16 0:47 ` Van Haaren, Harry
2018-10-11 16:58 ` [dpdk-dev] [PATCH v4 13/13] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-16 0:47 ` Van Haaren, Harry
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 00/13] introduce telemetry library Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 01/13] eal: add param register infrastructure Kevin Laatz
2018-10-17 9:41 ` Thomas Monjalon
2018-10-17 11:45 ` Gaëtan Rivet
2018-10-17 13:46 ` Thomas Monjalon
2018-10-17 14:09 ` Laatz, Kevin
2018-10-17 14:20 ` Thomas Monjalon
2018-10-17 13:55 ` Laatz, Kevin
2018-10-17 15:56 ` Gaëtan Rivet
2018-10-18 15:58 ` Laatz, Kevin
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 02/13] eal: make get runtime dir function public Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 03/13] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 04/13] telemetry: add initial connection socket Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 05/13] telemetry: add client feature and sockets Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 06/13] telemetry: add parser for client socket messages Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 07/13] telemetry: update metrics before sending stats Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 08/13] telemetry: format json response when " Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 09/13] telemetry: add tests for telemetry api Kevin Laatz
2018-10-16 15:57 ` [dpdk-dev] [PATCH v5 10/13] telemetry: add ability to disable selftest Kevin Laatz
2018-10-16 15:58 ` [dpdk-dev] [PATCH v5 11/13] doc: add telemetry documentation Kevin Laatz
2018-10-16 15:58 ` [dpdk-dev] [PATCH v5 12/13] usertools: add client python script for telemetry Kevin Laatz
2018-10-16 15:58 ` [dpdk-dev] [PATCH v5 13/13] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-18 8:07 ` [dpdk-dev] [PATCH v5 00/13] introduce telemetry library Mattias Rönnblom
2018-10-19 10:16 ` Laatz, Kevin
2018-10-22 7:11 ` Mattias Rönnblom
2018-10-22 9:03 ` Laatz, Kevin
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 " Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 01/13] eal: add option register infrastructure Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 02/13] eal: make get runtime dir function public Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 03/13] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 04/13] telemetry: add initial connection socket Kevin Laatz
2018-10-22 13:50 ` Mattias Rönnblom
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 05/13] telemetry: add client feature and sockets Kevin Laatz
2018-10-22 14:05 ` Mattias Rönnblom
2018-10-23 8:42 ` Laatz, Kevin
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 06/13] telemetry: add parser for client socket messages Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 07/13] telemetry: update metrics before sending stats Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 08/13] telemetry: format json response when " Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 09/13] telemetry: add tests for telemetry api Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 10/13] telemetry: add ability to disable selftest Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 11/13] doc: add telemetry documentation Kevin Laatz
2018-10-22 12:25 ` Kovacevic, Marko
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 12/13] usertools: add client python script for telemetry Kevin Laatz
2018-10-22 11:00 ` [dpdk-dev] [PATCH v6 13/13] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 00/13] introduce telemetry library Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 01/13] eal: add option register infrastructure Kevin Laatz
2018-10-24 14:01 ` Gaëtan Rivet
2018-10-24 14:33 ` Thomas Monjalon
2018-10-24 14:52 ` Laatz, Kevin
2018-10-24 15:05 ` Laatz, Kevin
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 02/13] eal: make get runtime dir function public Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 03/13] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 04/13] telemetry: add initial connection socket Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 05/13] telemetry: add client feature and sockets Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 06/13] telemetry: add parser for client socket messages Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 07/13] telemetry: update metrics before sending stats Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 08/13] telemetry: format json response when " Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 09/13] telemetry: add tests for telemetry api Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 10/13] telemetry: add ability to disable selftest Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 11/13] doc: add telemetry documentation Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 12/13] usertools: add client python script for telemetry Kevin Laatz
2018-10-24 13:27 ` [dpdk-dev] [PATCH v7 13/13] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-24 14:13 ` [dpdk-dev] [PATCH v7 00/13] introduce telemetry library Thomas Monjalon
2018-10-24 14:49 ` Laatz, Kevin
2018-10-24 16:02 ` [dpdk-dev] [PATCH v8 " Kevin Laatz
2018-10-24 16:02 ` [dpdk-dev] [PATCH v8 01/13] eal: add option register infrastructure Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 02/13] eal: make get runtime dir function public Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 03/13] telemetry: initial telemetry infrastructure Kevin Laatz
2018-10-25 20:33 ` Thomas Monjalon
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 04/13] telemetry: add initial connection socket Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 05/13] telemetry: add client feature and sockets Kevin Laatz
2018-10-25 20:29 ` Thomas Monjalon
2018-10-25 20:41 ` Thomas Monjalon
2018-10-25 20:44 ` Bruce Richardson
2018-10-25 20:49 ` Thomas Monjalon
2018-10-25 21:16 ` Richardson, Bruce
2018-10-25 23:58 ` Thomas Monjalon
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 06/13] telemetry: add parser for client socket messages Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 07/13] telemetry: update metrics before sending stats Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 08/13] telemetry: format json response when " Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 09/13] telemetry: add tests for telemetry api Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 10/13] telemetry: add ability to disable selftest Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 11/13] doc: add telemetry documentation Kevin Laatz
2018-10-25 20:31 ` Thomas Monjalon
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 12/13] usertools: add client python script for telemetry Kevin Laatz
2018-10-24 16:03 ` [dpdk-dev] [PATCH v8 13/13] build: add dependency on telemetry to apps in meson Kevin Laatz
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 00/12] Introduce Telemetry Library Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 01/12] eal: add option register infrastructure Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 02/12] eal: make get runtime dir function public Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 03/12] telemetry: initial telemetry infrastructure Harry van Haaren
2018-10-27 1:56 ` Thomas Monjalon
2018-10-27 2:19 ` Van Haaren, Harry
2018-10-27 2:33 ` Thomas Monjalon
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 04/12] telemetry: add initial connection socket Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 05/12] telemetry: add client feature and sockets Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 06/12] telemetry: add parser for client socket messages Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 07/12] telemetry: update metrics before sending stats Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 08/12] telemetry: format json response when " Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 09/12] telemetry: add ability to disable selftest Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 10/12] doc: add telemetry documentation Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 11/12] usertools: add client python script for telemetry Harry van Haaren
2018-10-26 23:59 ` [dpdk-dev] [PATCH v9 12/12] build: add dependency on telemetry to apps in meson Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 00/12] Introduce Telemetry Library Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 01/12] eal: add option register infrastructure Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 02/12] eal: make get runtime dir function public Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 03/12] telemetry: initial telemetry infrastructure Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 04/12] telemetry: add initial connection socket Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 05/12] telemetry: add client feature and sockets Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 06/12] telemetry: add parser for client socket messages Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 07/12] telemetry: update metrics before sending stats Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 08/12] telemetry: format json response when " Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 09/12] telemetry: add ability to disable selftest Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 10/12] doc: add telemetry documentation Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 11/12] usertools: add client python script for telemetry Harry van Haaren
2018-10-27 9:17 ` [dpdk-dev] [PATCH v10 12/12] build: add dependency on telemetry to apps in meson Harry van Haaren
2018-10-27 13:24 ` [dpdk-dev] [PATCH v10 00/12] Introduce Telemetry Library Thomas Monjalon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181011165837.81030-10-kevin.laatz@intel.com \
--to=kevin.laatz@intel.com \
--cc=brian.archbold@intel.com \
--cc=bruce.richardson@intel.com \
--cc=ciara.power@intel.com \
--cc=dev@dpdk.org \
--cc=gaetan.rivet@6wind.com \
--cc=harry.van.haaren@intel.com \
--cc=mattias.ronnblom@ericsson.com \
--cc=shreyansh.jain@nxp.com \
--cc=stephen@networkplumber.org \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).