From patchwork Thu Mar 19 17:18:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66940 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0CB28A0583; Thu, 19 Mar 2020 18:35:03 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4082E1C027; Thu, 19 Mar 2020 18:34:57 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id AD024F90 for ; Thu, 19 Mar 2020 18:34:54 +0100 (CET) IronPort-SDR: rEb0Fv+V7Qv5jcqonJvpluwlGcoh1YzKkQBnfXTaEQ+ZF0WtZf7AWrxCCn5V1xRi7Ft9BzsCBe B3tsWOmY1uWA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:34:54 -0700 IronPort-SDR: MvvJzgLqIAKDGqTmp5p93lCb0oO18+Jv0gNEaDJm/7rmeuDCu2RmD6bKE85L3mAo/bu07h2fkA 9/ZFAKfHZpnw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872578" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:34:51 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power Date: Thu, 19 Mar 2020 17:18:56 +0000 Message-Id: <20200319171907.60891-2-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 01/12] telemetry: move code to metrics for later reuse X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This commit moves some of the telemetry library code to a new file in the metrics library. No modifications are made to the moved code, except what is needed to allow it to compile and run. The additional code in metrics is built only when the Jansson library is present. Telemetry functions as normal, using the functions from the metrics_telemetry file. This move will enable code be reused by the new version of telemetry in a later commit, to support backward compatibility with the existing telemetry usage. Signed-off-by: Ciara Power --- lib/Makefile | 2 +- lib/librte_metrics/Makefile | 13 + lib/librte_metrics/meson.build | 9 + lib/librte_metrics/rte_metrics.c | 1 - lib/librte_metrics/rte_metrics.h | 3 +- lib/librte_metrics/rte_metrics_telemetry.c | 719 ++++++++++++++++++ lib/librte_metrics/rte_metrics_telemetry.h | 71 ++ lib/librte_metrics/rte_metrics_version.map | 7 + lib/librte_telemetry/rte_telemetry.c | 550 +------------- lib/librte_telemetry/rte_telemetry_internal.h | 32 +- lib/librte_telemetry/rte_telemetry_parser.c | 270 +------ mk/rte.app.mk | 2 + mk/rte.vars.mk | 2 + 13 files changed, 864 insertions(+), 817 deletions(-) create mode 100644 lib/librte_metrics/rte_metrics_telemetry.c create mode 100644 lib/librte_metrics/rte_metrics_telemetry.h diff --git a/lib/Makefile b/lib/Makefile index 46b91ae1a..07b1ec0b6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -71,7 +71,7 @@ DEPDIRS-librte_gro := librte_eal librte_mbuf librte_ethdev librte_net DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DEPDIRS-librte_jobstats := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics -DEPDIRS-librte_metrics := librte_eal +DEPDIRS-librte_metrics := librte_eal librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats DEPDIRS-librte_bitratestats := librte_eal librte_metrics librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile index 6b385f5cf..455569948 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -7,6 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_metrics.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal EXPORT_MAP := rte_metrics_version.map @@ -14,6 +15,18 @@ EXPORT_MAP := rte_metrics_version.map # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c +JANSSON_CFLAGS=$(shell $(PKG_CONFIG) --cflags jansson 2> /dev/null) +JANSSON_LINK=$(shell $(PKG_CONFIG) --libs jansson 2> /dev/null) +ifneq ($(JANSSON_LINK),) +SRCS-y += rte_metrics_telemetry.c +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics_telemetry.h + +LDLIBS += -lrte_ethdev +LDLIBS += $(JANSSON_LINK) + +CFLAGS += $(JANSSON_CFLAGS) +endif + # Install header file SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build index e26d1f46c..0f9f2e0e6 100644 --- a/lib/librte_metrics/meson.build +++ b/lib/librte_metrics/meson.build @@ -1,5 +1,14 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation +allow_experimental_apis = true sources = files('rte_metrics.c') headers = files('rte_metrics.h') + +jansson = dependency('jansson', required: false) +if jansson.found() + ext_deps += jansson + sources += files('rte_metrics_telemetry.c') + headers = files('rte_metrics_telemetry.h') + deps += ['ethdev'] +endif diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c index df5e32c59..9b38d7787 100644 --- a/lib/librte_metrics/rte_metrics.c +++ b/lib/librte_metrics/rte_metrics.c @@ -13,7 +13,6 @@ #include #include -#define RTE_METRICS_MAX_METRICS 256 #define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" /** diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h index 77bffe08e..466ca98c3 100644 --- a/lib/librte_metrics/rte_metrics.h +++ b/lib/librte_metrics/rte_metrics.h @@ -32,6 +32,7 @@ extern "C" { /** Maximum length of metric name (including null-terminator) */ #define RTE_METRICS_MAX_NAME_LEN 64 +#define RTE_METRICS_MAX_METRICS 256 /** * Global metric special id. @@ -43,7 +44,6 @@ extern "C" { */ #define RTE_METRICS_GLOBAL -1 - /** * A name-key lookup for metrics. * @@ -71,7 +71,6 @@ struct rte_metric_value { uint64_t value; }; - /** * Initializes metric module. This function must be called from * a primary process before metrics are used. diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c new file mode 100644 index 000000000..a6b261671 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_telemetry.c @@ -0,0 +1,719 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include + +#include +#include + +#include "rte_metrics.h" +#include "rte_metrics_telemetry.h" + +int metrics_log_level; + +/* Logging Macros */ +#define METRICS_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ##level, metrics_log_level, "%s(): "fmt "\n", \ + __func__, ##args) + +#define METRICS_LOG_ERR(fmt, args...) \ + METRICS_LOG(ERR, fmt, ## args) + +#define METRICS_LOG_WARN(fmt, args...) \ + METRICS_LOG(WARNING, fmt, ## args) + +static int32_t +rte_metrics_tel_is_port_active(int port_id) +{ + int ret; + + ret = rte_eth_find_next(port_id); + if (ret == port_id) + return 1; + + METRICS_LOG_ERR("port_id: %d is invalid, not active", + port_id); + + return 0; +} + +static int32_t +rte_metrics_tel_reg_port_ethdev_to_metrics(uint16_t port_id) +{ + int ret, num_xstats, ret_val, i; + struct rte_eth_xstat *eth_xstats = NULL; + struct rte_eth_xstat_name *eth_xstats_names = NULL; + + if (!rte_eth_dev_is_valid_port(port_id)) { + METRICS_LOG_ERR("port_id: %d is invalid", port_id); + return -EINVAL; + } + + num_xstats = rte_eth_xstats_get(port_id, NULL, 0); + if (num_xstats < 0) { + METRICS_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", + port_id, num_xstats); + return -EPERM; + } + + eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); + if (eth_xstats == NULL) { + METRICS_LOG_ERR("Failed to malloc memory for xstats"); + return -ENOMEM; + } + + ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); + const char *xstats_names[num_xstats]; + eth_xstats_names = malloc(sizeof(struct rte_eth_xstat_name) + * num_xstats); + if (ret < 0 || ret > num_xstats) { + METRICS_LOG_ERR("rte_eth_xstats_get(%u) len%i failed: %d", + port_id, num_xstats, ret); + ret_val = -EPERM; + goto free_xstats; + } + + if (eth_xstats_names == NULL) { + METRICS_LOG_ERR("Failed to malloc memory for xstats_names"); + ret_val = -ENOMEM; + goto free_xstats; + } + + ret = rte_eth_xstats_get_names(port_id, eth_xstats_names, num_xstats); + if (ret < 0 || ret > num_xstats) { + METRICS_LOG_ERR("rte_eth_xstats_get_names(%u) len%i failed: %d", + port_id, num_xstats, ret); + ret_val = -EPERM; + goto free_xstats; + } + + for (i = 0; i < num_xstats; i++) + xstats_names[i] = eth_xstats_names[eth_xstats[i].id].name; + + ret_val = rte_metrics_reg_names(xstats_names, num_xstats); + if (ret_val < 0) { + METRICS_LOG_ERR("rte_metrics_reg_names failed - metrics may already be registered"); + ret_val = -1; + goto free_xstats; + } + + goto free_xstats; + +free_xstats: + free(eth_xstats); + free(eth_xstats_names); + return ret_val; +} + +int32_t +rte_metrics_tel_reg_all_ethdev(int *metrics_register_done, int *reg_index_list) +{ + struct driver_index { + const void *dev_ops; + int reg_index; + } drv_idx[RTE_MAX_ETHPORTS] = { {0} }; + int nb_drv_idx = 0; + uint16_t pid; + int ret; + + RTE_ETH_FOREACH_DEV(pid) { + int i; + /* Different device types have different numbers of stats, so + * first check if the stats for this type of device have + * already been registered + */ + for (i = 0; i < nb_drv_idx; i++) { + if (rte_eth_devices[pid].dev_ops == + drv_idx[i].dev_ops) { + reg_index_list[pid] = drv_idx[i].reg_index; + break; + } + } + if (i < nb_drv_idx) + continue; /* we found a match, go to next port */ + + /* No match, register a new set of xstats for this port */ + ret = rte_metrics_tel_reg_port_ethdev_to_metrics(pid); + if (ret < 0) { + METRICS_LOG_ERR("Failed to register ethdev metrics"); + return -1; + } + reg_index_list[pid] = ret; + drv_idx[nb_drv_idx].dev_ops = rte_eth_devices[pid].dev_ops; + drv_idx[nb_drv_idx].reg_index = ret; + nb_drv_idx++; + } + + *metrics_register_done = 1; + return 0; +} + +static int32_t +rte_metrics_tel_update_metrics_ethdev(uint16_t port_id, int reg_start_index) +{ + int ret, num_xstats, i; + struct rte_eth_xstat *eth_xstats; + + if (!rte_eth_dev_is_valid_port(port_id)) { + METRICS_LOG_ERR("port_id: %d is invalid", port_id); + return -EINVAL; + } + + ret = rte_metrics_tel_is_port_active(port_id); + if (ret < 1) + return -EINVAL; + + num_xstats = rte_eth_xstats_get(port_id, NULL, 0); + if (num_xstats < 0) { + METRICS_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", port_id, + num_xstats); + return -EPERM; + } + + eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); + if (eth_xstats == NULL) { + METRICS_LOG_ERR("Failed to malloc memory for xstats"); + return -ENOMEM; + } + + ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); + if (ret < 0 || ret > num_xstats) { + free(eth_xstats); + METRICS_LOG_ERR("rte_eth_xstats_get(%u) len%i failed: %d", + port_id, num_xstats, ret); + return -EPERM; + } + + uint64_t xstats_values[num_xstats]; + for (i = 0; i < num_xstats; i++) + xstats_values[i] = eth_xstats[i].value; + + ret = rte_metrics_update_values(port_id, reg_start_index, xstats_values, + num_xstats); + if (ret < 0) { + METRICS_LOG_ERR("Could not update metrics values"); + free(eth_xstats); + return -EPERM; + } + + free(eth_xstats); + return 0; +} + +static int +rte_metrics_tel_get_metrics(uint32_t port_id, struct rte_metric_value + *metrics, struct rte_metric_name *names, int num_metrics) +{ + int ret, num_values; + + if (num_metrics < 0) { + METRICS_LOG_ERR("Invalid metrics count"); + return -EINVAL; + } else if (num_metrics == 0) { + METRICS_LOG_ERR("No metrics to display (none have been registered)"); + return -EPERM; + } + + if (metrics == NULL) { + METRICS_LOG_ERR("Metrics must be initialised."); + return -EINVAL; + } + + if (names == NULL) { + METRICS_LOG_ERR("Names must be initialised."); + return -EINVAL; + } + + ret = rte_metrics_get_names(names, num_metrics); + if (ret < 0 || ret > num_metrics) { + METRICS_LOG_ERR("Cannot get metrics names"); + return -EPERM; + } + + num_values = rte_metrics_get_values(port_id, NULL, 0); + ret = rte_metrics_get_values(port_id, metrics, num_values); + if (ret < 0 || ret > num_values) { + METRICS_LOG_ERR("Cannot get metrics values"); + return -EPERM; + } + + return 0; +} + +static int32_t +rte_metrics_tel_json_format_stat(json_t *stats, const char *metric_name, + uint64_t metric_value) +{ + int ret; + json_t *stat = json_object(); + + if (stat == NULL) { + METRICS_LOG_ERR("Could not create stat JSON object"); + return -EPERM; + } + + ret = json_object_set_new(stat, "name", json_string(metric_name)); + if (ret < 0) { + METRICS_LOG_ERR("Stat Name field cannot be set"); + return -EPERM; + } + + ret = json_object_set_new(stat, "value", json_integer(metric_value)); + if (ret < 0) { + METRICS_LOG_ERR("Stat Value field cannot be set"); + return -EPERM; + } + + ret = json_array_append_new(stats, stat); + if (ret < 0) { + METRICS_LOG_ERR("Stat cannot be added to stats json array"); + return -EPERM; + } + + return 0; +} + +static int32_t +rte_metrics_tel_json_format_port(uint32_t port_id, json_t *ports, + uint32_t *metric_ids, int num_metric_ids) +{ + struct rte_metric_value *metrics = 0; + struct rte_metric_name *names = 0; + int num_metrics, ret; + json_t *port, *stats; + int i; + + num_metrics = rte_metrics_get_names(NULL, 0); + if (num_metrics < 0) { + METRICS_LOG_ERR("Cannot get metrics count"); + goto einval_fail; + } else if (num_metrics == 0) { + METRICS_LOG_ERR("No metrics to display (none have been registered)"); + goto eperm_fail; + } + + metrics = malloc(sizeof(struct rte_metric_value) * num_metrics); + names = malloc(sizeof(struct rte_metric_name) * num_metrics); + if (metrics == NULL || names == NULL) { + METRICS_LOG_ERR("Cannot allocate memory"); + free(metrics); + free(names); + return -ENOMEM; + } + + ret = rte_metrics_tel_get_metrics(port_id, metrics, names, + num_metrics); + if (ret < 0) { + free(metrics); + free(names); + METRICS_LOG_ERR("rte_metrics_tel_get_metrics failed"); + return ret; + } + + port = json_object(); + stats = json_array(); + if (port == NULL || stats == NULL) { + METRICS_LOG_ERR("Could not create port/stats JSON objects"); + goto eperm_fail; + } + + ret = json_object_set_new(port, "port", json_integer(port_id)); + if (ret < 0) { + METRICS_LOG_ERR("Port field cannot be set"); + goto eperm_fail; + } + + for (i = 0; i < num_metric_ids; i++) { + int metric_id = metric_ids[i]; + int metric_index = -1; + int metric_name_key = -1; + int32_t j; + uint64_t metric_value; + + if (metric_id >= num_metrics) { + METRICS_LOG_ERR("Metric_id: %d is not valid", + metric_id); + goto einval_fail; + } + + for (j = 0; j < num_metrics; j++) { + if (metrics[j].key == metric_id) { + metric_name_key = metrics[j].key; + metric_index = j; + break; + } + } + + const char *metric_name = names[metric_name_key].name; + metric_value = metrics[metric_index].value; + + if (metric_name_key < 0 || metric_index < 0) { + METRICS_LOG_ERR("Could not get metric name/index"); + goto eperm_fail; + } + + ret = rte_metrics_tel_json_format_stat(stats, metric_name, + metric_value); + if (ret < 0) { + METRICS_LOG_ERR("Format stat with id: %u failed", + metric_id); + free(metrics); + free(names); + return ret; + } + } + + if (json_array_size(stats) == 0) + ret = json_object_set_new(port, "stats", json_null()); + else + ret = json_object_set_new(port, "stats", stats); + + if (ret < 0) { + METRICS_LOG_ERR("Stats object cannot be set"); + goto eperm_fail; + } + + ret = json_array_append_new(ports, port); + if (ret < 0) { + METRICS_LOG_ERR("Port object cannot be added to ports array"); + goto eperm_fail; + } + + free(metrics); + free(names); + return 0; + +eperm_fail: + free(metrics); + free(names); + return -EPERM; + +einval_fail: + free(metrics); + free(names); + return -EINVAL; +} + +int32_t +rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, + char **json_buffer) +{ + int ret; + json_t *root, *ports; + int i; + uint32_t port_id; + int num_port_ids; + int num_metric_ids; + + ports = json_array(); + if (ports == NULL) { + METRICS_LOG_ERR("Could not create ports JSON array"); + return -EPERM; + } + + if (ep->type == PORT_STATS) { + num_port_ids = ep->pp.num_port_ids; + num_metric_ids = ep->pp.num_metric_ids; + + if (num_port_ids <= 0 || num_metric_ids <= 0) { + METRICS_LOG_ERR("Please provide port and metric ids to query"); + return -EINVAL; + } + + for (i = 0; i < num_port_ids; i++) { + port_id = ep->pp.port_ids[i]; + if (!rte_eth_dev_is_valid_port(port_id)) { + METRICS_LOG_ERR("Port: %d invalid", + port_id); + return -EINVAL; + } + } + + for (i = 0; i < num_port_ids; i++) { + port_id = ep->pp.port_ids[i]; + ret = rte_metrics_tel_json_format_port(port_id, + ports, &ep->pp.metric_ids[0], + num_metric_ids); + if (ret < 0) { + METRICS_LOG_ERR("Format port in JSON failed"); + return ret; + } + } + } else if (ep->type == GLOBAL_STATS) { + /* Request Global Metrics */ + ret = rte_metrics_tel_json_format_port(RTE_METRICS_GLOBAL, + ports, &ep->gp.metric_ids[0], + ep->gp.num_metric_ids); + if (ret < 0) { + METRICS_LOG_ERR(" Request Global Metrics Failed"); + return ret; + } + } else { + METRICS_LOG_ERR(" Invalid metrics type in encode params"); + return -EINVAL; + } + + root = json_object(); + if (root == NULL) { + METRICS_LOG_ERR("Could not create root JSON object"); + return -EPERM; + } + + ret = json_object_set_new(root, "status_code", + json_string("Status OK: 200")); + if (ret < 0) { + METRICS_LOG_ERR("Status code field cannot be set"); + return -EPERM; + } + + ret = json_object_set_new(root, "data", ports); + if (ret < 0) { + METRICS_LOG_ERR("Data field cannot be set"); + return -EPERM; + } + + *json_buffer = json_dumps(root, JSON_INDENT(2)); + json_decref(root); + return 0; +} + +int32_t +rte_metrics_tel_get_global_stats(struct telemetry_encode_param *ep) +{ + int num_metrics, ret, i; + struct rte_metric_value *values; + + num_metrics = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0); + if (num_metrics < 0) { + METRICS_LOG_ERR("Cannot get metrics count"); + return -EINVAL; + } else if (num_metrics == 0) { + METRICS_LOG_ERR("No metrics to display (none have been registered)"); + return -EPERM; + } + + values = malloc(sizeof(struct rte_metric_value) * num_metrics); + if (values == NULL) { + METRICS_LOG_ERR("Cannot allocate memory"); + return -ENOMEM; + } + + ret = rte_metrics_get_values(RTE_METRICS_GLOBAL, values, num_metrics); + if (ret < 0) { + METRICS_LOG_ERR("Could not get stat values"); + free(values); + return -EINVAL; + } + for (i = 0; i < num_metrics; i++) + ep->gp.metric_ids[i] = values[i].key; + + ep->gp.num_metric_ids = num_metrics; + ep->type = GLOBAL_STATS; + free(values); + return 0; +} + +int32_t +rte_metrics_tel_get_ports_stats_json(struct telemetry_encode_param *ep, + int *reg_index, char **json_buffer) +{ + int ret, i; + uint32_t port_id; + + for (i = 0; i < ep->pp.num_port_ids; i++) { + port_id = ep->pp.port_ids[i]; + if (!rte_eth_dev_is_valid_port(port_id)) { + METRICS_LOG_ERR("Port: %d invalid", port_id); + return -EINVAL; + } + + ret = rte_metrics_tel_update_metrics_ethdev(port_id, + reg_index[i]); + if (ret < 0) { + METRICS_LOG_ERR("Failed to update ethdev metrics"); + return ret; + } + } + + ret = rte_metrics_tel_encode_json_format(ep, json_buffer); + if (ret < 0) { + METRICS_LOG_ERR("JSON encode function failed"); + return ret; + } + return 0; +} + +int32_t +rte_metrics_tel_get_port_stats_ids(struct telemetry_encode_param *ep) +{ + int ret, num_metrics, i, p; + struct rte_metric_value *values; + uint64_t num_port_ids = 0; + + num_metrics = rte_metrics_get_values(0, NULL, 0); + if (num_metrics < 0) { + METRICS_LOG_ERR("Cannot get metrics count"); + return -EINVAL; + } else if (num_metrics == 0) { + METRICS_LOG_ERR("No metrics to display (none have been registered)"); + return -EPERM; + } + + values = malloc(sizeof(struct rte_metric_value) * num_metrics); + if (values == NULL) { + METRICS_LOG_ERR("Cannot allocate memory"); + return -ENOMEM; + } + + RTE_ETH_FOREACH_DEV(p) { + ep->pp.port_ids[num_port_ids] = p; + num_port_ids++; + } + + if (!num_port_ids) { + METRICS_LOG_ERR("No active ports"); + goto fail; + } + + ret = rte_metrics_get_values(ep->pp.port_ids[0], values, num_metrics); + if (ret < 0) { + METRICS_LOG_ERR("Could not get stat values"); + goto fail; + } + for (i = 0; i < num_metrics; i++) + ep->pp.metric_ids[i] = values[i].key; + + ep->pp.num_port_ids = num_port_ids; + ep->pp.num_metric_ids = num_metrics; + ep->type = PORT_STATS; + return 0; + +fail: + free(values); + return -EINVAL; +} + +static int32_t +rte_metrics_tel_stat_names_to_ids(const char * const *stat_names, + uint32_t *stat_ids, uint64_t num_stat_names) +{ + struct rte_metric_name *names; + int ret, num_metrics; + uint32_t i, k; + + if (stat_names == NULL) { + METRICS_LOG_WARN("Invalid stat_names argument"); + return -EINVAL; + } + + if (num_stat_names <= 0) { + METRICS_LOG_WARN("Invalid num_stat_names argument"); + return -EINVAL; + } + + num_metrics = rte_metrics_get_names(NULL, 0); + if (num_metrics < 0) { + METRICS_LOG_ERR("Cannot get metrics count"); + return -EPERM; + } else if (num_metrics == 0) { + METRICS_LOG_WARN("No metrics have been registered"); + return -EPERM; + } + + names = malloc(sizeof(struct rte_metric_name) * num_metrics); + if (names == NULL) { + METRICS_LOG_ERR("Cannot allocate memory for names"); + return -ENOMEM; + } + + ret = rte_metrics_get_names(names, num_metrics); + if (ret < 0 || ret > num_metrics) { + METRICS_LOG_ERR("Cannot get metrics names"); + free(names); + return -EPERM; + } + + k = 0; + for (i = 0; i < (uint32_t)num_stat_names; i++) { + uint32_t j; + for (j = 0; j < (uint32_t)num_metrics; j++) { + if (strcmp(stat_names[i], names[j].name) == 0) { + stat_ids[k] = j; + k++; + break; + } + } + } + + if (k != num_stat_names) { + METRICS_LOG_WARN("Invalid stat names provided"); + free(names); + return -EINVAL; + } + + free(names); + return 0; +} + +int32_t +rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data) +{ + int ret; + json_t *port_ids_json = json_object_get(data, "ports"); + json_t *stat_names_json = json_object_get(data, "stats"); + uint64_t num_stat_names = json_array_size(stat_names_json); + const char *stat_names[num_stat_names]; + size_t index; + json_t *value; + + memset(ep, 0, sizeof(*ep)); + ep->pp.num_port_ids = json_array_size(port_ids_json); + ep->pp.num_metric_ids = num_stat_names; + if (!json_is_object(data)) { + METRICS_LOG_WARN("Invalid data provided for this command"); + return -EINVAL; + } + + if (!json_is_array(port_ids_json) || + !json_is_array(stat_names_json)) { + METRICS_LOG_WARN("Invalid input data array(s)"); + return -EINVAL; + } + + json_array_foreach(port_ids_json, index, value) { + if (!json_is_integer(value)) { + METRICS_LOG_WARN("Port ID given is not valid"); + return -EINVAL; + } + ep->pp.port_ids[index] = json_integer_value(value); + ret = rte_metrics_tel_is_port_active(ep->pp.port_ids[index]); + if (ret < 1) + return -EINVAL; + } + + json_array_foreach(stat_names_json, index, value) { + if (!json_is_string(value)) { + METRICS_LOG_WARN("Stat Name given is not a string"); + return -EINVAL; + } + stat_names[index] = json_string_value(value); + } + + ret = rte_metrics_tel_stat_names_to_ids(stat_names, ep->pp.metric_ids, + num_stat_names); + if (ret < 0) { + METRICS_LOG_ERR("Could not convert stat names to IDs"); + return ret; + } + + ep->type = PORT_STATS; + return 0; +} + +RTE_INIT(metrics_ctor) +{ + metrics_log_level = rte_log_register("lib.metrics"); + if (metrics_log_level >= 0) + rte_log_set_level(metrics_log_level, RTE_LOG_ERR); +} diff --git a/lib/librte_metrics/rte_metrics_telemetry.h b/lib/librte_metrics/rte_metrics_telemetry.h new file mode 100644 index 000000000..4104f1568 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_telemetry.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#ifdef RTE_LIBRTE_TELEMETRY +#include +#else +#define json_t void * +#endif + +#include "rte_metrics.h" + +#ifndef _RTE_METRICS_TELEMETRY_H_ +#define _RTE_METRICS_TELEMETRY_H_ + + +enum rte_telemetry_stats_type { + PORT_STATS = 0, + GLOBAL_STATS = 1 +}; + +struct telemetry_encode_param { + enum rte_telemetry_stats_type type; + union { + struct port_param { + int num_metric_ids; + uint32_t metric_ids[RTE_METRICS_MAX_METRICS]; + int num_port_ids; + uint32_t port_ids[RTE_MAX_ETHPORTS]; + } pp; + struct global_param { + int num_metric_ids; + uint32_t metric_ids[RTE_METRICS_MAX_METRICS]; + } gp; + }; +}; + +struct telemetry_metrics_data { + int reg_index[RTE_MAX_ETHPORTS]; + int metrics_register_done; +}; + +struct telemetry_metrics_data tel_met_data; + +__rte_experimental +int32_t rte_metrics_tel_reg_all_ethdev(int *metrics_register_done, + int *reg_index_list); + +__rte_experimental +int32_t +rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, + char **json_buffer); + +__rte_experimental +int32_t +rte_metrics_tel_get_global_stats(struct telemetry_encode_param *ep); + +__rte_experimental +int32_t +rte_metrics_tel_get_port_stats_ids(struct telemetry_encode_param *ep); + +__rte_experimental +int32_t +rte_metrics_tel_get_ports_stats_json(struct telemetry_encode_param *ep, + int *reg_index, char **json_buffer); + +__rte_experimental +int32_t +rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map index 85663f356..c88939b11 100644 --- a/lib/librte_metrics/rte_metrics_version.map +++ b/lib/librte_metrics/rte_metrics_version.map @@ -16,4 +16,11 @@ EXPERIMENTAL { global: rte_metrics_deinit; + rte_metrics_tel_encode_json_format; + rte_metrics_tel_reg_all_ethdev; + rte_metrics_tel_get_global_stats; + rte_metrics_tel_get_port_stats_ids; + rte_metrics_tel_get_ports_stats_json; + rte_metrics_tel_extract_data; + }; diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c index eb20cc651..1867b61f6 100644 --- a/lib/librte_telemetry/rte_telemetry.c +++ b/lib/librte_telemetry/rte_telemetry.c @@ -49,93 +49,6 @@ rte_telemetry_get_runtime_dir(char *socket_path, size_t size) snprintf(socket_path, size, "%s/telemetry", rte_eal_get_runtime_dir()); } -int32_t -rte_telemetry_is_port_active(int port_id) -{ - int ret; - - ret = rte_eth_find_next(port_id); - if (ret == port_id) - return 1; - - TELEMETRY_LOG_ERR("port_id: %d is invalid, not active", - port_id); - - return 0; -} - -static int32_t -rte_telemetry_update_metrics_ethdev(struct telemetry_impl *telemetry, - uint16_t port_id, int reg_start_index) -{ - int ret, num_xstats, i; - struct rte_eth_xstat *eth_xstats; - - if (!rte_eth_dev_is_valid_port(port_id)) { - TELEMETRY_LOG_ERR("port_id: %d is invalid", port_id); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_is_port_active(port_id); - if (ret < 1) { - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - num_xstats = rte_eth_xstats_get(port_id, NULL, 0); - if (num_xstats < 0) { - TELEMETRY_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", port_id, - num_xstats); - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); - if (eth_xstats == NULL) { - TELEMETRY_LOG_ERR("Failed to malloc memory for xstats"); - ret = rte_telemetry_send_error_response(telemetry, -ENOMEM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); - if (ret < 0 || ret > num_xstats) { - free(eth_xstats); - TELEMETRY_LOG_ERR("rte_eth_xstats_get(%u) len%i failed: %d", - port_id, num_xstats, ret); - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - uint64_t xstats_values[num_xstats]; - for (i = 0; i < num_xstats; i++) - xstats_values[i] = eth_xstats[i].value; - - ret = rte_metrics_update_values(port_id, reg_start_index, xstats_values, - num_xstats); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not update metrics values"); - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - free(eth_xstats); - return -1; - } - - free(eth_xstats); - return 0; -} - static int32_t rte_telemetry_write_to_socket(struct telemetry_impl *telemetry, const char *json_string) @@ -220,328 +133,6 @@ rte_telemetry_send_error_response(struct telemetry_impl *telemetry, return 0; } -static int -rte_telemetry_get_metrics(struct telemetry_impl *telemetry, uint32_t port_id, - struct rte_metric_value *metrics, struct rte_metric_name *names, - int num_metrics) -{ - int ret, num_values; - - if (num_metrics < 0) { - TELEMETRY_LOG_ERR("Invalid metrics count"); - goto einval_fail; - } else if (num_metrics == 0) { - TELEMETRY_LOG_ERR("No metrics to display (none have been registered)"); - goto eperm_fail; - } - - if (metrics == NULL) { - TELEMETRY_LOG_ERR("Metrics must be initialised."); - goto einval_fail; - } - - if (names == NULL) { - TELEMETRY_LOG_ERR("Names must be initialised."); - goto einval_fail; - } - - ret = rte_metrics_get_names(names, num_metrics); - if (ret < 0 || ret > num_metrics) { - TELEMETRY_LOG_ERR("Cannot get metrics names"); - goto eperm_fail; - } - - num_values = rte_metrics_get_values(port_id, NULL, 0); - ret = rte_metrics_get_values(port_id, metrics, num_values); - if (ret < 0 || ret > num_values) { - TELEMETRY_LOG_ERR("Cannot get metrics values"); - goto eperm_fail; - } - - return 0; - -eperm_fail: - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -} - -static int32_t -rte_telemetry_json_format_stat(struct telemetry_impl *telemetry, json_t *stats, - const char *metric_name, uint64_t metric_value) -{ - int ret; - json_t *stat = json_object(); - - if (stat == NULL) { - TELEMETRY_LOG_ERR("Could not create stat JSON object"); - goto eperm_fail; - } - - ret = json_object_set_new(stat, "name", json_string(metric_name)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Stat Name field cannot be set"); - goto eperm_fail; - } - - ret = json_object_set_new(stat, "value", json_integer(metric_value)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Stat Value field cannot be set"); - goto eperm_fail; - } - - ret = json_array_append_new(stats, stat); - if (ret < 0) { - TELEMETRY_LOG_ERR("Stat cannot be added to stats json array"); - goto eperm_fail; - } - - return 0; - -eperm_fail: - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -} - -static int32_t -rte_telemetry_json_format_port(struct telemetry_impl *telemetry, - uint32_t port_id, json_t *ports, uint32_t *metric_ids, - int num_metric_ids) -{ - struct rte_metric_value *metrics = 0; - struct rte_metric_name *names = 0; - int num_metrics, ret, err_ret; - json_t *port, *stats; - int i; - - num_metrics = rte_metrics_get_names(NULL, 0); - if (num_metrics < 0) { - TELEMETRY_LOG_ERR("Cannot get metrics count"); - goto einval_fail; - } else if (num_metrics == 0) { - TELEMETRY_LOG_ERR("No metrics to display (none have been registered)"); - goto eperm_fail; - } - - metrics = malloc(sizeof(struct rte_metric_value) * num_metrics); - names = malloc(sizeof(struct rte_metric_name) * num_metrics); - if (metrics == NULL || names == NULL) { - TELEMETRY_LOG_ERR("Cannot allocate memory"); - free(metrics); - free(names); - - err_ret = rte_telemetry_send_error_response(telemetry, -ENOMEM); - if (err_ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_get_metrics(telemetry, port_id, metrics, names, - num_metrics); - if (ret < 0) { - free(metrics); - free(names); - TELEMETRY_LOG_ERR("rte_telemetry_get_metrics failed"); - return -1; - } - - port = json_object(); - stats = json_array(); - if (port == NULL || stats == NULL) { - TELEMETRY_LOG_ERR("Could not create port/stats JSON objects"); - goto eperm_fail; - } - - ret = json_object_set_new(port, "port", json_integer(port_id)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Port field cannot be set"); - goto eperm_fail; - } - - for (i = 0; i < num_metric_ids; i++) { - int metric_id = metric_ids[i]; - int metric_index = -1; - int metric_name_key = -1; - int32_t j; - uint64_t metric_value; - - if (metric_id >= num_metrics) { - TELEMETRY_LOG_ERR("Metric_id: %d is not valid", - metric_id); - goto einval_fail; - } - - for (j = 0; j < num_metrics; j++) { - if (metrics[j].key == metric_id) { - metric_name_key = metrics[j].key; - metric_index = j; - break; - } - } - - const char *metric_name = names[metric_name_key].name; - metric_value = metrics[metric_index].value; - - if (metric_name_key < 0 || metric_index < 0) { - TELEMETRY_LOG_ERR("Could not get metric name/index"); - goto eperm_fail; - } - - ret = rte_telemetry_json_format_stat(telemetry, stats, - metric_name, metric_value); - if (ret < 0) { - TELEMETRY_LOG_ERR("Format stat with id: %u failed", - metric_id); - free(metrics); - free(names); - return -1; - } - } - - if (json_array_size(stats) == 0) - ret = json_object_set_new(port, "stats", json_null()); - else - ret = json_object_set_new(port, "stats", stats); - - if (ret < 0) { - TELEMETRY_LOG_ERR("Stats object cannot be set"); - goto eperm_fail; - } - - ret = json_array_append_new(ports, port); - if (ret < 0) { - TELEMETRY_LOG_ERR("Port object cannot be added to ports array"); - goto eperm_fail; - } - - free(metrics); - free(names); - return 0; - -eperm_fail: - free(metrics); - free(names); - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -einval_fail: - free(metrics); - free(names); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_encode_json_format(struct telemetry_impl *telemetry, - struct telemetry_encode_param *ep, char **json_buffer) -{ - int ret; - json_t *root, *ports; - int i; - uint32_t port_id; - int num_port_ids; - int num_metric_ids; - - ports = json_array(); - if (ports == NULL) { - TELEMETRY_LOG_ERR("Could not create ports JSON array"); - goto eperm_fail; - } - - if (ep->type == PORT_STATS) { - num_port_ids = ep->pp.num_port_ids; - num_metric_ids = ep->pp.num_metric_ids; - - if (num_port_ids <= 0 || num_metric_ids <= 0) { - TELEMETRY_LOG_ERR("Please provide port and metric ids to query"); - goto einval_fail; - } - - for (i = 0; i < num_port_ids; i++) { - port_id = ep->pp.port_ids[i]; - if (!rte_eth_dev_is_valid_port(port_id)) { - TELEMETRY_LOG_ERR("Port: %d invalid", - port_id); - goto einval_fail; - } - } - - for (i = 0; i < num_port_ids; i++) { - port_id = ep->pp.port_ids[i]; - ret = rte_telemetry_json_format_port(telemetry, - port_id, ports, &ep->pp.metric_ids[0], - num_metric_ids); - if (ret < 0) { - TELEMETRY_LOG_ERR("Format port in JSON failed"); - return -1; - } - } - } else if (ep->type == GLOBAL_STATS) { - /* Request Global Metrics */ - ret = rte_telemetry_json_format_port(telemetry, - RTE_METRICS_GLOBAL, - ports, &ep->gp.metric_ids[0], - ep->gp.num_metric_ids); - if (ret < 0) { - TELEMETRY_LOG_ERR(" Request Global Metrics Failed"); - return -1; - } - } else { - TELEMETRY_LOG_ERR(" Invalid metrics type in encode params"); - goto einval_fail; - } - - root = json_object(); - if (root == NULL) { - TELEMETRY_LOG_ERR("Could not create root JSON object"); - goto eperm_fail; - } - - ret = json_object_set_new(root, "status_code", - json_string("Status OK: 200")); - if (ret < 0) { - TELEMETRY_LOG_ERR("Status code field cannot be set"); - goto eperm_fail; - } - - ret = json_object_set_new(root, "data", ports); - if (ret < 0) { - TELEMETRY_LOG_ERR("Data field cannot be set"); - goto eperm_fail; - } - - *json_buffer = json_dumps(root, JSON_INDENT(2)); - json_decref(root); - return 0; - -eperm_fail: - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - int32_t rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, struct telemetry_impl *telemetry) @@ -559,10 +150,12 @@ rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, goto einval_fail; } - ret = rte_telemetry_encode_json_format(telemetry, ep, - &json_buffer); + ret = rte_metrics_tel_encode_json_format(ep, &json_buffer); if (ret < 0) { TELEMETRY_LOG_ERR("JSON encode function failed"); + ret = rte_telemetry_send_error_response(telemetry, ret); + if (ret < 0) + TELEMETRY_LOG_ERR("Could not send error"); return -1; } @@ -587,8 +180,6 @@ rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, { int ret; char *json_buffer = NULL; - uint32_t port_id; - int i; if (telemetry == NULL) { TELEMETRY_LOG_ERR("Invalid telemetry argument"); @@ -610,24 +201,14 @@ rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, goto einval_fail; } - for (i = 0; i < ep->pp.num_port_ids; i++) { - port_id = ep->pp.port_ids[i]; - if (!rte_eth_dev_is_valid_port(port_id)) { - TELEMETRY_LOG_ERR("Port: %d invalid", port_id); - goto einval_fail; - } - - ret = rte_telemetry_update_metrics_ethdev(telemetry, - port_id, telemetry->reg_index[i]); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to update ethdev metrics"); - return -1; - } - } - - ret = rte_telemetry_encode_json_format(telemetry, ep, &json_buffer); + ret = rte_metrics_tel_get_ports_stats_json(ep, telemetry->reg_index, + &json_buffer); if (ret < 0) { - TELEMETRY_LOG_ERR("JSON encode function failed"); + TELEMETRY_LOG_ERR("Function for get_ports_stats_json" + " failed"); + ret = rte_telemetry_send_error_response(telemetry, ret); + if (ret < 0) + TELEMETRY_LOG_ERR("Could not send error"); return -1; } @@ -646,114 +227,23 @@ rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, return -1; } - -static int32_t -rte_telemetry_reg_ethdev_to_metrics(uint16_t port_id) -{ - int ret, num_xstats, ret_val, i; - struct rte_eth_xstat *eth_xstats = NULL; - struct rte_eth_xstat_name *eth_xstats_names = NULL; - - if (!rte_eth_dev_is_valid_port(port_id)) { - TELEMETRY_LOG_ERR("port_id: %d is invalid", port_id); - return -EINVAL; - } - - num_xstats = rte_eth_xstats_get(port_id, NULL, 0); - if (num_xstats < 0) { - TELEMETRY_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", - port_id, num_xstats); - return -EPERM; - } - - eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); - if (eth_xstats == NULL) { - TELEMETRY_LOG_ERR("Failed to malloc memory for xstats"); - return -ENOMEM; - } - - ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); - const char *xstats_names[num_xstats]; - eth_xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * num_xstats); - if (ret < 0 || ret > num_xstats) { - TELEMETRY_LOG_ERR("rte_eth_xstats_get(%u) len%i failed: %d", - port_id, num_xstats, ret); - ret_val = -EPERM; - goto free_xstats; - } - - if (eth_xstats_names == NULL) { - TELEMETRY_LOG_ERR("Failed to malloc memory for xstats_names"); - ret_val = -ENOMEM; - goto free_xstats; - } - - ret = rte_eth_xstats_get_names(port_id, eth_xstats_names, num_xstats); - if (ret < 0 || ret > num_xstats) { - TELEMETRY_LOG_ERR("rte_eth_xstats_get_names(%u) len%i failed: %d", - port_id, num_xstats, ret); - ret_val = -EPERM; - goto free_xstats; - } - - for (i = 0; i < num_xstats; i++) - xstats_names[i] = eth_xstats_names[eth_xstats[i].id].name; - - ret_val = rte_metrics_reg_names(xstats_names, num_xstats); - if (ret_val < 0) { - TELEMETRY_LOG_ERR("rte_metrics_reg_names failed - metrics may already be registered"); - ret_val = -1; - goto free_xstats; - } - - goto free_xstats; - -free_xstats: - free(eth_xstats); - free(eth_xstats_names); - return ret_val; -} - static int32_t rte_telemetry_initial_accept(struct telemetry_impl *telemetry) { - struct driver_index { - const void *dev_ops; - int reg_index; - } drv_idx[RTE_MAX_ETHPORTS] = { {0} }; - int nb_drv_idx = 0; - uint16_t pid; int ret; int selftest = 0; - RTE_ETH_FOREACH_DEV(pid) { - int i; - /* Different device types have different numbers of stats, so - * first check if the stats for this type of device have - * already been registered - */ - for (i = 0; i < nb_drv_idx; i++) { - if (rte_eth_devices[pid].dev_ops == drv_idx[i].dev_ops) { - telemetry->reg_index[pid] = drv_idx[i].reg_index; - break; - } - } - if (i < nb_drv_idx) - continue; /* we found a match, go to next port */ - - /* No match, register a new set of xstats for this port */ - ret = rte_telemetry_reg_ethdev_to_metrics(pid); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to register ethdev metrics"); - return -1; - } - telemetry->reg_index[pid] = ret; - drv_idx[nb_drv_idx].dev_ops = rte_eth_devices[pid].dev_ops; - drv_idx[nb_drv_idx].reg_index = ret; - nb_drv_idx++; + ret = rte_metrics_tel_reg_all_ethdev( + &telemetry->metrics_register_done, + telemetry->reg_index); + if (ret < 0) { + TELEMETRY_LOG_ERR("Failed to register ethdev metrics"); + ret = rte_telemetry_send_error_response(telemetry, ret); + if (ret < 0) + TELEMETRY_LOG_ERR("Could not send error"); + return -1; } - telemetry->metrics_register_done = 1; if (selftest) { ret = rte_telemetry_socket_messaging_testing(telemetry->reg_index[0], telemetry->server_fd); diff --git a/lib/librte_telemetry/rte_telemetry_internal.h b/lib/librte_telemetry/rte_telemetry_internal.h index 3f8dbc2db..ca70e2ed7 100644 --- a/lib/librte_telemetry/rte_telemetry_internal.h +++ b/lib/librte_telemetry/rte_telemetry_internal.h @@ -4,6 +4,8 @@ #include #include +#include +#include #ifndef _RTE_TELEMETRY_INTERNAL_H_ #define _RTE_TELEMETRY_INTERNAL_H_ @@ -50,28 +52,6 @@ enum rte_telemetry_parser_actions { ACTION_DELETE = 2 }; -enum rte_telemetry_stats_type { - PORT_STATS = 0, - GLOBAL_STATS = 1 -}; - -/* @internal */ -struct telemetry_encode_param { - enum rte_telemetry_stats_type type; - union { - struct port_param { - int num_metric_ids; - uint32_t metric_ids[MAX_METRICS]; - int num_port_ids; - uint32_t port_ids[RTE_MAX_ETHPORTS]; - } pp; - struct global_param { - int num_metric_ids; - uint32_t metric_ids[MAX_METRICS]; - } gp; - }; -}; - int32_t rte_telemetry_parse_client_message(struct telemetry_impl *telemetry, char *buf); @@ -87,14 +67,6 @@ int32_t rte_telemetry_unregister_client(struct telemetry_impl *telemetry, const char *client_path); -/** - * This is a wrapper for the ethdev api rte_eth_find_next(). - * If rte_eth_find_next() returns the same port id that we passed it, - * then we know that that port is active. - */ -int32_t -rte_telemetry_is_port_active(int port_id); - int32_t rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, struct telemetry_impl *telemetry); diff --git a/lib/librte_telemetry/rte_telemetry_parser.c b/lib/librte_telemetry/rte_telemetry_parser.c index e8c269e85..11edf79e8 100644 --- a/lib/librte_telemetry/rte_telemetry_parser.c +++ b/lib/librte_telemetry/rte_telemetry_parser.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "rte_telemetry_internal.h" #include "rte_telemetry_parser.h" @@ -172,93 +173,11 @@ rte_telemetry_command_port_stats(struct telemetry_impl *telemetry, int action, return -1; } -static int32_t -rte_telemetry_stat_names_to_ids(struct telemetry_impl *telemetry, - const char * const *stat_names, uint32_t *stat_ids, - uint64_t num_stat_names) -{ - struct rte_metric_name *names; - int ret, num_metrics; - uint32_t i, k; - - if (stat_names == NULL) { - TELEMETRY_LOG_WARN("Invalid stat_names argument"); - goto einval_fail; - } - - if (num_stat_names <= 0) { - TELEMETRY_LOG_WARN("Invalid num_stat_names argument"); - goto einval_fail; - } - - num_metrics = rte_metrics_get_names(NULL, 0); - if (num_metrics < 0) { - TELEMETRY_LOG_ERR("Cannot get metrics count"); - goto eperm_fail; - } else if (num_metrics == 0) { - TELEMETRY_LOG_WARN("No metrics have been registered"); - goto eperm_fail; - } - - names = malloc(sizeof(struct rte_metric_name) * num_metrics); - if (names == NULL) { - TELEMETRY_LOG_ERR("Cannot allocate memory for names"); - - ret = rte_telemetry_send_error_response(telemetry, -ENOMEM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } - - ret = rte_metrics_get_names(names, num_metrics); - if (ret < 0 || ret > num_metrics) { - TELEMETRY_LOG_ERR("Cannot get metrics names"); - free(names); - goto eperm_fail; - } - - k = 0; - for (i = 0; i < (uint32_t)num_stat_names; i++) { - uint32_t j; - for (j = 0; j < (uint32_t)num_metrics; j++) { - if (strcmp(stat_names[i], names[j].name) == 0) { - stat_ids[k] = j; - k++; - break; - } - } - } - - if (k != num_stat_names) { - TELEMETRY_LOG_WARN("Invalid stat names provided"); - free(names); - goto einval_fail; - } - - free(names); - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - -eperm_fail: - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - static int32_t rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry, int action, json_t *data) { - int ret, num_metrics, i, p; - struct rte_metric_value *values; - uint64_t num_port_ids = 0; + int ret; struct telemetry_encode_param ep; memset(&ep, 0, sizeof(ep)); @@ -283,85 +202,29 @@ rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry, return -1; } - num_metrics = rte_metrics_get_values(0, NULL, 0); - if (num_metrics < 0) { - TELEMETRY_LOG_ERR("Cannot get metrics count"); - - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } else if (num_metrics == 0) { - TELEMETRY_LOG_ERR("No metrics to display (none have been registered)"); - - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } - - values = malloc(sizeof(struct rte_metric_value) * num_metrics); - if (values == NULL) { - TELEMETRY_LOG_ERR("Cannot allocate memory"); - ret = rte_telemetry_send_error_response(telemetry, - -ENOMEM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - RTE_ETH_FOREACH_DEV(p) { - ep.pp.port_ids[num_port_ids] = p; - num_port_ids++; - } - - if (!num_port_ids) { - TELEMETRY_LOG_WARN("No active ports"); - - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - goto fail; - } - - ret = rte_metrics_get_values(ep.pp.port_ids[0], values, num_metrics); + ret = rte_metrics_tel_get_port_stats_ids(&ep); if (ret < 0) { - TELEMETRY_LOG_ERR("Could not get stat values"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); + TELEMETRY_LOG_ERR("Could not get ports stat values"); + ret = rte_telemetry_send_error_response(telemetry, ret); if (ret < 0) TELEMETRY_LOG_ERR("Could not send error"); - goto fail; + return -1; } - for (i = 0; i < num_metrics; i++) - ep.pp.metric_ids[i] = values[i].key; - - ep.pp.num_port_ids = num_port_ids; - ep.pp.num_metric_ids = num_metrics; - ep.type = PORT_STATS; ret = rte_telemetry_send_ports_stats_values(&ep, telemetry); if (ret < 0) { TELEMETRY_LOG_ERR("Sending ports stats values failed"); - goto fail; + return -1; } - free(values); return 0; - -fail: - free(values); - return -1; } static int32_t rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry, int action, json_t *data) { - int ret, num_metrics, i; - struct rte_metric_value *values; + int ret; struct telemetry_encode_param ep; memset(&ep, 0, sizeof(ep)); @@ -386,61 +249,22 @@ rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry, return -1; } - num_metrics = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0); - if (num_metrics < 0) { - TELEMETRY_LOG_ERR("Cannot get metrics count"); - - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } else if (num_metrics == 0) { - TELEMETRY_LOG_ERR("No metrics to display (none have been registered)"); - - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } - - values = malloc(sizeof(struct rte_metric_value) * num_metrics); - if (values == NULL) { - TELEMETRY_LOG_ERR("Cannot allocate memory"); - ret = rte_telemetry_send_error_response(telemetry, - -ENOMEM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_metrics_get_values(RTE_METRICS_GLOBAL, values, num_metrics); + ret = rte_metrics_tel_get_global_stats(&ep); if (ret < 0) { - TELEMETRY_LOG_ERR("Could not get stat values"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); + TELEMETRY_LOG_ERR("Could not get global stat values"); + ret = rte_telemetry_send_error_response(telemetry, ret); if (ret < 0) TELEMETRY_LOG_ERR("Could not send error"); - goto fail; + return -1; } - for (i = 0; i < num_metrics; i++) - ep.gp.metric_ids[i] = values[i].key; - - ep.gp.num_metric_ids = num_metrics; - ep.type = GLOBAL_STATS; ret = rte_telemetry_send_global_stats_values(&ep, telemetry); if (ret < 0) { TELEMETRY_LOG_ERR("Sending global stats values failed"); - goto fail; + return -1; } - free(values); return 0; - -fail: - free(values); - return -1; } static int32_t @@ -448,17 +272,7 @@ rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl *telemetry, int action, json_t *data) { int ret; - json_t *port_ids_json = json_object_get(data, "ports"); - json_t *stat_names_json = json_object_get(data, "stats"); - uint64_t num_stat_names = json_array_size(stat_names_json); - const char *stat_names[num_stat_names]; struct telemetry_encode_param ep; - size_t index; - json_t *value; - - memset(&ep, 0, sizeof(ep)); - ep.pp.num_port_ids = json_array_size(port_ids_json); - ep.pp.num_metric_ids = num_stat_names; if (telemetry == NULL) { TELEMETRY_LOG_ERR("Invalid telemetry argument"); return -1; @@ -472,65 +286,15 @@ rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl return -1; } - if (!json_is_object(data)) { - TELEMETRY_LOG_WARN("Invalid data provided for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - if (!json_is_array(port_ids_json) || - !json_is_array(stat_names_json)) { - TELEMETRY_LOG_WARN("Invalid input data array(s)"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); + ret = rte_metrics_tel_extract_data(&ep, data); + if (ret < 0) { + TELEMETRY_LOG_ERR("Extracting JSON data failed"); + ret = rte_telemetry_send_error_response(telemetry, ret); if (ret < 0) TELEMETRY_LOG_ERR("Could not send error"); return -1; } - json_array_foreach(port_ids_json, index, value) { - if (!json_is_integer(value)) { - TELEMETRY_LOG_WARN("Port ID given is not valid"); - ret = rte_telemetry_send_error_response(telemetry, - -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - ep.pp.port_ids[index] = json_integer_value(value); - ret = rte_telemetry_is_port_active(ep.pp.port_ids[index]); - if (ret < 1) { - ret = rte_telemetry_send_error_response(telemetry, - -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - } - - json_array_foreach(stat_names_json, index, value) { - if (!json_is_string(value)) { - TELEMETRY_LOG_WARN("Stat Name given is not a string"); - - ret = rte_telemetry_send_error_response(telemetry, - -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; - } - stat_names[index] = json_string_value(value); - } - - ret = rte_telemetry_stat_names_to_ids(telemetry, stat_names, - ep.pp.metric_ids, num_stat_names); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not convert stat names to IDs"); - return -1; - } - - ep.type = PORT_STATS; ret = rte_telemetry_send_ports_stats_values(&ep, telemetry); if (ret < 0) { TELEMETRY_LOG_ERR("Sending ports stats values failed"); diff --git a/mk/rte.app.mk b/mk/rte.app.mk index d295ca0a5..e68368614 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -55,7 +55,9 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += -lrte_telemetry -ljansson _LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --no-whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --as-needed _LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += -lrte_jobstats +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += --no-whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_POWER) += -lrte_power diff --git a/mk/rte.vars.mk b/mk/rte.vars.mk index 07b0db127..c16786960 100644 --- a/mk/rte.vars.mk +++ b/mk/rte.vars.mk @@ -100,3 +100,5 @@ include $(RTE_SDK)/mk/target/$(RTE_TARGET)/rte.vars.mk else include $(RTE_SDK)/mk/target/generic/rte.vars.mk endif + +PKG_CONFIG?=$(CROSS)pkg-config From patchwork Thu Mar 19 17:18:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66941 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id C0F76A0583; Thu, 19 Mar 2020 18:35:25 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7D3551C067; Thu, 19 Mar 2020 18:34:59 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 1599B1C025 for ; Thu, 19 Mar 2020 18:34:56 +0100 (CET) IronPort-SDR: qd6zt0jCdvjEAH8WJdz16iqofGcSQa9FqOKbz3kUYwYdrkN9+1dUZtNOQ7N624rZsMlUav9Ztf ovE1r5hopWAg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:34:56 -0700 IronPort-SDR: 8bHBNbYJX/2BTFi/rKx+yoD1L0t6gMrTu3InEhHwsu326DKQuRjh3qctsRWfx7rzEck6U6s4sM VinsvnRSa4FA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872599" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:34:54 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power , Bruce Richardson Date: Thu, 19 Mar 2020 17:18:57 +0000 Message-Id: <20200319171907.60891-3-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 02/12] metrics: reduce code taken from telemetry X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The telemetry code that was moved into the metrics library can be shortened, while still maintaining the same functionality. Signed-off-by: Ciara Power Signed-off-by: Bruce Richardson --- lib/librte_metrics/rte_metrics_telemetry.c | 476 ++++---------------- lib/librte_metrics/rte_metrics_telemetry.h | 18 +- lib/librte_telemetry/rte_telemetry.c | 11 - lib/librte_telemetry/rte_telemetry_parser.c | 12 +- 4 files changed, 96 insertions(+), 421 deletions(-) diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c index a6b261671..78c21663d 100644 --- a/lib/librte_metrics/rte_metrics_telemetry.c +++ b/lib/librte_metrics/rte_metrics_telemetry.c @@ -23,33 +23,12 @@ int metrics_log_level; #define METRICS_LOG_WARN(fmt, args...) \ METRICS_LOG(WARNING, fmt, ## args) -static int32_t -rte_metrics_tel_is_port_active(int port_id) -{ - int ret; - - ret = rte_eth_find_next(port_id); - if (ret == port_id) - return 1; - - METRICS_LOG_ERR("port_id: %d is invalid, not active", - port_id); - - return 0; -} - static int32_t rte_metrics_tel_reg_port_ethdev_to_metrics(uint16_t port_id) { - int ret, num_xstats, ret_val, i; - struct rte_eth_xstat *eth_xstats = NULL; + int ret, num_xstats, i; struct rte_eth_xstat_name *eth_xstats_names = NULL; - if (!rte_eth_dev_is_valid_port(port_id)) { - METRICS_LOG_ERR("port_id: %d is invalid", port_id); - return -EINVAL; - } - num_xstats = rte_eth_xstats_get(port_id, NULL, 0); if (num_xstats < 0) { METRICS_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", @@ -57,53 +36,32 @@ rte_metrics_tel_reg_port_ethdev_to_metrics(uint16_t port_id) return -EPERM; } - eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); - if (eth_xstats == NULL) { - METRICS_LOG_ERR("Failed to malloc memory for xstats"); - return -ENOMEM; - } - - ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); const char *xstats_names[num_xstats]; eth_xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * num_xstats); - if (ret < 0 || ret > num_xstats) { - METRICS_LOG_ERR("rte_eth_xstats_get(%u) len%i failed: %d", - port_id, num_xstats, ret); - ret_val = -EPERM; - goto free_xstats; - } - if (eth_xstats_names == NULL) { METRICS_LOG_ERR("Failed to malloc memory for xstats_names"); - ret_val = -ENOMEM; + ret = -ENOMEM; goto free_xstats; } - ret = rte_eth_xstats_get_names(port_id, eth_xstats_names, num_xstats); - if (ret < 0 || ret > num_xstats) { - METRICS_LOG_ERR("rte_eth_xstats_get_names(%u) len%i failed: %d", - port_id, num_xstats, ret); - ret_val = -EPERM; + if (rte_eth_xstats_get_names(port_id, + eth_xstats_names, num_xstats) != num_xstats) { + METRICS_LOG_ERR("rte_eth_xstats_get_names(%u) len %d failed", + port_id, num_xstats); + ret = -EPERM; goto free_xstats; } for (i = 0; i < num_xstats; i++) - xstats_names[i] = eth_xstats_names[eth_xstats[i].id].name; - - ret_val = rte_metrics_reg_names(xstats_names, num_xstats); - if (ret_val < 0) { + xstats_names[i] = eth_xstats_names[i].name; + ret = rte_metrics_reg_names(xstats_names, num_xstats); + if (ret < 0) METRICS_LOG_ERR("rte_metrics_reg_names failed - metrics may already be registered"); - ret_val = -1; - goto free_xstats; - } - - goto free_xstats; free_xstats: - free(eth_xstats); free(eth_xstats_names); - return ret_val; + return ret; } int32_t @@ -113,20 +71,18 @@ rte_metrics_tel_reg_all_ethdev(int *metrics_register_done, int *reg_index_list) const void *dev_ops; int reg_index; } drv_idx[RTE_MAX_ETHPORTS] = { {0} }; - int nb_drv_idx = 0; - uint16_t pid; - int ret; + int ret, nb_drv_idx = 0; + uint16_t d; - RTE_ETH_FOREACH_DEV(pid) { + RTE_ETH_FOREACH_DEV(d) { int i; /* Different device types have different numbers of stats, so * first check if the stats for this type of device have * already been registered */ for (i = 0; i < nb_drv_idx; i++) { - if (rte_eth_devices[pid].dev_ops == - drv_idx[i].dev_ops) { - reg_index_list[pid] = drv_idx[i].reg_index; + if (rte_eth_devices[d].dev_ops == drv_idx[i].dev_ops) { + reg_index_list[d] = drv_idx[i].reg_index; break; } } @@ -134,17 +90,16 @@ rte_metrics_tel_reg_all_ethdev(int *metrics_register_done, int *reg_index_list) continue; /* we found a match, go to next port */ /* No match, register a new set of xstats for this port */ - ret = rte_metrics_tel_reg_port_ethdev_to_metrics(pid); + ret = rte_metrics_tel_reg_port_ethdev_to_metrics(d); if (ret < 0) { - METRICS_LOG_ERR("Failed to register ethdev metrics"); - return -1; + METRICS_LOG_ERR("Failed to register ethdev to metrics"); + return ret; } - reg_index_list[pid] = ret; - drv_idx[nb_drv_idx].dev_ops = rte_eth_devices[pid].dev_ops; + reg_index_list[d] = ret; + drv_idx[nb_drv_idx].dev_ops = rte_eth_devices[d].dev_ops; drv_idx[nb_drv_idx].reg_index = ret; nb_drv_idx++; } - *metrics_register_done = 1; return 0; } @@ -155,28 +110,17 @@ rte_metrics_tel_update_metrics_ethdev(uint16_t port_id, int reg_start_index) int ret, num_xstats, i; struct rte_eth_xstat *eth_xstats; - if (!rte_eth_dev_is_valid_port(port_id)) { - METRICS_LOG_ERR("port_id: %d is invalid", port_id); - return -EINVAL; - } - - ret = rte_metrics_tel_is_port_active(port_id); - if (ret < 1) - return -EINVAL; - num_xstats = rte_eth_xstats_get(port_id, NULL, 0); if (num_xstats < 0) { METRICS_LOG_ERR("rte_eth_xstats_get(%u) failed: %d", port_id, num_xstats); return -EPERM; } - eth_xstats = malloc(sizeof(struct rte_eth_xstat) * num_xstats); if (eth_xstats == NULL) { METRICS_LOG_ERR("Failed to malloc memory for xstats"); return -ENOMEM; } - ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); if (ret < 0 || ret > num_xstats) { free(eth_xstats); @@ -188,223 +132,96 @@ rte_metrics_tel_update_metrics_ethdev(uint16_t port_id, int reg_start_index) uint64_t xstats_values[num_xstats]; for (i = 0; i < num_xstats; i++) xstats_values[i] = eth_xstats[i].value; - - ret = rte_metrics_update_values(port_id, reg_start_index, xstats_values, - num_xstats); - if (ret < 0) { + if (rte_metrics_update_values(port_id, reg_start_index, xstats_values, + num_xstats) < 0) { METRICS_LOG_ERR("Could not update metrics values"); free(eth_xstats); return -EPERM; } - free(eth_xstats); return 0; } -static int -rte_metrics_tel_get_metrics(uint32_t port_id, struct rte_metric_value - *metrics, struct rte_metric_name *names, int num_metrics) -{ - int ret, num_values; - - if (num_metrics < 0) { - METRICS_LOG_ERR("Invalid metrics count"); - return -EINVAL; - } else if (num_metrics == 0) { - METRICS_LOG_ERR("No metrics to display (none have been registered)"); - return -EPERM; - } - - if (metrics == NULL) { - METRICS_LOG_ERR("Metrics must be initialised."); - return -EINVAL; - } - - if (names == NULL) { - METRICS_LOG_ERR("Names must be initialised."); - return -EINVAL; - } - - ret = rte_metrics_get_names(names, num_metrics); - if (ret < 0 || ret > num_metrics) { - METRICS_LOG_ERR("Cannot get metrics names"); - return -EPERM; - } - - num_values = rte_metrics_get_values(port_id, NULL, 0); - ret = rte_metrics_get_values(port_id, metrics, num_values); - if (ret < 0 || ret > num_values) { - METRICS_LOG_ERR("Cannot get metrics values"); - return -EPERM; - } - - return 0; -} - static int32_t -rte_metrics_tel_json_format_stat(json_t *stats, const char *metric_name, - uint64_t metric_value) -{ - int ret; - json_t *stat = json_object(); - - if (stat == NULL) { - METRICS_LOG_ERR("Could not create stat JSON object"); - return -EPERM; - } - - ret = json_object_set_new(stat, "name", json_string(metric_name)); - if (ret < 0) { - METRICS_LOG_ERR("Stat Name field cannot be set"); - return -EPERM; - } - - ret = json_object_set_new(stat, "value", json_integer(metric_value)); - if (ret < 0) { - METRICS_LOG_ERR("Stat Value field cannot be set"); - return -EPERM; - } - - ret = json_array_append_new(stats, stat); - if (ret < 0) { - METRICS_LOG_ERR("Stat cannot be added to stats json array"); - return -EPERM; - } - - return 0; -} - -static int32_t -rte_metrics_tel_json_format_port(uint32_t port_id, json_t *ports, +rte_metrics_tel_format_port(uint32_t pid, json_t *ports, uint32_t *metric_ids, int num_metric_ids) { - struct rte_metric_value *metrics = 0; - struct rte_metric_name *names = 0; - int num_metrics, ret; + struct rte_metric_value *metrics = NULL; + struct rte_metric_name *names = NULL; + int num_metrics, i, ret = -EPERM; /* most error cases return EPERM */ json_t *port, *stats; - int i; num_metrics = rte_metrics_get_names(NULL, 0); if (num_metrics < 0) { METRICS_LOG_ERR("Cannot get metrics count"); - goto einval_fail; + return -EINVAL; } else if (num_metrics == 0) { METRICS_LOG_ERR("No metrics to display (none have been registered)"); - goto eperm_fail; + return -EPERM; } metrics = malloc(sizeof(struct rte_metric_value) * num_metrics); names = malloc(sizeof(struct rte_metric_name) * num_metrics); if (metrics == NULL || names == NULL) { METRICS_LOG_ERR("Cannot allocate memory"); - free(metrics); - free(names); return -ENOMEM; } - ret = rte_metrics_tel_get_metrics(port_id, metrics, names, - num_metrics); - if (ret < 0) { - free(metrics); - free(names); - METRICS_LOG_ERR("rte_metrics_tel_get_metrics failed"); - return ret; + if (rte_metrics_get_names(names, num_metrics) != num_metrics || + rte_metrics_get_values(pid, metrics, num_metrics) + != num_metrics) { + METRICS_LOG_ERR("Error getting metrics"); + goto fail; } - port = json_object(); stats = json_array(); - if (port == NULL || stats == NULL) { - METRICS_LOG_ERR("Could not create port/stats JSON objects"); - goto eperm_fail; - } - - ret = json_object_set_new(port, "port", json_integer(port_id)); - if (ret < 0) { - METRICS_LOG_ERR("Port field cannot be set"); - goto eperm_fail; + if (stats == NULL) { + METRICS_LOG_ERR("Could not create stats JSON object"); + goto fail; } - for (i = 0; i < num_metric_ids; i++) { - int metric_id = metric_ids[i]; - int metric_index = -1; - int metric_name_key = -1; + for (i = 0; i < num_metrics; i++) { int32_t j; - uint64_t metric_value; - - if (metric_id >= num_metrics) { - METRICS_LOG_ERR("Metric_id: %d is not valid", - metric_id); - goto einval_fail; - } - - for (j = 0; j < num_metrics; j++) { - if (metrics[j].key == metric_id) { - metric_name_key = metrics[j].key; - metric_index = j; + for (j = 0; j < num_metric_ids; j++) + if (metrics[i].key == metric_ids[j]) break; - } - } - - const char *metric_name = names[metric_name_key].name; - metric_value = metrics[metric_index].value; - if (metric_name_key < 0 || metric_index < 0) { - METRICS_LOG_ERR("Could not get metric name/index"); - goto eperm_fail; - } + if (num_metric_ids > 0 && j == num_metric_ids) + continue; /* can't find this id */ - ret = rte_metrics_tel_json_format_stat(stats, metric_name, - metric_value); - if (ret < 0) { + json_t *stat = json_pack("{s,s,s,I}", + "name", names[metrics[i].key].name, + "value", metrics[i].value); + if (stat == NULL || json_array_append_new(stats, stat) < 0) { METRICS_LOG_ERR("Format stat with id: %u failed", - metric_id); - free(metrics); - free(names); - return ret; + metrics[i].key); + goto fail; } } - if (json_array_size(stats) == 0) - ret = json_object_set_new(port, "stats", json_null()); - else - ret = json_object_set_new(port, "stats", stats); - - if (ret < 0) { - METRICS_LOG_ERR("Stats object cannot be set"); - goto eperm_fail; - } - - ret = json_array_append_new(ports, port); - if (ret < 0) { - METRICS_LOG_ERR("Port object cannot be added to ports array"); - goto eperm_fail; + port = json_pack("{s,i,s,o}", "port", pid, "stats", + json_array_size(stats) ? stats : json_null()); + if (port == NULL || json_array_append_new(ports, port) < 0) { + METRICS_LOG_ERR("Error creating port and adding to ports"); + goto fail; } free(metrics); free(names); return 0; -eperm_fail: - free(metrics); - free(names); - return -EPERM; - -einval_fail: +fail: free(metrics); free(names); - return -EINVAL; + return ret; } int32_t rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, char **json_buffer) { - int ret; json_t *root, *ports; - int i; - uint32_t port_id; - int num_port_ids; - int num_metric_ids; + int ret, i; ports = json_array(); if (ports == NULL) { @@ -413,28 +230,15 @@ rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, } if (ep->type == PORT_STATS) { - num_port_ids = ep->pp.num_port_ids; - num_metric_ids = ep->pp.num_metric_ids; - - if (num_port_ids <= 0 || num_metric_ids <= 0) { - METRICS_LOG_ERR("Please provide port and metric ids to query"); + if (ep->pp.num_port_ids <= 0) { + METRICS_LOG_ERR("Please provide port/metric ids"); return -EINVAL; } - for (i = 0; i < num_port_ids; i++) { - port_id = ep->pp.port_ids[i]; - if (!rte_eth_dev_is_valid_port(port_id)) { - METRICS_LOG_ERR("Port: %d invalid", - port_id); - return -EINVAL; - } - } - - for (i = 0; i < num_port_ids; i++) { - port_id = ep->pp.port_ids[i]; - ret = rte_metrics_tel_json_format_port(port_id, + for (i = 0; i < ep->pp.num_port_ids; i++) { + ret = rte_metrics_tel_format_port(ep->pp.port_ids[i], ports, &ep->pp.metric_ids[0], - num_metric_ids); + ep->pp.num_metric_ids); if (ret < 0) { METRICS_LOG_ERR("Format port in JSON failed"); return ret; @@ -442,34 +246,21 @@ rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, } } else if (ep->type == GLOBAL_STATS) { /* Request Global Metrics */ - ret = rte_metrics_tel_json_format_port(RTE_METRICS_GLOBAL, - ports, &ep->gp.metric_ids[0], - ep->gp.num_metric_ids); + ret = rte_metrics_tel_format_port(RTE_METRICS_GLOBAL, + ports, NULL, 0); if (ret < 0) { - METRICS_LOG_ERR(" Request Global Metrics Failed"); + METRICS_LOG_ERR("Request Global Metrics Failed"); return ret; } } else { - METRICS_LOG_ERR(" Invalid metrics type in encode params"); + METRICS_LOG_ERR("Invalid metrics type in encode params"); return -EINVAL; } - root = json_object(); + root = json_pack("{s,s,s,o}", "status_code", "Status OK: 200", + "data", ports); if (root == NULL) { - METRICS_LOG_ERR("Could not create root JSON object"); - return -EPERM; - } - - ret = json_object_set_new(root, "status_code", - json_string("Status OK: 200")); - if (ret < 0) { - METRICS_LOG_ERR("Status code field cannot be set"); - return -EPERM; - } - - ret = json_object_set_new(root, "data", ports); - if (ret < 0) { - METRICS_LOG_ERR("Data field cannot be set"); + METRICS_LOG_ERR("Root, Status or data field cannot be set"); return -EPERM; } @@ -478,42 +269,6 @@ rte_metrics_tel_encode_json_format(struct telemetry_encode_param *ep, return 0; } -int32_t -rte_metrics_tel_get_global_stats(struct telemetry_encode_param *ep) -{ - int num_metrics, ret, i; - struct rte_metric_value *values; - - num_metrics = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0); - if (num_metrics < 0) { - METRICS_LOG_ERR("Cannot get metrics count"); - return -EINVAL; - } else if (num_metrics == 0) { - METRICS_LOG_ERR("No metrics to display (none have been registered)"); - return -EPERM; - } - - values = malloc(sizeof(struct rte_metric_value) * num_metrics); - if (values == NULL) { - METRICS_LOG_ERR("Cannot allocate memory"); - return -ENOMEM; - } - - ret = rte_metrics_get_values(RTE_METRICS_GLOBAL, values, num_metrics); - if (ret < 0) { - METRICS_LOG_ERR("Could not get stat values"); - free(values); - return -EINVAL; - } - for (i = 0; i < num_metrics; i++) - ep->gp.metric_ids[i] = values[i].key; - - ep->gp.num_metric_ids = num_metrics; - ep->type = GLOBAL_STATS; - free(values); - return 0; -} - int32_t rte_metrics_tel_get_ports_stats_json(struct telemetry_encode_param *ep, int *reg_index, char **json_buffer) @@ -547,24 +302,7 @@ rte_metrics_tel_get_ports_stats_json(struct telemetry_encode_param *ep, int32_t rte_metrics_tel_get_port_stats_ids(struct telemetry_encode_param *ep) { - int ret, num_metrics, i, p; - struct rte_metric_value *values; - uint64_t num_port_ids = 0; - - num_metrics = rte_metrics_get_values(0, NULL, 0); - if (num_metrics < 0) { - METRICS_LOG_ERR("Cannot get metrics count"); - return -EINVAL; - } else if (num_metrics == 0) { - METRICS_LOG_ERR("No metrics to display (none have been registered)"); - return -EPERM; - } - - values = malloc(sizeof(struct rte_metric_value) * num_metrics); - if (values == NULL) { - METRICS_LOG_ERR("Cannot allocate memory"); - return -ENOMEM; - } + int p, num_port_ids = 0; RTE_ETH_FOREACH_DEV(p) { ep->pp.port_ids[num_port_ids] = p; @@ -573,51 +311,26 @@ rte_metrics_tel_get_port_stats_ids(struct telemetry_encode_param *ep) if (!num_port_ids) { METRICS_LOG_ERR("No active ports"); - goto fail; - } - - ret = rte_metrics_get_values(ep->pp.port_ids[0], values, num_metrics); - if (ret < 0) { - METRICS_LOG_ERR("Could not get stat values"); - goto fail; + return -EINVAL; } - for (i = 0; i < num_metrics; i++) - ep->pp.metric_ids[i] = values[i].key; ep->pp.num_port_ids = num_port_ids; - ep->pp.num_metric_ids = num_metrics; + ep->pp.num_metric_ids = 0; ep->type = PORT_STATS; return 0; - -fail: - free(values); - return -EINVAL; } static int32_t rte_metrics_tel_stat_names_to_ids(const char * const *stat_names, - uint32_t *stat_ids, uint64_t num_stat_names) + uint32_t *stat_ids, int num_stat_names) { struct rte_metric_name *names; - int ret, num_metrics; - uint32_t i, k; - - if (stat_names == NULL) { - METRICS_LOG_WARN("Invalid stat_names argument"); - return -EINVAL; - } - - if (num_stat_names <= 0) { - METRICS_LOG_WARN("Invalid num_stat_names argument"); - return -EINVAL; - } + int num_metrics; + int i, j, nb_stat_ids = 0; num_metrics = rte_metrics_get_names(NULL, 0); - if (num_metrics < 0) { - METRICS_LOG_ERR("Cannot get metrics count"); - return -EPERM; - } else if (num_metrics == 0) { - METRICS_LOG_WARN("No metrics have been registered"); + if (num_metrics <= 0) { + METRICS_LOG_ERR("Error getting metrics count - no metrics may be registered"); return -EPERM; } @@ -627,29 +340,25 @@ rte_metrics_tel_stat_names_to_ids(const char * const *stat_names, return -ENOMEM; } - ret = rte_metrics_get_names(names, num_metrics); - if (ret < 0 || ret > num_metrics) { + if (rte_metrics_get_names(names, num_metrics) != num_metrics) { METRICS_LOG_ERR("Cannot get metrics names"); free(names); return -EPERM; } - k = 0; - for (i = 0; i < (uint32_t)num_stat_names; i++) { - uint32_t j; - for (j = 0; j < (uint32_t)num_metrics; j++) { + for (i = 0; i < num_stat_names; i++) { + for (j = 0; j < num_metrics; j++) { if (strcmp(stat_names[i], names[j].name) == 0) { - stat_ids[k] = j; - k++; + stat_ids[nb_stat_ids++] = j; break; } } - } - - if (k != num_stat_names) { - METRICS_LOG_WARN("Invalid stat names provided"); - free(names); - return -EINVAL; + if (j == num_metrics) { + METRICS_LOG_WARN("Invalid stat name %s\n", + stat_names[i]); + free(names); + return -EINVAL; + } } free(names); @@ -670,28 +379,21 @@ rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data) memset(ep, 0, sizeof(*ep)); ep->pp.num_port_ids = json_array_size(port_ids_json); ep->pp.num_metric_ids = num_stat_names; - if (!json_is_object(data)) { + if (!json_is_object(data) || !json_is_array(port_ids_json) || + !json_is_array(stat_names_json)) { METRICS_LOG_WARN("Invalid data provided for this command"); return -EINVAL; } - if (!json_is_array(port_ids_json) || - !json_is_array(stat_names_json)) { - METRICS_LOG_WARN("Invalid input data array(s)"); - return -EINVAL; - } - json_array_foreach(port_ids_json, index, value) { if (!json_is_integer(value)) { METRICS_LOG_WARN("Port ID given is not valid"); return -EINVAL; } ep->pp.port_ids[index] = json_integer_value(value); - ret = rte_metrics_tel_is_port_active(ep->pp.port_ids[index]); - if (ret < 1) + if (rte_eth_dev_is_valid_port(ep->pp.port_ids[index]) < 1) return -EINVAL; } - json_array_foreach(stat_names_json, index, value) { if (!json_is_string(value)) { METRICS_LOG_WARN("Stat Name given is not a string"); diff --git a/lib/librte_metrics/rte_metrics_telemetry.h b/lib/librte_metrics/rte_metrics_telemetry.h index 4104f1568..6c2391c56 100644 --- a/lib/librte_metrics/rte_metrics_telemetry.h +++ b/lib/librte_metrics/rte_metrics_telemetry.h @@ -21,18 +21,12 @@ enum rte_telemetry_stats_type { struct telemetry_encode_param { enum rte_telemetry_stats_type type; - union { - struct port_param { - int num_metric_ids; - uint32_t metric_ids[RTE_METRICS_MAX_METRICS]; - int num_port_ids; - uint32_t port_ids[RTE_MAX_ETHPORTS]; - } pp; - struct global_param { - int num_metric_ids; - uint32_t metric_ids[RTE_METRICS_MAX_METRICS]; - } gp; - }; + struct port_param { + int num_metric_ids; + uint32_t metric_ids[RTE_METRICS_MAX_METRICS]; + int num_port_ids; + uint32_t port_ids[RTE_MAX_ETHPORTS]; + } pp; }; struct telemetry_metrics_data { diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c index 1867b61f6..2022ce68e 100644 --- a/lib/librte_telemetry/rte_telemetry.c +++ b/lib/librte_telemetry/rte_telemetry.c @@ -145,11 +145,6 @@ rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, return -1; } - if (ep->gp.num_metric_ids < 0) { - TELEMETRY_LOG_ERR("Invalid num_metric_ids, must be positive"); - goto einval_fail; - } - ret = rte_metrics_tel_encode_json_format(ep, &json_buffer); if (ret < 0) { TELEMETRY_LOG_ERR("JSON encode function failed"); @@ -166,12 +161,6 @@ rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, } return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; } int32_t diff --git a/lib/librte_telemetry/rte_telemetry_parser.c b/lib/librte_telemetry/rte_telemetry_parser.c index 11edf79e8..4e236e1e6 100644 --- a/lib/librte_telemetry/rte_telemetry_parser.c +++ b/lib/librte_telemetry/rte_telemetry_parser.c @@ -225,9 +225,8 @@ rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry, int action, json_t *data) { int ret; - struct telemetry_encode_param ep; + struct telemetry_encode_param ep = { .type = GLOBAL_STATS }; - memset(&ep, 0, sizeof(ep)); if (telemetry == NULL) { TELEMETRY_LOG_ERR("Invalid telemetry argument"); return -1; @@ -249,15 +248,6 @@ rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry, return -1; } - ret = rte_metrics_tel_get_global_stats(&ep); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not get global stat values"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - ret = rte_telemetry_send_global_stats_values(&ep, telemetry); if (ret < 0) { TELEMETRY_LOG_ERR("Sending global stats values failed"); From patchwork Thu Mar 19 17:18:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66942 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B1416A0583; Thu, 19 Mar 2020 18:35:40 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id ECB721C06D; Thu, 19 Mar 2020 18:35:00 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id C88181C036 for ; Thu, 19 Mar 2020 18:34:58 +0100 (CET) IronPort-SDR: jk+AkQ50hbPyeumV8DJ27h0icr4+Y3k2xlnTFEgAm5xdQ53ijCY1Lg6D7K0PBbYDdV5VzZgiz1 +OHxdoOekAKA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:34:58 -0700 IronPort-SDR: EQGlc/uzOMAQYFoTNJ54gI4gO3xhmqqJNWtrFOBZPgJHqdn85YZAHz59YJSkxaEjyx9Od8nrGV JN3F+J9f7wng== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872615" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:34:56 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Bruce Richardson Date: Thu, 19 Mar 2020 17:18:58 +0000 Message-Id: <20200319171907.60891-4-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 03/12] telemetry: invert dependency on metrics X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson Rather than having the telemetry library depend on the metrics lib we invert the dependency so that metrics instead depends on telemetry lib, and registers the needed functions with it at init time. This prepares the way for a cleaner telemetry architecture to be applied in later patches. Signed-off-by: Bruce Richardson --- lib/Makefile | 7 +++-- lib/librte_metrics/Makefile | 1 + lib/librte_metrics/meson.build | 2 +- lib/librte_metrics/rte_metrics.c | 5 ++++ lib/librte_metrics/rte_metrics.h | 2 ++ lib/librte_metrics/rte_metrics_telemetry.c | 14 +++++++++ lib/librte_telemetry/Makefile | 3 +- lib/librte_telemetry/meson.build | 2 +- lib/librte_telemetry/rte_telemetry.c | 19 ++++++++---- lib/librte_telemetry/rte_telemetry_internal.h | 30 +++++++++++++++++++ lib/librte_telemetry/rte_telemetry_parser.c | 5 ++-- .../rte_telemetry_version.map | 1 + lib/meson.build | 3 +- mk/rte.app.mk | 6 +--- 14 files changed, 80 insertions(+), 20 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 07b1ec0b6..31b943817 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -22,6 +22,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile DEPDIRS-librte_cfgfile := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DEPDIRS-librte_cmdline := librte_eal librte_net +DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry +DEPDIRS-librte_telemetry := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ethdev DEPDIRS-librte_ethdev := librte_net librte_eal librte_mempool librte_ring DEPDIRS-librte_ethdev += librte_mbuf @@ -72,6 +74,9 @@ DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DEPDIRS-librte_jobstats := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DEPDIRS-librte_metrics := librte_eal librte_ethdev +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +DEPDIRS-librte_metrics += librte_telemetry +endif DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats DEPDIRS-librte_bitratestats := librte_eal librte_metrics librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats @@ -114,8 +119,6 @@ DEPDIRS-librte_bpf := librte_eal librte_mempool librte_mbuf librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += librte_ipsec DEPDIRS-librte_ipsec := librte_eal librte_mbuf librte_cryptodev librte_security \ librte_net -DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry -DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_RCU) += librte_rcu DEPDIRS-librte_rcu := librte_eal diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile index 455569948..fa762ba37 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -25,6 +25,7 @@ LDLIBS += -lrte_ethdev LDLIBS += $(JANSSON_LINK) CFLAGS += $(JANSSON_CFLAGS) +CFLAGS += -I$(RTE_SDK)/lib/librte_telemetry/ endif # Install header file diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build index 0f9f2e0e6..d116857e2 100644 --- a/lib/librte_metrics/meson.build +++ b/lib/librte_metrics/meson.build @@ -10,5 +10,5 @@ if jansson.found() ext_deps += jansson sources += files('rte_metrics_telemetry.c') headers = files('rte_metrics_telemetry.h') - deps += ['ethdev'] + deps += ['ethdev', 'telemetry'] endif diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c index 9b38d7787..e07670219 100644 --- a/lib/librte_metrics/rte_metrics.c +++ b/lib/librte_metrics/rte_metrics.c @@ -13,6 +13,8 @@ #include #include +int metrics_initialized; + #define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" /** @@ -60,6 +62,8 @@ rte_metrics_init(int socket_id) struct rte_metrics_data_s *stats; const struct rte_memzone *memzone; + if (metrics_initialized) + return; if (rte_eal_process_type() != RTE_PROC_PRIMARY) return; @@ -73,6 +77,7 @@ rte_metrics_init(int socket_id) stats = memzone->addr; memset(stats, 0, sizeof(struct rte_metrics_data_s)); rte_spinlock_init(&stats->lock); + metrics_initialized = 1; } int diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h index 466ca98c3..fbe64ddf2 100644 --- a/lib/librte_metrics/rte_metrics.h +++ b/lib/librte_metrics/rte_metrics.h @@ -30,6 +30,8 @@ extern "C" { #endif +extern int metrics_initialized; + /** Maximum length of metric name (including null-terminator) */ #define RTE_METRICS_MAX_NAME_LEN 64 #define RTE_METRICS_MAX_METRICS 256 diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c index 78c21663d..31d505551 100644 --- a/lib/librte_metrics/rte_metrics_telemetry.c +++ b/lib/librte_metrics/rte_metrics_telemetry.c @@ -6,6 +6,9 @@ #include #include +#ifdef RTE_LIBRTE_TELEMETRY +#include +#endif #include "rte_metrics.h" #include "rte_metrics_telemetry.h" @@ -74,6 +77,7 @@ rte_metrics_tel_reg_all_ethdev(int *metrics_register_done, int *reg_index_list) int ret, nb_drv_idx = 0; uint16_t d; + rte_metrics_init(rte_socket_id()); RTE_ETH_FOREACH_DEV(d) { int i; /* Different device types have different numbers of stats, so @@ -415,6 +419,16 @@ rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data) RTE_INIT(metrics_ctor) { +#ifdef RTE_LIBRTE_TELEMETRY + static const struct metrics_functions fns = { + .reg_all_ethdev = rte_metrics_tel_reg_all_ethdev, + .encode_json_format = rte_metrics_tel_encode_json_format, + .get_port_stats_ids = rte_metrics_tel_get_port_stats_ids, + .get_ports_stats_json = rte_metrics_tel_get_ports_stats_json, + .extract_data = rte_metrics_tel_extract_data + }; + rte_telemetry_set_metrics_fns(&fns); /* assign them to telemetry lib */ +#endif metrics_log_level = rte_log_register("lib.metrics"); if (metrics_log_level >= 0) rte_log_set_level(metrics_log_level, RTE_LOG_ERR); diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index f36454855..17e651c41 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -9,8 +9,9 @@ LIB = librte_telemetry.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) CFLAGS += -DALLOW_EXPERIMENTAL_API +CFLAGS += -I$(RTE_SDK)/lib/librte_metrics/ -LDLIBS += -lrte_eal -lrte_ethdev +LDLIBS += -lrte_eal LDLIBS += -lrte_metrics LDLIBS += -lpthread LDLIBS += -ljansson diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build index 26a331140..b34661ac1 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -3,8 +3,8 @@ 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') -deps += ['metrics', 'ethdev'] cflags += '-DALLOW_EXPERIMENTAL_API' +includes += include_directories('../librte_metrics') jansson = dependency('jansson', required: false) if jansson.found() diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c index 2022ce68e..2fb8ffe87 100644 --- a/lib/librte_telemetry/rte_telemetry.c +++ b/lib/librte_telemetry/rte_telemetry.c @@ -10,10 +10,10 @@ #include #include -#include #include #include #include +#include #include "rte_telemetry.h" #include "rte_telemetry_internal.h" @@ -43,6 +43,15 @@ struct json_data { int stat_value; }; +/* global array of functions pointers to metrics library */ +const struct metrics_functions *metrics_fns; + +void +rte_telemetry_set_metrics_fns(const struct metrics_functions *fns) +{ + metrics_fns = fns; +} + static void rte_telemetry_get_runtime_dir(char *socket_path, size_t size) { @@ -145,7 +154,7 @@ rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, return -1; } - ret = rte_metrics_tel_encode_json_format(ep, &json_buffer); + ret = metrics_fns->encode_json_format(ep, &json_buffer); if (ret < 0) { TELEMETRY_LOG_ERR("JSON encode function failed"); ret = rte_telemetry_send_error_response(telemetry, ret); @@ -190,7 +199,7 @@ rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, goto einval_fail; } - ret = rte_metrics_tel_get_ports_stats_json(ep, telemetry->reg_index, + ret = metrics_fns->get_ports_stats_json(ep, telemetry->reg_index, &json_buffer); if (ret < 0) { TELEMETRY_LOG_ERR("Function for get_ports_stats_json" @@ -222,8 +231,7 @@ rte_telemetry_initial_accept(struct telemetry_impl *telemetry) int ret; int selftest = 0; - ret = rte_metrics_tel_reg_all_ethdev( - &telemetry->metrics_register_done, + ret = metrics_fns->reg_all_ethdev(&telemetry->metrics_register_done, telemetry->reg_index); if (ret < 0) { TELEMETRY_LOG_ERR("Failed to register ethdev metrics"); @@ -467,7 +475,6 @@ rte_telemetry_init(void) } static_telemetry->socket_id = rte_socket_id(); - rte_metrics_init(static_telemetry->socket_id); ret = pthread_attr_init(&attr); if (ret != 0) { diff --git a/lib/librte_telemetry/rte_telemetry_internal.h b/lib/librte_telemetry/rte_telemetry_internal.h index ca70e2ed7..2ef72b1ec 100644 --- a/lib/librte_telemetry/rte_telemetry_internal.h +++ b/lib/librte_telemetry/rte_telemetry_internal.h @@ -10,6 +10,36 @@ #ifndef _RTE_TELEMETRY_INTERNAL_H_ #define _RTE_TELEMETRY_INTERNAL_H_ +/* function types for the functions coming from metrics library */ +typedef int32_t (*metrics_tel_reg_all_ethdev_t)(int *metrics_register_done, + int *reg_index_list); + +typedef int32_t (*metrics_tel_encode_json_format_t)( + struct telemetry_encode_param *ep, char **json_buffer); + +typedef int32_t (*metrics_tel_get_port_stats_ids_t)( + struct telemetry_encode_param *ep); + +typedef int32_t (*metrics_tel_get_ports_stats_json_t)( + struct telemetry_encode_param *ep, + int *reg_index, char **json_buffer); + +typedef int32_t (*metrics_tel_extract_data_t)(struct telemetry_encode_param *ep, + json_t *data); + +struct metrics_functions { + metrics_tel_reg_all_ethdev_t reg_all_ethdev; + metrics_tel_encode_json_format_t encode_json_format; + metrics_tel_get_port_stats_ids_t get_port_stats_ids; + metrics_tel_get_ports_stats_json_t get_ports_stats_json; + metrics_tel_extract_data_t extract_data; +}; +extern const struct metrics_functions *metrics_fns; + +/* API for use by metrics libraries to provide the functions to use */ +__rte_experimental +void rte_telemetry_set_metrics_fns(const struct metrics_functions *fns); + /* Logging Macros */ extern int telemetry_log_level; diff --git a/lib/librte_telemetry/rte_telemetry_parser.c b/lib/librte_telemetry/rte_telemetry_parser.c index 4e236e1e6..7dc84c2cf 100644 --- a/lib/librte_telemetry/rte_telemetry_parser.c +++ b/lib/librte_telemetry/rte_telemetry_parser.c @@ -10,7 +10,6 @@ #include #include -#include #include #include "rte_telemetry_internal.h" @@ -202,7 +201,7 @@ rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry, return -1; } - ret = rte_metrics_tel_get_port_stats_ids(&ep); + ret = metrics_fns->get_port_stats_ids(&ep); if (ret < 0) { TELEMETRY_LOG_ERR("Could not get ports stat values"); ret = rte_telemetry_send_error_response(telemetry, ret); @@ -276,7 +275,7 @@ rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl return -1; } - ret = rte_metrics_tel_extract_data(&ep, data); + ret = metrics_fns->extract_data(&ep, data); if (ret < 0) { TELEMETRY_LOG_ERR("Extracting JSON data failed"); ret = rte_telemetry_send_error_response(telemetry, ret); diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map index fa62d7718..a80058c59 100644 --- a/lib/librte_telemetry/rte_telemetry_version.map +++ b/lib/librte_telemetry/rte_telemetry_version.map @@ -5,6 +5,7 @@ EXPERIMENTAL { rte_telemetry_init; rte_telemetry_parse; rte_telemetry_selftest; + rte_telemetry_set_metrics_fns; local: *; }; diff --git a/lib/meson.build b/lib/meson.build index 0af3efab2..77bed670e 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -11,6 +11,7 @@ libraries = [ 'kvargs', # eal depends on kvargs 'eal', # everything depends on eal + 'telemetry', 'ring', 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core 'cmdline', 'metrics', # bitrate/latency stats depends on this @@ -30,7 +31,7 @@ libraries = [ # add pkt framework libs which use other libs from above 'port', 'table', 'pipeline', # flow_classify lib depends on pkt framework table lib - 'flow_classify', 'bpf', 'telemetry'] + 'flow_classify', 'bpf'] if is_windows libraries = ['kvargs','eal'] # only supported libraries for windows diff --git a/mk/rte.app.mk b/mk/rte.app.mk index e68368614..fdaf3ec2c 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -49,11 +49,6 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_FIB) += -lrte_fib _LDLIBS-$(CONFIG_RTE_LIBRTE_RIB) += -lrte_rib _LDLIBS-$(CONFIG_RTE_LIBRTE_LPM) += -lrte_lpm _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += -lrte_acl -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --no-as-needed -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --whole-archive -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += -lrte_telemetry -ljansson -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --no-whole-archive -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += --as-needed _LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += -lrte_jobstats _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics @@ -95,6 +90,7 @@ _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING) += -lrte_mempool_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_MEMPOOL) += -lrte_mempool_octeontx2 _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci +_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += -lrte_telemetry -ljansson _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder From patchwork Thu Mar 19 17:18:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66943 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 15848A0583; Thu, 19 Mar 2020 18:35:59 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B4A7A1C0AD; Thu, 19 Mar 2020 18:35:02 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 283541C07D for ; Thu, 19 Mar 2020 18:35:01 +0100 (CET) IronPort-SDR: JwoTLHjsh6+V1OseFk+WaohS0fUQ++C1b99awvyx+4nkowEust+XQkTWFGyFybJ+uR8M3GDUwE 1i1X30+/4+ug== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:00 -0700 IronPort-SDR: 2hHjiUkxc73fZ25jhuRVw2ta9W+mo/gQ70PKddWDbnasIR8CTMEfKDo3kCfKwA3WRVjppqIcgt JV2vd7X0TnFQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872635" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:34:58 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Bruce Richardson , Ciara Power Date: Thu, 19 Mar 2020 17:18:59 +0000 Message-Id: <20200319171907.60891-5-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 04/12] telemetry: introduce new telemetry functionality X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson This patch introduces a new telemetry connection socket and handling functionality. Like the existing telemetry implementation (which is unaffected by this change) it uses a unix socket, but unlike the existing one it does not have a fixed list of commands - instead libraries or applications can register telemetry commands and callbacks to provide a full-extensible solution for all kinds of telemetry across DPDK. Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- lib/librte_telemetry/Makefile | 4 + lib/librte_telemetry/meson.build | 6 +- lib/librte_telemetry/rte_telemetry.c | 3 + lib/librte_telemetry/rte_telemetry.h | 59 ++++ .../rte_telemetry_version.map | 2 + lib/librte_telemetry/telemetry.c | 257 ++++++++++++++++++ 6 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 lib/librte_telemetry/telemetry.c diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index 17e651c41..b34fe90d4 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -10,6 +10,9 @@ CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -I$(RTE_SDK)/lib/librte_metrics/ +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/ +CFLAGS += -pthread LDLIBS += -lrte_eal LDLIBS += -lrte_metrics @@ -22,6 +25,7 @@ EXPORT_MAP := rte_telemetry_version.map 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 # 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 b34661ac1..49c947120 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -1,7 +1,11 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation -sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c') +includes = [global_inc] +includes += include_directories('../librte_eal/common/include/arch/' + arch_subdir) + +sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c', + 'telemetry.c') headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h') cflags += '-DALLOW_EXPERIMENTAL_API' includes += include_directories('../librte_metrics') diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c index 2fb8ffe87..45b6d9d94 100644 --- a/lib/librte_telemetry/rte_telemetry.c +++ b/lib/librte_telemetry/rte_telemetry.c @@ -503,6 +503,9 @@ rte_telemetry_init(void) return -EPERM; } + if (rte_telemetry_new_init() != 0) + return -1; + return 0; } diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h index aedb31859..060613117 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -3,10 +3,13 @@ */ #include +#include #ifndef _RTE_TELEMETRY_H_ #define _RTE_TELEMETRY_H_ +#define TELEMETRY_MAX_CALLBACKS 64 + /** * @file * RTE Telemetry @@ -16,6 +19,33 @@ * a JSON encoded response containing telemetry data. ***/ +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * This telemetry callback is used when registering a command. + * It handles getting and formatting stats to be returned to telemetry when + * requested. Stats up to buf_len in length are put in the buffer. + * + * @return + * Length of buffer used on success. + * @return + * Negative integer on error. + */ +typedef int (*telemetry_cb)(const char *cmd, const char *params, + char *buffer, int buf_len); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Used for handling data received over a telemetry socket. + * + * @return + * Void. + */ +typedef void * (*handler)(void *sock_id); + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice @@ -66,4 +96,33 @@ __rte_experimental int32_t rte_telemetry_selftest(void); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Used when registering a command and callback function with telemetry. + * + * @return + * 0 on success. + * @return + * -EINVAL for invalid parameters failure. + * @return + * -ENOENT if max callbacks limit has been reached. + */ +__rte_experimental +int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Initialize new version of Telemetry. + * + * @return + * 0 on success. + * @return + * -1 on failure. + */ +__rte_experimental +int rte_telemetry_new_init(void); #endif diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map index a80058c59..831bbd59a 100644 --- a/lib/librte_telemetry/rte_telemetry_version.map +++ b/lib/librte_telemetry/rte_telemetry_version.map @@ -6,6 +6,8 @@ EXPERIMENTAL { rte_telemetry_parse; rte_telemetry_selftest; rte_telemetry_set_metrics_fns; + rte_telemetry_new_init; + rte_telemetry_register_cmd; local: *; }; diff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c new file mode 100644 index 000000000..1ad784f59 --- /dev/null +++ b/lib/librte_telemetry/telemetry.c @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include +#include +#include +#include +#include + +/* we won't link against libbsd, so just always use DPDKs-specific strlcpy */ +#undef RTE_USE_LIBBSD +#include +#include +#include + +#include "rte_telemetry.h" + +#define MAX_CMD_LEN 56 + +static int +list_commands(const char *cmd __rte_unused, const char *params __rte_unused, + char *buffer, int buf_len); + +static void * +client_handler(void *socket); + +struct cmd_callback { + char cmd[MAX_CMD_LEN]; + telemetry_cb fn; +}; + +struct socket { + int sock; + char path[sizeof(((struct sockaddr_un *)0)->sun_path)]; + handler fn; +}; +static struct socket v2_socket; /* socket for v2 telemetry */ +static char telemetry_log_error[1024]; /* Will contain error on init failure */ +/* list of command callbacks, with one command registered by default */ +static struct cmd_callback callbacks[TELEMETRY_MAX_CALLBACKS] = { + { .cmd = "/", .fn = list_commands }, +}; +static int num_callbacks = 1; /* How many commands are registered */ +/* Used when accessing or modifying list of command callbacks */ +static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER; + +int +rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn) +{ + int i = 0; + + if (strlen(cmd) >= MAX_CMD_LEN || fn == NULL || cmd[0] != '/') + return -EINVAL; + if (num_callbacks >= TELEMETRY_MAX_CALLBACKS) + return -ENOENT; + + rte_spinlock_lock(&callback_sl); + while (i < num_callbacks && strcmp(cmd, callbacks[i].cmd) > 0) + i++; + if (i != num_callbacks) + /* Move elements to keep the list alphabetical */ + memmove(callbacks + i + 1, callbacks + i, + sizeof(struct cmd_callback) * (num_callbacks - i)); + + strlcpy(callbacks[i].cmd, cmd, MAX_CMD_LEN); + callbacks[i].fn = fn; + num_callbacks++; + rte_spinlock_unlock(&callback_sl); + + return 0; +} + +static int +list_commands(const char *cmd __rte_unused, const char *params __rte_unused, + char *buffer, int buf_len) +{ + int i, ret, used = 0; + + used += strlcpy(buffer, "[", buf_len); + for (i = 0; i < num_callbacks; i++) { + ret = snprintf(buffer + used, buf_len - used, "\"%s\",", + callbacks[i].cmd); + if (ret + used >= buf_len) + break; + used += ret; + } + buffer[used - 1] = ']'; + return used; +} + +static void +perform_command(telemetry_cb fn, const char *cmd, const char *param, int s) +{ + char out_buf[1024 * 12]; + + int used = snprintf(out_buf, + sizeof(out_buf), "{\"%s\":", cmd); + int ret = fn(cmd, param, out_buf + used, sizeof(out_buf) - used); + if (ret < 0) { + used += strlcpy(out_buf + used, "null}\n", + sizeof(out_buf) - used); + if (write(s, out_buf, used) < 0) + perror("Error writing to socket"); + return; + } + used += ret; + used += strlcpy(out_buf + used, "}\n", sizeof(out_buf) - used); + if (write(s, out_buf, used) < 0) + perror("Error writing to socket"); +} + +static int +unknown_command(const char *cmd __rte_unused, const char *params __rte_unused, + char *buffer, int buf_len) +{ + return snprintf(buffer, buf_len, "null"); +} + +static void * +client_handler(void *sock_id) +{ + int s = (int)(uintptr_t)sock_id; + char buffer[1024]; + + /* receive data is not null terminated */ + int bytes = read(s, buffer, sizeof(buffer)); + buffer[bytes] = 0; + while (bytes > 0) { + const char *cmd = strtok(buffer, ","); + const char *param = strtok(NULL, ","); + telemetry_cb fn = unknown_command; + int i; + + rte_spinlock_lock(&callback_sl); + for (i = 0; i < num_callbacks; i++) + if (strcmp(cmd, callbacks[i].cmd) == 0) { + fn = callbacks[i].fn; + break; + } + + rte_spinlock_unlock(&callback_sl); + perform_command(fn, cmd, param, s); + + bytes = read(s, buffer, sizeof(buffer)); + buffer[bytes] = 0; + } + close(s); + return NULL; +} + +static void * +socket_listener(void *socket) +{ + while (1) { + pthread_t th; + struct socket *s = (struct socket *)socket; + int s_accepted = accept(s->sock, NULL, NULL); + if (s_accepted < 0) { + snprintf(telemetry_log_error, + sizeof(telemetry_log_error), + "Error with accept, telemetry thread quitting\n"); + return NULL; + } + pthread_create(&th, NULL, s->fn, (void *)(uintptr_t)s_accepted); + pthread_detach(th); + } + return NULL; +} + +static inline char * +get_socket_path(const char *runtime_dir) +{ + static char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/dpdk_telemetry.%d", + strlen(runtime_dir) ? runtime_dir : "/tmp", getpid()); + return path; +} + +static void +unlink_sockets(void) +{ + if (v2_socket.path[0]) + unlink(v2_socket.path); +} + +static int +create_socket(char *path) +{ + int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (sock < 0) { + snprintf(telemetry_log_error, sizeof(telemetry_log_error), + "Error with socket creation, %s", + strerror(errno)); + return -1; + } + + struct sockaddr_un sun = {.sun_family = AF_UNIX}; + strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); + unlink(sun.sun_path); + if (bind(sock, (void *) &sun, sizeof(sun)) < 0) { + snprintf(telemetry_log_error, sizeof(telemetry_log_error), + "Error binding socket: %s", + strerror(errno)); + sun.sun_path[0] = 0; + goto error; + } + + if (listen(sock, 1) < 0) { + snprintf(telemetry_log_error, sizeof(telemetry_log_error), + "Error calling listen for socket: %s", + strerror(errno)); + goto error; + } + + return sock; + +error: + close(sock); + unlink_sockets(); + return -1; +} + +static int +telemetry_v2_init(const char *runtime_dir, const char **err_str) +{ + pthread_t t_new; + + v2_socket.fn = client_handler; + if (strlcpy(v2_socket.path, get_socket_path(runtime_dir), + sizeof(v2_socket.path)) >= sizeof(v2_socket.path)) { + snprintf(telemetry_log_error, sizeof(telemetry_log_error), + "Error with socket binding, path too long"); + return -1; + } + + v2_socket.sock = create_socket(v2_socket.path); + if (v2_socket.sock < 0) { + *err_str = telemetry_log_error; + return -1; + } + pthread_create(&t_new, NULL, socket_listener, &v2_socket); + atexit(unlink_sockets); + + return 0; +} + +int32_t +rte_telemetry_new_init(void) +{ + const char *error_str; + if (telemetry_v2_init(rte_eal_get_runtime_dir(), &error_str) != 0) { + printf("Error initialising telemetry - %s", error_str); + return -1; + } + return 0; +} From patchwork Thu Mar 19 17:19:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66944 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1B568A0583; Thu, 19 Mar 2020 18:36:13 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 298FF1C038; Thu, 19 Mar 2020 18:35:05 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id DCBCD1C0B0 for ; Thu, 19 Mar 2020 18:35:02 +0100 (CET) IronPort-SDR: bJdRQzpKDf/Aitl4/I+O86ZanvJby/dDOWBTDSQaki2os42a1HFm6NZCndXBCdnSSg8hJvX7G1 ZS70ry1TccbQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:02 -0700 IronPort-SDR: ukgHefClS6yxTqRMGgDvSsEJybDj3bISg1VmjEn8MGAPfdzlgGbUaPVwNff7U6hzuZCb6SRImu m56bZigyF8IQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872655" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:00 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Bruce Richardson , Ciara Power Date: Thu, 19 Mar 2020 17:19:00 +0000 Message-Id: <20200319171907.60891-6-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 05/12] ethdev: add callback support for telemetry X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson The ethdev library now registers commands with telemetry, and implements the callback functions. These commands allow the list of ethdev ports and the stats for a port to be queried. Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- lib/librte_ethdev/Makefile | 4 ++ lib/librte_ethdev/meson.build | 4 ++ lib/librte_ethdev/rte_ethdev.c | 79 ++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile index b627e4e23..4ba9cb8f4 100644 --- a/lib/librte_ethdev/Makefile +++ b/lib/librte_ethdev/Makefile @@ -24,6 +24,10 @@ SRCS-y += rte_tm.c SRCS-y += rte_mtr.c SRCS-y += ethdev_profile.c +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +LDLIBS += -lrte_telemetry +endif + # # Export include files # diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build index 3537f22f5..072805cf1 100644 --- a/lib/librte_ethdev/meson.build +++ b/lib/librte_ethdev/meson.build @@ -26,3 +26,7 @@ headers = files('rte_ethdev.h', 'rte_tm_driver.h') deps += ['net', 'kvargs', 'meter'] + +if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') + deps += ['telemetry'] +endif diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index 774c721b3..e7646a9b3 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -38,6 +38,9 @@ #include #include #include +#ifdef RTE_LIBRTE_TELEMETRY +#include +#endif #include "rte_ethdev.h" #include "rte_ethdev_driver.h" @@ -5189,9 +5192,85 @@ rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da) return result; } +#ifdef RTE_LIBRTE_TELEMETRY +static int +handle_port_list(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len) +{ + int used = 0; + int port_id; + + used = strlcpy(buffer, "[", buf_len); + RTE_ETH_FOREACH_DEV(port_id) + used += snprintf(buffer + used, buf_len - used, "%d,", port_id); + buffer[used - 1] = ']'; + return used; +} + +static int +handle_port_stats(const char *cmd __rte_unused, + const char *params, + char *buffer, int buf_len) +{ + struct rte_eth_xstat *eth_xstats; + struct rte_eth_xstat_name *xstat_names; + int port_id, num_xstats; + int i, ret; + int used = 0; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + port_id = atoi(params); + if (!rte_eth_dev_is_valid_port(port_id)) + return -1; + + used = strlcpy(buffer, "{", buf_len); + + num_xstats = rte_eth_xstats_get(port_id, NULL, 0); + if (num_xstats < 0) + return -1; + + /* use one malloc for both names and stats */ + eth_xstats = malloc((sizeof(struct rte_eth_xstat) + + sizeof(struct rte_eth_xstat_name)) * num_xstats); + if (eth_xstats == NULL) + return -1; + xstat_names = (void *)ð_xstats[num_xstats]; + + ret = rte_eth_xstats_get_names(port_id, xstat_names, num_xstats); + if (ret < 0 || ret > num_xstats) { + free(eth_xstats); + return -1; + } + + ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats); + if (ret < 0 || ret > num_xstats) { + free(eth_xstats); + return -1; + } + + for (i = 0; i < num_xstats; i++) { + ret = snprintf(buffer + used, buf_len - used, "\"%s\":%"PRIu64",", + xstat_names[i].name, eth_xstats[i].value); + if (ret + used >= buf_len) + break; + used += ret; + } + + buffer[used - 1] = '}'; + return used; +} +#endif + RTE_INIT(ethdev_init_log) { rte_eth_dev_logtype = rte_log_register("lib.ethdev"); if (rte_eth_dev_logtype >= 0) rte_log_set_level(rte_eth_dev_logtype, RTE_LOG_INFO); +#ifdef RTE_LIBRTE_TELEMETRY + rte_telemetry_register_cmd("/ethdev/list", handle_port_list); + rte_telemetry_register_cmd("/ethdev/stats", handle_port_stats); +#endif } From patchwork Thu Mar 19 17:19:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66945 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7F16EA0583; Thu, 19 Mar 2020 18:36:26 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6DDAA1C0B6; Thu, 19 Mar 2020 18:35:06 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 660D61C026 for ; Thu, 19 Mar 2020 18:35:04 +0100 (CET) IronPort-SDR: DA7Wl7p/PE5o/ZLkK3gvy6dvA7IwDlCvSh//6PWVoRr82Epjxr0O8Fump3kRnLRNFtmiM/F1eF Y/baKEUFXUNA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:04 -0700 IronPort-SDR: 3MN6n112vleU7VCm37JMuqG4+jVJjuUXpEIBj0J+FJQHOod6XSXpVLzyUL1Uj+nkCH2mKwstYr S7kzUX81Gr5A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872670" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:02 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Bruce Richardson , Ciara Power Date: Thu, 19 Mar 2020 17:19:01 +0000 Message-Id: <20200319171907.60891-7-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 06/12] usertools: add new telemetry python script X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson This patch adds a python script that can be used with the new telemetry socket. It connects as a client to the socket, and allows the user send a command and see the JSON response. The example usage below shows the script connecting to the new telemetry socket, and sending two basic ethdev commands entered by the user. The response for each command is shown below the user input. Connecting to /var/run/dpdk/rte/dpdk_telemetry.19707 --> / {"/": ["/", "/ethdev/list", "/ethdev/stats"]} --> /ethdev/list {"/ethdev/list": [0, 1]} --> /ethdev/stats,0 {"/ethdev/stats": {"rx_good_packets": 0, "tx_good_packets": 0, "tx_priority7_xon_to_xoff_packets": 0}} Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- This is a temporary script for testing purposes. Later versions of the patchset will include a production ready version, which may be merged into the existing dpdk_telemetry script. --- usertools/test_new_telemetry.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 usertools/test_new_telemetry.py diff --git a/usertools/test_new_telemetry.py b/usertools/test_new_telemetry.py new file mode 100755 index 000000000..23e879122 --- /dev/null +++ b/usertools/test_new_telemetry.py @@ -0,0 +1,30 @@ +#! /usr/bin/python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020 Intel Corporation + +import socket +import os +import glob +import json + +def handle_socket(path): + print("Connecting to " + path) + try: + fd.connect(path) + except OSError: + return + text = input('--> ') + while (text != "quit"): + fd.send(text.encode()) + reply = json.loads(fd.recv(1024 * 12).decode()) + print(json.dumps(reply)) + text = input('--> ') + fd.close() + +fd = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) +# Path to sockets for processes run as a root user +for f in glob.glob('/var/run/dpdk/*/dpdk_telemetry.*'): + handle_socket(f) +# Path to sockets for processes run as a regular user +for f in glob.glob('/run/user/%d/dpdk/*/dpdk_telemetry.*' % os.getuid()): + handle_socket(f) From patchwork Thu Mar 19 17:19:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66946 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 46C6BA0583; Thu, 19 Mar 2020 18:36:39 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E015A1C0BE; Thu, 19 Mar 2020 18:35:07 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 5CC051C0B4 for ; Thu, 19 Mar 2020 18:35:06 +0100 (CET) IronPort-SDR: Waji2AwA8SPls364u4Q3qtI6UDjv7PKaGb+LWkTpAZTpChdgSnWEcM86b9nn99xKmA37OVKGwV YCtjBk1NM8yQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:06 -0700 IronPort-SDR: myLFVtOOD0fkkpzvh0eGOGFtC2Tr2eSN35r9MNmVz5m6QDBsKAyBC8S4r6gjLVPM1Uv4sdKvw4 87iFIEu2uexA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872690" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:04 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power , Bruce Richardson Date: Thu, 19 Mar 2020 17:19:02 +0000 Message-Id: <20200319171907.60891-8-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 07/12] rawdev: add callback support for telemetry X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The rawdev library now registers commands with telemetry, and implements the corresponding callback functions. These allow a list of rawdev devices and stats for a rawdev port to be queried. An example usage, with ioat rawdev driver instances, is shown below: Connecting to /var/run/dpdk/rte/dpdk_telemetry.22345 --> / {"/": ["/", "/ethdev/list", "/ethdev/stats", "/rawdev/list", "/rawdev/stats"]} --> /rawdev/list {"/rawdev/list": [0, 1, 2, 3, 4, 5]} --> /rawdev/stats,0 {"/rawdev/stats": {"failed_enqueues": 0, "successful_enqueues": 0, "copies_started": 0, "copies_completed": 0}} Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- lib/librte_rawdev/Makefile | 5 ++ lib/librte_rawdev/meson.build | 5 ++ lib/librte_rawdev/rte_rawdev.c | 88 ++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/lib/librte_rawdev/Makefile b/lib/librte_rawdev/Makefile index 7dd1197dc..ccf68f60e 100644 --- a/lib/librte_rawdev/Makefile +++ b/lib/librte_rawdev/Makefile @@ -11,6 +11,11 @@ CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_eal +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +CFLAGS += -DALLOW_EXPERIMENTAL_API +LDLIBS += -lrte_telemetry +endif + # library source files SRCS-y += rte_rawdev.c diff --git a/lib/librte_rawdev/meson.build b/lib/librte_rawdev/meson.build index a20fbdc04..3a0ea2a29 100644 --- a/lib/librte_rawdev/meson.build +++ b/lib/librte_rawdev/meson.build @@ -3,3 +3,8 @@ sources = files('rte_rawdev.c') headers = files('rte_rawdev.h', 'rte_rawdev_pmd.h') + +if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') + allow_experimental_apis = true + deps += ['telemetry'] +endif diff --git a/lib/librte_rawdev/rte_rawdev.c b/lib/librte_rawdev/rte_rawdev.c index b6f1e1c77..034a0e32f 100644 --- a/lib/librte_rawdev/rte_rawdev.c +++ b/lib/librte_rawdev/rte_rawdev.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef RTE_LIBRTE_TELEMETRY +#include +#endif #include "rte_rawdev.h" #include "rte_rawdev_pmd.h" @@ -544,9 +547,94 @@ rte_rawdev_pmd_release(struct rte_rawdev *rawdev) return 0; } +#ifdef RTE_LIBRTE_TELEMETRY +static int +handle_dev_list(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len) +{ + int used = 0; + int i; + + used = strlcpy(buffer, "[", buf_len); + for (i = 0; i < rawdev_globals.nb_devs; i++) + if (rte_rawdevices[i].attached == RTE_RAWDEV_ATTACHED) + used += snprintf(buffer + used, buf_len - used, "%d,", + rte_rawdevices[i].dev_id); + + buffer[used - 1] = ']'; + return used; +} + +static int +handle_dev_stats(const char *cmd __rte_unused, + const char *params, + char *buffer, int buf_len) +{ + uint64_t *rawdev_xstats; + struct rte_rawdev_xstats_name *xstat_names; + int dev_id, num_xstats, i, ret; + int used = 0; + unsigned int *ids; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + dev_id = atoi(params); + if (!rte_rawdev_pmd_is_valid_dev(dev_id)) + return -1; + + used = strlcpy(buffer, "{", buf_len); + + num_xstats = xstats_get_count(dev_id); + if (num_xstats < 0) + return -1; + + /* use one malloc for names, stats and ids */ + rawdev_xstats = malloc((sizeof(uint64_t) + + sizeof(struct rte_rawdev_xstats_name) + + sizeof(unsigned int)) * num_xstats); + if (rawdev_xstats == NULL) + return -1; + xstat_names = (void *)&rawdev_xstats[num_xstats]; + ids = (void *)&xstat_names[num_xstats]; + + ret = rte_rawdev_xstats_names_get(dev_id, xstat_names, num_xstats); + if (ret < 0 || ret > num_xstats) { + free(rawdev_xstats); + return -1; + } + + for (i = 0; i < num_xstats; i++) + ids[i] = i; + + ret = rte_rawdev_xstats_get(dev_id, ids, rawdev_xstats, num_xstats); + if (ret < 0 || ret > num_xstats) { + free(rawdev_xstats); + return -1; + } + + for (i = 0; i < num_xstats; i++) { + ret = snprintf(buffer + used, buf_len - used, "\"%s\":%"PRIu64",", + xstat_names[i].name, rawdev_xstats[i]); + if (ret + used >= buf_len) + break; + used += ret; + } + + buffer[used - 1] = '}'; + free(rawdev_xstats); + return used; +} +#endif + RTE_INIT(librawdev_init_log) { librawdev_logtype = rte_log_register("lib.rawdev"); if (librawdev_logtype >= 0) rte_log_set_level(librawdev_logtype, RTE_LOG_INFO); +#ifdef RTE_LIBRTE_TELEMETRY + rte_telemetry_register_cmd("/rawdev/list", handle_dev_list); + rte_telemetry_register_cmd("/rawdev/stats", handle_dev_stats); +#endif } From patchwork Thu Mar 19 17:19:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66947 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 075E8A0583; Thu, 19 Mar 2020 18:36:52 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 475B21C0C1; Thu, 19 Mar 2020 18:35:10 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 6203D1C0C1 for ; Thu, 19 Mar 2020 18:35:08 +0100 (CET) IronPort-SDR: jCi2ih9X6i+l40haHEeLv3jdckrmFJRu/pf7JiM0+WUBd3OHObNsQmXsqfOPeLKm/etdYc65dG NvGjalNwLPvQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:08 -0700 IronPort-SDR: sSDsoWGbl42qJbfk+HHTIQ3RrAtE6NvZXxP/ZyH/fonxM8eXu4XcRQPckCfYWdYTr4Fv1RszLj iw5muQNkpYTQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872701" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:06 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power , Bruce Richardson Date: Thu, 19 Mar 2020 17:19:03 +0000 Message-Id: <20200319171907.60891-9-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 08/12] examples/l3fwd-power: enable use of new telemetry X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The l3fwd-power example app now registers a stats command with telemetry, and provides a callback function to handle formatting the power stats. An example usage is shown below: Connecting to /var/run/dpdk/rte/dpdk_telemetry.23863 --> / {"/": ["/", "/ethdev/list", "/ethdev/stats", "/l3fwd-power/stats"]} --> /l3fwd-power/stats {"/l3fwd-power/stats": {"empty_poll": 281625000, "full_poll": 0, "busy_percent": 0}} The existing stats tracking done by the app using the metrics library is unaffected. This will still be used to ensure backward compatibility. Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- examples/l3fwd-power/Makefile | 4 +++ examples/l3fwd-power/main.c | 62 ++++++++++++++++++++++++-------- examples/l3fwd-power/meson.build | 4 +++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/examples/l3fwd-power/Makefile b/examples/l3fwd-power/Makefile index 729d49639..531a1d81c 100644 --- a/examples/l3fwd-power/Makefile +++ b/examples/l3fwd-power/Makefile @@ -68,6 +68,10 @@ ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +LDLIBS += -lrte_telemetry +endif + include $(RTE_SDK)/mk/rte.extapp.mk endif endif diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index c7fe0ec03..de52a47b6 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -46,6 +46,9 @@ #include #include #include +#ifdef RTE_LIBRTE_TELEMETRY +#include +#endif #include "perf_core.h" #include "main.h" @@ -131,7 +134,7 @@ #define EMPTY_POLL_MED_THRESHOLD 350000UL #define EMPTY_POLL_HGH_THRESHOLD 580000UL - +#define NUM_TELSTATS RTE_DIM(telstats_strings) static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; @@ -2079,14 +2082,11 @@ init_power_library(void) return ret; } static void -update_telemetry(__attribute__((unused)) struct rte_timer *tim, - __attribute__((unused)) void *arg) +get_current_stat_values(uint64_t *values) { unsigned int lcore_id = rte_lcore_id(); struct lcore_conf *qconf; uint64_t app_eps = 0, app_fps = 0, app_br = 0; - uint64_t values[3] = {0}; - int ret; uint64_t count = 0; RTE_LCORE_FOREACH_SLAVE(lcore_id) { @@ -2105,17 +2105,48 @@ update_telemetry(__attribute__((unused)) struct rte_timer *tim, values[0] = app_eps/count; values[1] = app_fps/count; values[2] = app_br/count; - } else { - values[0] = 0; - values[1] = 0; - values[2] = 0; - } + } else + memset(values, 0, sizeof(uint64_t) * NUM_TELSTATS); + +} +static void +update_telemetry(__attribute__((unused)) struct rte_timer *tim, + __attribute__((unused)) void *arg) +{ + int ret; + uint64_t values[3] = {0}; + + get_current_stat_values(values); ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, telstats_index, values, RTE_DIM(values)); if (ret < 0) RTE_LOG(WARNING, POWER, "failed to update metrcis\n"); } +#ifdef RTE_LIBRTE_TELEMETRY +static int +handle_app_stats(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len) +{ + int ret, used = 0; + uint64_t values[3] = {0}; + uint32_t i; + + used = strlcpy(buffer, "{", buf_len); + get_current_stat_values(values); + for (i = 0; i < NUM_TELSTATS; i++) { + ret = snprintf(buffer + used, buf_len - used, "\"%s\":%"PRIu64",", + telstats_strings[i].name, values[i]); + if (ret + used >= buf_len) + break; + used += ret; + } + + buffer[used - 1] = '}'; + return used; +} +#endif static void telemetry_setup_timer(void) { @@ -2203,8 +2234,7 @@ main(int argc, char **argv) uint32_t dev_rxq_num, dev_txq_num; uint8_t nb_rx_queue, queue, socketid; uint16_t portid; - uint8_t num_telstats = RTE_DIM(telstats_strings); - const char *ptr_strings[num_telstats]; + const char *ptr_strings[NUM_TELSTATS]; /* catch SIGINT and restore cpufreq governor to ondemand */ signal(SIGINT, signal_exit_now); @@ -2503,10 +2533,10 @@ main(int argc, char **argv) /* Init metrics library */ rte_metrics_init(rte_socket_id()); /** Register stats with metrics library */ - for (i = 0; i < num_telstats; i++) + for (i = 0; i < NUM_TELSTATS; i++) ptr_strings[i] = telstats_strings[i].name; - ret = rte_metrics_reg_names(ptr_strings, num_telstats); + ret = rte_metrics_reg_names(ptr_strings, NUM_TELSTATS); if (ret >= 0) telstats_index = ret; else @@ -2516,6 +2546,10 @@ main(int argc, char **argv) rte_spinlock_init(&stats[lcore_id].telemetry_lock); } rte_timer_init(&telemetry_timer); +#ifdef RTE_LIBRTE_TELEMETRY + rte_telemetry_register_cmd("/l3fwd-power/stats", + handle_app_stats); +#endif rte_eal_mp_remote_launch(main_telemetry_loop, NULL, SKIP_MASTER); } diff --git a/examples/l3fwd-power/meson.build b/examples/l3fwd-power/meson.build index d5a3d4bb2..e7c6be647 100644 --- a/examples/l3fwd-power/meson.build +++ b/examples/l3fwd-power/meson.build @@ -16,3 +16,7 @@ deps += ['power', 'timer', 'lpm', 'hash', 'metrics'] sources = files( 'main.c', 'perf_core.c' ) + +if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') + deps += ['telemetry'] +endif From patchwork Thu Mar 19 17:19:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66948 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0DA89A0583; Thu, 19 Mar 2020 18:37:09 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E424A1C0CF; Thu, 19 Mar 2020 18:35:12 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 606201C0C4 for ; Thu, 19 Mar 2020 18:35:10 +0100 (CET) IronPort-SDR: emuATZEshyZuI/pwD5ngESu8wwsLIOtSyUOodsujtoImi7+eUqIxdM/yjSCWNVMuivuQGE7vYH OloA6QfNNDdw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:10 -0700 IronPort-SDR: y5rYNiXO+89EMfmtQr0NMOG2RpmvMlI6zvqs1o0epzmmU7N+u7R6CECvNDeOkD2xSEAWsq3o7/ HL9g4XYhtnVA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872719" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:08 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power Date: Thu, 19 Mar 2020 17:19:04 +0000 Message-Id: <20200319171907.60891-10-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 09/12] telemetry: introduce telemetry backward compatibility X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The new telemetry will now open a socket using the old telemetry path, to ensure backward compatibility. This is not yet initialised, as it would clash with the existing telemetry, to be removed in a later patch. This means that both old and new telemetry socket interfaces are handled in a common way. Signed-off-by: Ciara Power --- lib/librte_metrics/Makefile | 2 +- lib/librte_metrics/meson.build | 1 + lib/librte_metrics/rte_metrics_telemetry.c | 113 +++++++++ lib/librte_telemetry/Makefile | 1 + lib/librte_telemetry/meson.build | 4 +- lib/librte_telemetry/rte_telemetry.h | 1 + lib/librte_telemetry/rte_telemetry_legacy.h | 48 ++++ .../rte_telemetry_version.map | 2 + lib/librte_telemetry/telemetry.c | 32 +++ lib/librte_telemetry/telemetry_legacy.c | 226 ++++++++++++++++++ 10 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 lib/librte_telemetry/rte_telemetry_legacy.h create mode 100644 lib/librte_telemetry/telemetry_legacy.c diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile index fa762ba37..c8b9b143d 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -21,7 +21,7 @@ ifneq ($(JANSSON_LINK),) SRCS-y += rte_metrics_telemetry.c SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics_telemetry.h -LDLIBS += -lrte_ethdev +LDLIBS += -lrte_ethdev -lrte_telemetry LDLIBS += $(JANSSON_LINK) CFLAGS += $(JANSSON_CFLAGS) diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build index d116857e2..1a7cbf29c 100644 --- a/lib/librte_metrics/meson.build +++ b/lib/librte_metrics/meson.build @@ -11,4 +11,5 @@ if jansson.found() sources += files('rte_metrics_telemetry.c') headers = files('rte_metrics_telemetry.h') deps += ['ethdev', 'telemetry'] + includes += include_directories('../librte_telemetry') endif diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c index 31d505551..49de9d74b 100644 --- a/lib/librte_metrics/rte_metrics_telemetry.c +++ b/lib/librte_metrics/rte_metrics_telemetry.c @@ -8,6 +8,7 @@ #include #ifdef RTE_LIBRTE_TELEMETRY #include +#include #endif #include "rte_metrics.h" @@ -417,6 +418,112 @@ rte_metrics_tel_extract_data(struct telemetry_encode_param *ep, json_t *data) return 0; } +static int +rte_metrics_tel_initial_metrics_setup(void) +{ + int ret; + rte_metrics_init(rte_socket_id()); + + if (!tel_met_data.metrics_register_done) { + ret = rte_metrics_tel_reg_all_ethdev( + &tel_met_data.metrics_register_done, + tel_met_data.reg_index); + if (ret < 0) + return ret; + } + return 0; +} + +static int +handle_ports_all_stats_values(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len) +{ + struct telemetry_encode_param ep; + int ret, used = 0; + char *json_buffer = NULL; + + ret = rte_metrics_tel_initial_metrics_setup(); + if (ret < 0) + return ret; + + memset(&ep, 0, sizeof(ep)); + ret = rte_metrics_tel_get_port_stats_ids(&ep); + if (ret < 0) + return ret; + + ret = rte_metrics_tel_get_ports_stats_json(&ep, tel_met_data.reg_index, + &json_buffer); + if (ret < 0) + return ret; + + used += strlcpy(buffer, json_buffer, buf_len); + return used; +} + +static int +handle_global_stats_values(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len) +{ + char *json_buffer = NULL; + struct telemetry_encode_param ep = { .type = GLOBAL_STATS }; + int ret, used = 0; + + ret = rte_metrics_tel_initial_metrics_setup(); + if (ret < 0) + return ret; + + ret = rte_metrics_tel_encode_json_format(&ep, &json_buffer); + if (ret < 0) { + METRICS_LOG_ERR("JSON encode function failed"); + return ret; + } + used += strlcpy(buffer, json_buffer, buf_len); + return used; +} + +static int +handle_ports_stats_values_by_name(const char *cmd __rte_unused, + const char *params, + char *buffer, int buf_len) +{ + char *json_buffer = NULL; + struct telemetry_encode_param ep; + int ret, used = 0; + json_t *data; + json_error_t error; + + ret = rte_metrics_tel_initial_metrics_setup(); + if (ret < 0) + return ret; + + data = json_loads(params, 0, &error); + if (!data) { + METRICS_LOG_WARN("Could not load JSON object from data passed in : %s", + error.text); + return -EPERM; + } else if (!json_is_object(data)) { + METRICS_LOG_WARN("JSON Request data is not a JSON object"); + json_decref(data); + return -EINVAL; + } + + ret = rte_metrics_tel_extract_data(&ep, data); + if (ret < 0) { + METRICS_LOG_ERR("Extract data function failed"); + return ret; + } + + ret = rte_metrics_tel_encode_json_format(&ep, &json_buffer); + if (ret < 0) { + METRICS_LOG_ERR("JSON encode function failed"); + return ret; + } + used += strlcpy(buffer, json_buffer, buf_len); + return used; +} + RTE_INIT(metrics_ctor) { #ifdef RTE_LIBRTE_TELEMETRY @@ -428,6 +535,12 @@ RTE_INIT(metrics_ctor) .extract_data = rte_metrics_tel_extract_data }; rte_telemetry_set_metrics_fns(&fns); /* assign them to telemetry lib */ + rte_telemetry_legacy_register("ports_all_stat_values", DATA_NOT_REQ, + handle_ports_all_stats_values); + rte_telemetry_legacy_register("global_stat_values", DATA_NOT_REQ, + handle_global_stats_values); + rte_telemetry_legacy_register("ports_stats_values_by_name", DATA_REQ, + handle_ports_stats_values_by_name); #endif metrics_log_level = rte_log_register("lib.metrics"); if (metrics_log_level >= 0) diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index b34fe90d4..e2af886b6 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -26,6 +26,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_legacy.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 49c947120..caca32b2e 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -4,8 +4,8 @@ includes = [global_inc] includes += include_directories('../librte_eal/common/include/arch/' + arch_subdir) -sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c', - 'telemetry.c') +sources = files('rte_telemetry.c','rte_telemetry_parser.c', 'rte_telemetry_parser_test.c', + 'telemetry.c', 'telemetry_legacy.c') headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h') cflags += '-DALLOW_EXPERIMENTAL_API' includes += include_directories('../librte_metrics') diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h index 060613117..13ce235cb 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -125,4 +125,5 @@ int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); */ __rte_experimental int rte_telemetry_new_init(void); + #endif diff --git a/lib/librte_telemetry/rte_telemetry_legacy.h b/lib/librte_telemetry/rte_telemetry_legacy.h new file mode 100644 index 000000000..66c4981b3 --- /dev/null +++ b/lib/librte_telemetry/rte_telemetry_legacy.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#ifndef _RTE_TELEMETRY_LEGACY_H_ +#define _RTE_TELEMETRY_LEGACY_H_ + +#include +#include "rte_telemetry.h" + +enum rte_telemetry_legacy_data_req { + DATA_NOT_REQ = 0, + DATA_REQ +}; + +extern int num_legacy_callbacks; + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Used for handling data received over the legacy telemetry socket. + * + * @return + * Void. + */ +void *legacy_client_handler(void *sock_id); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Used when registering a command and callback function with + * telemetry legacy support. + * + * @return + * 0 on success. + * @return + * -EINVAL for invalid parameters failure. + * @return + * -ENOENT if max callbacks limit has been reached. + */ +__rte_experimental +int rte_telemetry_legacy_register(const char *cmd, + enum rte_telemetry_legacy_data_req data_req, + telemetry_cb fn); + +#endif diff --git a/lib/librte_telemetry/rte_telemetry_version.map b/lib/librte_telemetry/rte_telemetry_version.map index 831bbd59a..2db0a5a44 100644 --- a/lib/librte_telemetry/rte_telemetry_version.map +++ b/lib/librte_telemetry/rte_telemetry_version.map @@ -8,6 +8,8 @@ EXPERIMENTAL { rte_telemetry_set_metrics_fns; rte_telemetry_new_init; rte_telemetry_register_cmd; + rte_telemetry_legacy_init; + rte_telemetry_legacy_register; local: *; }; diff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c index 1ad784f59..e77672b48 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -15,6 +15,7 @@ #include #include "rte_telemetry.h" +#include "rte_telemetry_legacy.h" #define MAX_CMD_LEN 56 @@ -36,6 +37,7 @@ struct socket { handler fn; }; static struct socket v2_socket; /* socket for v2 telemetry */ +static struct socket v1_socket; /* socket for v1 telemetry */ static char telemetry_log_error[1024]; /* Will contain error on init failure */ /* list of command callbacks, with one command registered by default */ static struct cmd_callback callbacks[TELEMETRY_MAX_CALLBACKS] = { @@ -182,6 +184,8 @@ unlink_sockets(void) { if (v2_socket.path[0]) unlink(v2_socket.path); + if (v1_socket.path[0]) + unlink(v1_socket.path); } static int @@ -221,6 +225,34 @@ create_socket(char *path) return -1; } +static int __rte_unused /* will be used in future commit */ +telemetry_legacy_init(const char *runtime_dir, const char **err_str) +{ + pthread_t t_old; + + if (num_legacy_callbacks == 1) { + *err_str = "No legacy callbacks - error creating legacy socket"; + return -1; + } + + v1_socket.fn = legacy_client_handler; + if ((size_t) snprintf(v1_socket.path, sizeof(v1_socket.path), + "%s/telemetry", runtime_dir) + >= sizeof(v1_socket.path)) { + snprintf(telemetry_log_error, sizeof(telemetry_log_error), + "Error with socket binding, path too long"); + return -1; + } + v1_socket.sock = create_socket(v1_socket.path); + if (v1_socket.sock < 0) { + *err_str = telemetry_log_error; + return -1; + } + pthread_create(&t_old, NULL, socket_listener, &v1_socket); + + return 0; +} + static int telemetry_v2_init(const char *runtime_dir, const char **err_str) { diff --git a/lib/librte_telemetry/telemetry_legacy.c b/lib/librte_telemetry/telemetry_legacy.c new file mode 100644 index 000000000..e7c01525b --- /dev/null +++ b/lib/librte_telemetry/telemetry_legacy.c @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include +#include +#include +#include + +/* we won't link against libbsd, so just always use DPDKs-specific strlcpy */ +#undef RTE_USE_LIBBSD +#include +#include +#include + +#include "rte_telemetry_legacy.h" + +#define MAX_LEN 128 +#define BUF_SIZE 1024 +#define CLIENTS_UNREG_ACTION "\"action\":2" +#define CLIENTS_CMD "\"command\":\"clients\"" +#define CLIENTS_DATA "\"data\":{\"client_path\":\"" +#define STATS_ACTION "\"action\":0" +#define DATA_REQ_LABEL "\"data\":" +#define TELEMETRY_LEGACY_MAX_CALLBACKS 4 + + +static int +register_client(const char *cmd __rte_unused, + const char *params __rte_unused, + char *buffer, int buf_len); + +struct json_command { + char action[MAX_LEN]; + char cmd[MAX_LEN]; + char data[MAX_LEN]; + telemetry_cb fn; + +}; + +struct json_command callbacks[TELEMETRY_LEGACY_MAX_CALLBACKS] = { + { + .action = "\"action\":1", + .cmd = CLIENTS_CMD, + .data = CLIENTS_DATA, + .fn = register_client + } +}; +int num_legacy_callbacks = 1; +static rte_spinlock_t callback_sl = RTE_SPINLOCK_INITIALIZER; + +int +rte_telemetry_legacy_register(const char *cmd, enum + rte_telemetry_legacy_data_req data_req, telemetry_cb fn) +{ + if (fn == NULL) + return -EINVAL; + if (num_legacy_callbacks >= (int) RTE_DIM(callbacks)) + return -ENOENT; + + rte_spinlock_lock(&callback_sl); + strlcpy(callbacks[num_legacy_callbacks].action, STATS_ACTION, MAX_LEN); + snprintf(callbacks[num_legacy_callbacks].cmd, MAX_LEN, + "\"command\":\"%s\"", cmd); + snprintf(callbacks[num_legacy_callbacks].data, MAX_LEN, + data_req ? "%s{\"" : "%snull", + DATA_REQ_LABEL); + callbacks[num_legacy_callbacks].fn = fn; + num_legacy_callbacks++; + rte_spinlock_unlock(&callback_sl); + + return 0; +} + +static int +register_client(const char *cmd __rte_unused, const char *params, + char *buffer __rte_unused, int buf_len __rte_unused) +{ + pthread_t th; + char data[BUF_SIZE]; + int fd; + struct sockaddr_un addrs; + + strlcpy(data, strchr(params, ':'), sizeof(data)); + memcpy(data, &data[strlen(":\"")], strlen(data)); + *strchr(data, '\"') = 0; + + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + addrs.sun_family = AF_UNIX; + strlcpy(addrs.sun_path, data, sizeof(addrs.sun_path)); + + if (connect(fd, (struct sockaddr *)&addrs, sizeof(addrs)) == -1) { + perror("\nClient connection error\n"); + return -1; + } + pthread_create(&th, NULL, &legacy_client_handler, + (void *)(uintptr_t)fd); + return 0; +} + +static int +send_error_response(int s, int err) +{ + const char *desc; + char out_buf[100000]; + + switch (err) { + case -ENOMEM: + desc = "Memory Allocation Error"; + break; + case -EINVAL: + desc = "Invalid Argument 404"; + break; + case -EPERM: + desc = "Unknown"; + break; + default: + /* Default case keeps behaviour of Telemetry library */ + printf("\nInvalid error type: %d\n", err); + return -EINVAL; + } + int used = snprintf(out_buf, sizeof(out_buf), "{\"status_code\": " + "\"Status Error: %s\", \"data\": null}", desc); + if (write(s, out_buf, used) < 0) { + perror("Error writing to socket"); + return -1; + } + return 0; +} + +static void +perform_command(telemetry_cb fn, const char *param, int s) +{ + char out_buf[100000]; + int ret, used = 0; + + ret = fn("", param, out_buf, sizeof(out_buf)); + if (ret < 0) { + ret = send_error_response(s, ret); + if (ret < 0) + printf("\nCould not send error response\n"); + return; + } + used += ret; + if (write(s, out_buf, used) < 0) + perror("Error writing to socket"); +} + +static int +parse_client_request(char *buffer, int buf_len, int s) +{ + int i; + char *data = buffer + buf_len; + telemetry_cb fn = NULL; + const char *valid_sep = ",}"; + if (buffer[0] != '{' || buffer[buf_len - 1] != '}') + return -EPERM; + + if (strstr(buffer, CLIENTS_UNREG_ACTION) && strstr(buffer, CLIENTS_CMD) + && strstr(buffer, CLIENTS_DATA)) + return 0; + + for (i = 0; i < num_legacy_callbacks; i++) { + char *action_ptr = strstr(buffer, callbacks[i].action); + char *cmd_ptr = strstr(buffer, callbacks[i].cmd); + char *data_ptr = strstr(buffer, callbacks[i].data); + if (!action_ptr || !cmd_ptr || !data_ptr) + continue; + + char action_sep = action_ptr[strlen(callbacks[i].action)]; + char cmd_sep = cmd_ptr[strlen(callbacks[i].cmd)]; + if (!(strchr(valid_sep, action_sep) && strchr(valid_sep, + cmd_sep))) + return -EPERM; + char data_sep; + + if (!strchr(data_ptr, '{')) + data_sep = data_ptr[strlen(callbacks[i].data)]; + else { + char *data_end = strchr(data_ptr, '}'); + data = data_ptr + strlen(DATA_REQ_LABEL); + data_sep = data_end[1]; + data_end[1] = 0; + } + if (!strchr(valid_sep, data_sep)) + return -EPERM; + fn = callbacks[i].fn; + break; + } + + if (!fn) + return -EINVAL; + perform_command(fn, data, s); + return 0; +} + +void * +legacy_client_handler(void *sock_id) +{ + int s = (int)(uintptr_t)sock_id; + int ret; + char buffer_recv[BUF_SIZE]; + /* receive data is not null terminated */ + int bytes = read(s, buffer_recv, sizeof(buffer_recv)); + buffer_recv[bytes] = 0; + + while (bytes > 0) { + int i, j; + char buffer[BUF_SIZE]; + for (i = 0, j = 0; buffer_recv[i] != '\0'; i++) { + buffer[j] = buffer_recv[i]; + j += !isspace(buffer_recv[i]); + } + buffer[j] = 0; + ret = parse_client_request(buffer, j, s); + if (ret < 0) { + ret = send_error_response(s, ret); + if (ret < 0) + printf("\nCould not send error response\n"); + } + bytes = read(s, buffer_recv, sizeof(buffer_recv)); + buffer_recv[bytes] = 0; + } + close(s); + return NULL; +} From patchwork Thu Mar 19 17:19:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66949 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1DAD0A0583; Thu, 19 Mar 2020 18:37:25 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4F0F11C0D6; Thu, 19 Mar 2020 18:35:15 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 9E7941C0CD for ; Thu, 19 Mar 2020 18:35:12 +0100 (CET) IronPort-SDR: W7xsYROh9XrAeUOLWm3uJqBMi9C3PQ7AkprwVh9ZtuiAfJtgSAR8rwag/ECdtyqpQgw1Ye83n8 kRWtygd0mTxg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:12 -0700 IronPort-SDR: tuHp867mGC7FUhPS9XtEX9kGxVvWull3lzDfyvXS0EvdgirHRAbuD5IqDvRDxc71wl3imIsaXh DU6oVm+Vbu0A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872739" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:10 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power Date: Thu, 19 Mar 2020 17:19:05 +0000 Message-Id: <20200319171907.60891-11-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 10/12] telemetry: remove existing telemetry files X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch removes the existing telemetry files, which are now redundant as the new version of telemetry has backward compatibility for their functionality. Signed-off-by: Ciara Power --- lib/librte_metrics/rte_metrics_telemetry.c | 9 - lib/librte_telemetry/Makefile | 5 - lib/librte_telemetry/meson.build | 15 +- lib/librte_telemetry/rte_telemetry.c | 1384 ----------------- lib/librte_telemetry/rte_telemetry.h | 57 +- lib/librte_telemetry/rte_telemetry_internal.h | 114 -- lib/librte_telemetry/rte_telemetry_parser.c | 435 ------ lib/librte_telemetry/rte_telemetry_parser.h | 15 - .../rte_telemetry_parser_test.c | 533 ------- .../rte_telemetry_socket_tests.h | 36 - .../rte_telemetry_version.map | 6 - lib/librte_telemetry/telemetry.c | 19 +- 12 files changed, 24 insertions(+), 2604 deletions(-) delete mode 100644 lib/librte_telemetry/rte_telemetry.c delete mode 100644 lib/librte_telemetry/rte_telemetry_internal.h delete mode 100644 lib/librte_telemetry/rte_telemetry_parser.c delete mode 100644 lib/librte_telemetry/rte_telemetry_parser.h delete mode 100644 lib/librte_telemetry/rte_telemetry_parser_test.c delete mode 100644 lib/librte_telemetry/rte_telemetry_socket_tests.h diff --git a/lib/librte_metrics/rte_metrics_telemetry.c b/lib/librte_metrics/rte_metrics_telemetry.c index 49de9d74b..5ef6f765a 100644 --- a/lib/librte_metrics/rte_metrics_telemetry.c +++ b/lib/librte_metrics/rte_metrics_telemetry.c @@ -7,7 +7,6 @@ #include #include #ifdef RTE_LIBRTE_TELEMETRY -#include #include #endif @@ -527,14 +526,6 @@ handle_ports_stats_values_by_name(const char *cmd __rte_unused, RTE_INIT(metrics_ctor) { #ifdef RTE_LIBRTE_TELEMETRY - static const struct metrics_functions fns = { - .reg_all_ethdev = rte_metrics_tel_reg_all_ethdev, - .encode_json_format = rte_metrics_tel_encode_json_format, - .get_port_stats_ids = rte_metrics_tel_get_port_stats_ids, - .get_ports_stats_json = rte_metrics_tel_get_ports_stats_json, - .extract_data = rte_metrics_tel_extract_data - }; - rte_telemetry_set_metrics_fns(&fns); /* assign them to telemetry lib */ rte_telemetry_legacy_register("ports_all_stat_values", DATA_NOT_REQ, handle_ports_all_stats_values); rte_telemetry_legacy_register("global_stat_values", DATA_NOT_REQ, diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index e2af886b6..4982aa457 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -15,16 +15,11 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/ CFLAGS += -pthread LDLIBS += -lrte_eal -LDLIBS += -lrte_metrics LDLIBS += -lpthread -LDLIBS += -ljansson EXPORT_MAP := rte_telemetry_version.map # 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 SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry_legacy.c diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build index caca32b2e..5d5ac8925 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -4,17 +4,8 @@ includes = [global_inc] includes += include_directories('../librte_eal/common/include/arch/' + arch_subdir) -sources = files('rte_telemetry.c','rte_telemetry_parser.c', 'rte_telemetry_parser_test.c', - 'telemetry.c', 'telemetry_legacy.c') -headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h') +sources = files('telemetry.c', 'telemetry_legacy.c') +headers = files('rte_telemetry.h') cflags += '-DALLOW_EXPERIMENTAL_API' includes += include_directories('../librte_metrics') - -jansson = dependency('jansson', required: false) -if jansson.found() - ext_deps += jansson - dpdk_app_link_libraries += ['telemetry'] -else - build = false - reason = 'missing dependency "jansson"' -endif +dpdk_app_link_libraries += ['telemetry'] diff --git a/lib/librte_telemetry/rte_telemetry.c b/lib/librte_telemetry/rte_telemetry.c deleted file mode 100644 index 45b6d9d94..000000000 --- a/lib/librte_telemetry/rte_telemetry.c +++ /dev/null @@ -1,1384 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "rte_telemetry.h" -#include "rte_telemetry_internal.h" -#include "rte_telemetry_parser.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 { - const char *test_name; - int (*test_func_ptr)(struct telemetry_impl *telemetry, int fd); -}; - -struct json_data { - char *status_code; - const char *data; - int port; - char *stat_name; - int stat_value; -}; - -/* global array of functions pointers to metrics library */ -const struct metrics_functions *metrics_fns; - -void -rte_telemetry_set_metrics_fns(const struct metrics_functions *fns) -{ - metrics_fns = fns; -} - -static void -rte_telemetry_get_runtime_dir(char *socket_path, size_t size) -{ - snprintf(socket_path, size, "%s/telemetry", rte_eal_get_runtime_dir()); -} - -static int32_t -rte_telemetry_write_to_socket(struct telemetry_impl *telemetry, - const char *json_string) -{ - int ret; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Could not initialise TELEMETRY_API"); - return -1; - } - - if (telemetry->request_client == NULL) { - TELEMETRY_LOG_ERR("No client has been chosen to write to"); - return -1; - } - - if (json_string == NULL) { - TELEMETRY_LOG_ERR("Invalid JSON string!"); - return -1; - } - - ret = send(telemetry->request_client->fd, - json_string, strlen(json_string), 0); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to write to socket for client: %s", - telemetry->request_client->file_path); - return -1; - } - - return 0; -} - -int32_t -rte_telemetry_send_error_response(struct telemetry_impl *telemetry, - int error_type) -{ - int ret; - const char *status_code, *json_buffer; - json_t *root; - - if (error_type == -EPERM) - status_code = "Status Error: Unknown"; - else if (error_type == -EINVAL) - status_code = "Status Error: Invalid Argument 404"; - else if (error_type == -ENOMEM) - status_code = "Status Error: Memory Allocation Error"; - else { - TELEMETRY_LOG_ERR("Invalid error type"); - return -EINVAL; - } - - root = json_object(); - - if (root == NULL) { - TELEMETRY_LOG_ERR("Could not create root JSON object"); - return -EPERM; - } - - ret = json_object_set_new(root, "status_code", json_string(status_code)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Status code field cannot be set"); - json_decref(root); - return -EPERM; - } - - ret = json_object_set_new(root, "data", json_null()); - if (ret < 0) { - TELEMETRY_LOG_ERR("Data field cannot be set"); - json_decref(root); - return -EPERM; - } - - json_buffer = json_dumps(root, 0); - json_decref(root); - - ret = rte_telemetry_write_to_socket(telemetry, json_buffer); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not write to socket"); - return -EPERM; - } - - return 0; -} - -int32_t -rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, - struct telemetry_impl *telemetry) -{ - int ret; - char *json_buffer = NULL; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - ret = metrics_fns->encode_json_format(ep, &json_buffer); - if (ret < 0) { - TELEMETRY_LOG_ERR("JSON encode function failed"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_write_to_socket(telemetry, json_buffer); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not write to socket"); - return -1; - } - - return 0; -} - -int32_t -rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, - struct telemetry_impl *telemetry) -{ - int ret; - char *json_buffer = NULL; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (ep == NULL) { - TELEMETRY_LOG_ERR("Invalid encode param argument"); - goto einval_fail; - } - - if (ep->pp.num_metric_ids < 0) { - TELEMETRY_LOG_ERR("Invalid num_metric_ids, must be positive"); - goto einval_fail; - } - - if (ep->pp.num_port_ids < 0) { - TELEMETRY_LOG_ERR("Invalid num_port_ids, must be positive"); - goto einval_fail; - } - - ret = metrics_fns->get_ports_stats_json(ep, telemetry->reg_index, - &json_buffer); - if (ret < 0) { - TELEMETRY_LOG_ERR("Function for get_ports_stats_json" - " failed"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_write_to_socket(telemetry, json_buffer); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not write to socket"); - return -1; - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_initial_accept(struct telemetry_impl *telemetry) -{ - int ret; - int selftest = 0; - - ret = metrics_fns->reg_all_ethdev(&telemetry->metrics_register_done, - telemetry->reg_index); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to register ethdev metrics"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - if (selftest) { - ret = rte_telemetry_socket_messaging_testing(telemetry->reg_index[0], - 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; -} - -static int32_t -rte_telemetry_read_client(struct telemetry_impl *telemetry) -{ - char buf[BUF_SIZE]; - int ret, buffer_read; - - buffer_read = read(telemetry->accept_fd, buf, BUF_SIZE-1); - - if (buffer_read == -1) { - TELEMETRY_LOG_ERR("Read error"); - return -1; - } else if (buffer_read == 0) { - goto close_socket; - } else { - buf[buffer_read] = '\0'; - ret = rte_telemetry_parse_client_message(telemetry, buf); - if (ret < 0) - TELEMETRY_LOG_WARN("Parse message failed"); - goto close_socket; - } - -close_socket: - if (close(telemetry->accept_fd) < 0) { - TELEMETRY_LOG_ERR("Close TELEMETRY socket failed"); - free(telemetry); - return -EPERM; - } - telemetry->accept_fd = 0; - - return 0; -} - -static int32_t -rte_telemetry_accept_new_client(struct telemetry_impl *telemetry) -{ - int ret; - - if (telemetry->accept_fd <= 0) { - ret = listen(telemetry->server_fd, 1); - if (ret < 0) { - TELEMETRY_LOG_ERR("Listening error with server fd"); - return -1; - } - - telemetry->accept_fd = accept(telemetry->server_fd, NULL, NULL); - if (telemetry->accept_fd >= 0 && - telemetry->metrics_register_done == 0) { - ret = rte_telemetry_initial_accept(telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to run initial configurations/tests"); - return -1; - } - } - } else { - ret = rte_telemetry_read_client(telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Failed to read socket buffer"); - return -1; - } - } - - return 0; -} - -static int32_t -rte_telemetry_read_client_sockets(struct telemetry_impl *telemetry) -{ - int ret; - telemetry_client *client; - char client_buf[BUF_SIZE]; - int bytes; - - TAILQ_FOREACH(client, &telemetry->client_list_head, client_list) { - bytes = read(client->fd, client_buf, BUF_SIZE-1); - - if (bytes > 0) { - client_buf[bytes] = '\0'; - telemetry->request_client = client; - ret = rte_telemetry_parse(telemetry, client_buf); - if (ret < 0) { - TELEMETRY_LOG_WARN("Parse socket input failed: %i", - ret); - return -1; - } - } - } - - return 0; -} - -static int32_t -rte_telemetry_run(void *userdata) -{ - int ret; - struct telemetry_impl *telemetry = userdata; - - if (telemetry == NULL) { - TELEMETRY_LOG_WARN("TELEMETRY could not be initialised"); - return -1; - } - - ret = rte_telemetry_accept_new_client(telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Accept and read new client failed"); - return -1; - } - - ret = rte_telemetry_read_client_sockets(telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Client socket read failed"); - return -1; - } - - return 0; -} - -static void -*rte_telemetry_run_thread_func(void *userdata) -{ - int ret; - struct telemetry_impl *telemetry = userdata; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("%s passed a NULL instance", __func__); - pthread_exit(0); - } - - while (telemetry->thread_status) { - rte_telemetry_run(telemetry); - ret = usleep(SLEEP_TIME); - if (ret < 0) - TELEMETRY_LOG_ERR("Calling thread could not be put to sleep"); - } - pthread_exit(0); -} - -static int32_t -rte_telemetry_set_socket_nonblock(int fd) -{ - int flags; - - if (fd < 0) { - TELEMETRY_LOG_ERR("Invalid fd provided"); - return -1; - } - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - flags = 0; - - return fcntl(fd, F_SETFL, flags | O_NONBLOCK); -} - -static int32_t -rte_telemetry_create_socket(struct telemetry_impl *telemetry) -{ - int ret; - struct sockaddr_un addr; - char socket_path[BUF_SIZE]; - - if (telemetry == NULL) - return -1; - - telemetry->server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (telemetry->server_fd == -1) { - TELEMETRY_LOG_ERR("Failed to open socket"); - return -1; - } - - ret = rte_telemetry_set_socket_nonblock(telemetry->server_fd); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not set socket to NONBLOCK"); - goto close_socket; - } - - 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)); - unlink(socket_path); - - if (bind(telemetry->server_fd, (struct sockaddr *)&addr, - sizeof(addr)) < 0) { - TELEMETRY_LOG_ERR("Socket binding error"); - goto close_socket; - } - - return 0; - -close_socket: - if (close(telemetry->server_fd) < 0) { - TELEMETRY_LOG_ERR("Close TELEMETRY socket failed"); - return -EPERM; - } - - return -1; -} - -int32_t -rte_telemetry_init(void) -{ - int ret; - pthread_attr_t attr; - const char *telemetry_ctrl_thread = "telemetry"; - - if (static_telemetry) { - TELEMETRY_LOG_WARN("TELEMETRY structure already initialised"); - return -EALREADY; - } - - static_telemetry = calloc(1, sizeof(struct telemetry_impl)); - if (static_telemetry == NULL) { - TELEMETRY_LOG_ERR("Memory could not be allocated"); - return -ENOMEM; - } - - static_telemetry->socket_id = rte_socket_id(); - - ret = pthread_attr_init(&attr); - if (ret != 0) { - TELEMETRY_LOG_ERR("Pthread attribute init failed"); - return -EPERM; - } - - ret = rte_telemetry_create_socket(static_telemetry); - if (ret < 0) { - ret = rte_telemetry_cleanup(); - if (ret < 0) - TELEMETRY_LOG_ERR("TELEMETRY cleanup failed"); - return -EPERM; - } - TAILQ_INIT(&static_telemetry->client_list_head); - - ret = rte_ctrl_thread_create(&static_telemetry->thread_id, - telemetry_ctrl_thread, &attr, rte_telemetry_run_thread_func, - (void *)static_telemetry); - static_telemetry->thread_status = 1; - - if (ret < 0) { - ret = rte_telemetry_cleanup(); - if (ret < 0) - TELEMETRY_LOG_ERR("TELEMETRY cleanup failed"); - return -EPERM; - } - - if (rte_telemetry_new_init() != 0) - return -1; - - return 0; -} - -static int32_t -rte_telemetry_client_cleanup(struct telemetry_client *client) -{ - int ret; - - ret = close(client->fd); - free(client->file_path); - free(client); - - if (ret < 0) { - TELEMETRY_LOG_ERR("Close client socket failed"); - return -EPERM; - } - - return 0; -} - -int32_t -rte_telemetry_cleanup(void) -{ - int ret; - struct telemetry_impl *telemetry = static_telemetry; - telemetry_client *client, *temp_client; - - TAILQ_FOREACH_SAFE(client, &telemetry->client_list_head, client_list, - temp_client) { - TAILQ_REMOVE(&telemetry->client_list_head, client, client_list); - ret = rte_telemetry_client_cleanup(client); - if (ret < 0) { - TELEMETRY_LOG_ERR("Client cleanup failed"); - return -EPERM; - } - } - - ret = close(telemetry->server_fd); - if (ret < 0) { - TELEMETRY_LOG_ERR("Close TELEMETRY socket failed"); - free(telemetry); - return -EPERM; - } - - telemetry->thread_status = 0; - pthread_join(telemetry->thread_id, NULL); - free(telemetry); - static_telemetry = NULL; - - return 0; -} - -int32_t -rte_telemetry_unregister_client(struct telemetry_impl *telemetry, - const char *client_path) -{ - int ret; - telemetry_client *client, *temp_client; - - if (telemetry == NULL) { - TELEMETRY_LOG_WARN("TELEMETRY is not initialised"); - return -ENODEV; - } - - if (client_path == NULL) { - TELEMETRY_LOG_ERR("Invalid client path"); - goto einval_fail; - } - - if (TAILQ_EMPTY(&telemetry->client_list_head)) { - TELEMETRY_LOG_ERR("There are no clients currently registered"); - return -EPERM; - } - - TAILQ_FOREACH_SAFE(client, &telemetry->client_list_head, client_list, - temp_client) { - if (strcmp(client_path, client->file_path) == 0) { - TAILQ_REMOVE(&telemetry->client_list_head, client, - client_list); - ret = rte_telemetry_client_cleanup(client); - - if (ret < 0) { - TELEMETRY_LOG_ERR("Client cleanup failed"); - return -EPERM; - } - - return 0; - } - } - - TELEMETRY_LOG_WARN("Couldn't find client, possibly not registered yet."); - return -1; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -EINVAL; -} - -int32_t -rte_telemetry_register_client(struct telemetry_impl *telemetry, - const char *client_path) -{ - int ret, fd; - struct sockaddr_un addrs; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Could not initialize TELEMETRY API"); - return -ENODEV; - } - - if (client_path == NULL) { - TELEMETRY_LOG_ERR("Invalid client path"); - return -EINVAL; - } - - telemetry_client *client; - TAILQ_FOREACH(client, &telemetry->client_list_head, client_list) { - if (strcmp(client_path, client->file_path) == 0) { - TELEMETRY_LOG_WARN("'%s' already registered", - client_path); - return -EINVAL; - } - } - - fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (fd == -1) { - TELEMETRY_LOG_ERR("Client socket error"); - return -EACCES; - } - - ret = rte_telemetry_set_socket_nonblock(fd); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not set socket to NONBLOCK"); - return -EPERM; - } - - addrs.sun_family = AF_UNIX; - strlcpy(addrs.sun_path, client_path, sizeof(addrs.sun_path)); - telemetry_client *new_client = malloc(sizeof(telemetry_client)); - new_client->file_path = strdup(client_path); - new_client->fd = fd; - - if (connect(fd, (struct sockaddr *)&addrs, sizeof(addrs)) == -1) { - TELEMETRY_LOG_ERR("TELEMETRY client connect to %s didn't work", - client_path); - ret = rte_telemetry_client_cleanup(new_client); - if (ret < 0) { - TELEMETRY_LOG_ERR("Client cleanup failed"); - return -EPERM; - } - return -EINVAL; - } - - TAILQ_INSERT_HEAD(&telemetry->client_list_head, new_client, client_list); - - return 0; -} - -int32_t -rte_telemetry_parse_client_message(struct telemetry_impl *telemetry, char *buf) -{ - int ret, action_int; - json_error_t error; - json_t *root = json_loads(buf, 0, &error); - - if (root == NULL) { - TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s", - error.text); - goto fail; - } else if (!json_is_object(root)) { - TELEMETRY_LOG_WARN("JSON Request is not a JSON object"); - goto fail; - } - - json_t *action = json_object_get(root, "action"); - if (action == NULL) { - TELEMETRY_LOG_WARN("Request does not have action field"); - goto fail; - } else if (!json_is_integer(action)) { - TELEMETRY_LOG_WARN("Action value is not an integer"); - goto fail; - } - - json_t *command = json_object_get(root, "command"); - if (command == NULL) { - TELEMETRY_LOG_WARN("Request does not have command field"); - goto fail; - } else if (!json_is_string(command)) { - TELEMETRY_LOG_WARN("Command value is not a string"); - goto fail; - } - - action_int = json_integer_value(action); - if (action_int != ACTION_POST) { - TELEMETRY_LOG_WARN("Invalid action code"); - goto fail; - } - - if (strcmp(json_string_value(command), "clients") != 0) { - TELEMETRY_LOG_WARN("Invalid command"); - goto fail; - } - - json_t *data = json_object_get(root, "data"); - if (data == NULL) { - TELEMETRY_LOG_WARN("Request does not have data field"); - goto fail; - } - - json_t *client_path = json_object_get(data, "client_path"); - if (client_path == NULL) { - TELEMETRY_LOG_WARN("Request does not have client_path field"); - goto fail; - } - - if (!json_is_string(client_path)) { - TELEMETRY_LOG_WARN("Client_path value is not a string"); - goto fail; - } - - ret = rte_telemetry_register_client(telemetry, - json_string_value(client_path)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not register client"); - telemetry->register_fail_count++; - goto fail; - } - - return 0; - -fail: - TELEMETRY_LOG_WARN("Client attempted to register with invalid message"); - json_decref(root); - return -1; -} - -static int32_t -rte_telemetry_dummy_client_socket(const char *valid_client_path) -{ - int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 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[0] = 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_SEQPACKET, 0); - *recv_fd = socket(AF_UNIX, SOCK_SEQPACKET, 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; - const char *status = "Status Error: Invalid Argument 404"; - const 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"; - const 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; - -static struct rte_option option = { - .name = "telemetry", - .usage = "Enable telemetry backend", - .cb = &rte_telemetry_init, - .enabled = 0 -}; - -RTE_INIT(rte_telemetry_register) -{ - telemetry_log_level = rte_log_register("lib.telemetry"); - if (telemetry_log_level >= 0) - rte_log_set_level(telemetry_log_level, RTE_LOG_ERR); - - rte_option_register(&option); -} diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h index 13ce235cb..2b988e6cb 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -15,8 +15,9 @@ * RTE Telemetry * * The telemetry library provides a method to retrieve statistics from - * DPDK by sending a JSON encoded message over a socket. DPDK will send + * DPDK by sending a request message over a socket. DPDK will send * a JSON encoded response containing telemetry data. + * ***/ /** @@ -46,56 +47,6 @@ typedef int (*telemetry_cb)(const char *cmd, const char *params, */ typedef void * (*handler)(void *sock_id); -/** - * @warning - * @b EXPERIMENTAL: this API may change without prior notice - * - * Initialize Telemetry - * - * @return - * 0 on successful initialisation. - * @return - * -ENOMEM on memory allocation error - * @return - * -EPERM on unknown error failure - * @return - * -EALREADY if Telemetry is already initialised. - */ -__rte_experimental -int32_t -rte_telemetry_init(void); - -/** - * @warning - * @b EXPERIMENTAL: this API may change without prior notice - * - * Clean up and free memory. - * - * @return - * 0 on success - * @return - * -EPERM on failure - */ -__rte_experimental -int32_t -rte_telemetry_cleanup(void); - -/** - * @warning - * @b EXPERIMENTAL: this API may change without prior notice - * - * 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 - */ -__rte_experimental -int32_t -rte_telemetry_selftest(void); - /** * @warning * @b EXPERIMENTAL: this API may change without prior notice @@ -116,7 +67,7 @@ int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); * @warning * @b EXPERIMENTAL: this API may change without prior notice * - * Initialize new version of Telemetry. + * Initialize Telemetry. * * @return * 0 on success. @@ -124,6 +75,6 @@ int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); * -1 on failure. */ __rte_experimental -int rte_telemetry_new_init(void); +int rte_telemetry_init(void); #endif diff --git a/lib/librte_telemetry/rte_telemetry_internal.h b/lib/librte_telemetry/rte_telemetry_internal.h deleted file mode 100644 index 2ef72b1ec..000000000 --- a/lib/librte_telemetry/rte_telemetry_internal.h +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include -#include -#include -#include - -#ifndef _RTE_TELEMETRY_INTERNAL_H_ -#define _RTE_TELEMETRY_INTERNAL_H_ - -/* function types for the functions coming from metrics library */ -typedef int32_t (*metrics_tel_reg_all_ethdev_t)(int *metrics_register_done, - int *reg_index_list); - -typedef int32_t (*metrics_tel_encode_json_format_t)( - struct telemetry_encode_param *ep, char **json_buffer); - -typedef int32_t (*metrics_tel_get_port_stats_ids_t)( - struct telemetry_encode_param *ep); - -typedef int32_t (*metrics_tel_get_ports_stats_json_t)( - struct telemetry_encode_param *ep, - int *reg_index, char **json_buffer); - -typedef int32_t (*metrics_tel_extract_data_t)(struct telemetry_encode_param *ep, - json_t *data); - -struct metrics_functions { - metrics_tel_reg_all_ethdev_t reg_all_ethdev; - metrics_tel_encode_json_format_t encode_json_format; - metrics_tel_get_port_stats_ids_t get_port_stats_ids; - metrics_tel_get_ports_stats_json_t get_ports_stats_json; - metrics_tel_extract_data_t extract_data; -}; -extern const struct metrics_functions *metrics_fns; - -/* API for use by metrics libraries to provide the functions to use */ -__rte_experimental -void rte_telemetry_set_metrics_fns(const struct metrics_functions *fns); - -/* Logging Macros */ -extern int telemetry_log_level; - -#define TELEMETRY_LOG(level, fmt, args...) \ - rte_log(RTE_LOG_ ##level, telemetry_log_level, "%s(): "fmt "\n", \ - __func__, ##args) - -#define TELEMETRY_LOG_ERR(fmt, args...) \ - TELEMETRY_LOG(ERR, fmt, ## args) - -#define TELEMETRY_LOG_WARN(fmt, args...) \ - TELEMETRY_LOG(WARNING, fmt, ## args) - -#define TELEMETRY_LOG_INFO(fmt, args...) \ - TELEMETRY_LOG(INFO, fmt, ## args) - -#define MAX_METRICS 256 - -typedef struct telemetry_client { - char *file_path; - int fd; - TAILQ_ENTRY(telemetry_client) client_list; -} telemetry_client; - -typedef struct telemetry_impl { - int accept_fd; - int server_fd; - pthread_t thread_id; - int thread_status; - uint32_t socket_id; - int reg_index[RTE_MAX_ETHPORTS]; - int metrics_register_done; - TAILQ_HEAD(, telemetry_client) client_list_head; - struct telemetry_client *request_client; - int register_fail_count; -} telemetry_impl; - -enum rte_telemetry_parser_actions { - ACTION_GET = 0, - ACTION_DELETE = 2 -}; - -int32_t -rte_telemetry_parse_client_message(struct telemetry_impl *telemetry, char *buf); - -int32_t -rte_telemetry_send_error_response(struct telemetry_impl *telemetry, - int error_type); - -int32_t -rte_telemetry_register_client(struct telemetry_impl *telemetry, - const char *client_path); - -int32_t -rte_telemetry_unregister_client(struct telemetry_impl *telemetry, - const char *client_path); - -int32_t -rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep, - struct telemetry_impl *telemetry); - -int32_t -rte_telemetry_socket_messaging_testing(int index, int socket); - -int32_t -rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep, - struct telemetry_impl *telemetry); - -int32_t -rte_telemetry_parser_test(struct telemetry_impl *telemetry); - -#endif diff --git a/lib/librte_telemetry/rte_telemetry_parser.c b/lib/librte_telemetry/rte_telemetry_parser.c deleted file mode 100644 index 7dc84c2cf..000000000 --- a/lib/librte_telemetry/rte_telemetry_parser.c +++ /dev/null @@ -1,435 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "rte_telemetry_internal.h" -#include "rte_telemetry_parser.h" - -typedef int (*command_func)(struct telemetry_impl *, int, json_t *); - -struct rte_telemetry_command { - const char *text; - command_func fn; -} command; - -static int32_t -rte_telemetry_command_clients(struct telemetry_impl *telemetry, int action, - json_t *data) -{ - int ret; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (action != ACTION_DELETE) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - goto einval_fail; - } - - if (!json_is_object(data)) { - TELEMETRY_LOG_WARN("Invalid data provided for this command"); - goto einval_fail; - } - - json_t *client_path = json_object_get(data, "client_path"); - if (!json_is_string(client_path)) { - TELEMETRY_LOG_WARN("Command value is not a string"); - goto einval_fail; - } - - ret = rte_telemetry_unregister_client(telemetry, - json_string_value(client_path)); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not unregister client"); - goto einval_fail; - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_command_ports(struct telemetry_impl *telemetry, int action, - json_t *data) -{ - int ret; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (!json_is_null(data)) { - TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'ports' command"); - goto einval_fail; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - goto einval_fail; - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_command_ports_details(struct telemetry_impl *telemetry, - int action, json_t *data) -{ - json_t *value, *port_ids_json = json_object_get(data, "ports"); - uint64_t num_port_ids = json_array_size(port_ids_json); - int ret, port_ids[num_port_ids]; - RTE_SET_USED(port_ids); - size_t index; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - goto einval_fail; - } - - if (!json_is_object(data)) { - TELEMETRY_LOG_WARN("Invalid data provided for this command"); - goto einval_fail; - } - - if (!json_is_array(port_ids_json)) { - TELEMETRY_LOG_WARN("Invalid Port ID array"); - goto einval_fail; - } - - json_array_foreach(port_ids_json, index, value) { - if (!json_is_integer(value)) { - TELEMETRY_LOG_WARN("Port ID given is invalid"); - goto einval_fail; - } - port_ids[index] = json_integer_value(value); - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_command_port_stats(struct telemetry_impl *telemetry, int action, - json_t *data) -{ - int ret; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (!json_is_null(data)) { - TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'port_stats' command"); - goto einval_fail; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - goto einval_fail; - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; -} - -static int32_t -rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry, - int action, json_t *data) -{ - int ret; - struct telemetry_encode_param ep; - - memset(&ep, 0, sizeof(ep)); - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - if (json_is_object(data)) { - TELEMETRY_LOG_WARN("Invalid data provided for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = metrics_fns->get_port_stats_ids(&ep); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not get ports stat values"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_send_ports_stats_values(&ep, telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Sending ports stats values failed"); - return -1; - } - - return 0; -} - -static int32_t -rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry, - int action, json_t *data) -{ - int ret; - struct telemetry_encode_param ep = { .type = GLOBAL_STATS }; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - if (json_is_object(data)) { - TELEMETRY_LOG_WARN("Invalid data provided for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_send_global_stats_values(&ep, telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Sending global stats values failed"); - return -1; - } - - return 0; -} - -static int32_t -rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl - *telemetry, int action, json_t *data) -{ - int ret; - struct telemetry_encode_param ep; - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - if (action != ACTION_GET) { - TELEMETRY_LOG_WARN("Invalid action for this command"); - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = metrics_fns->extract_data(&ep, data); - if (ret < 0) { - TELEMETRY_LOG_ERR("Extracting JSON data failed"); - ret = rte_telemetry_send_error_response(telemetry, ret); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -1; - } - - ret = rte_telemetry_send_ports_stats_values(&ep, telemetry); - if (ret < 0) { - TELEMETRY_LOG_ERR("Sending ports stats values failed"); - return -1; - } - - return 0; -} - -static int32_t -rte_telemetry_parse_command(struct telemetry_impl *telemetry, int action, - const char *command, json_t *data) -{ - int ret; - uint32_t i; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - struct rte_telemetry_command commands[] = { - { - .text = "clients", - .fn = &rte_telemetry_command_clients - }, - { - .text = "ports", - .fn = &rte_telemetry_command_ports - }, - { - .text = "ports_details", - .fn = &rte_telemetry_command_ports_details - }, - { - .text = "port_stats", - .fn = &rte_telemetry_command_port_stats - }, - { - .text = "ports_stats_values_by_name", - .fn = &rte_telemetry_command_ports_stats_values_by_name - }, - { - .text = "ports_all_stat_values", - .fn = &rte_telemetry_command_ports_all_stat_values - }, - { - .text = "global_stat_values", - .fn = &rte_telemetry_command_global_stat_values - } - }; - - const uint32_t num_commands = RTE_DIM(commands); - - for (i = 0; i < num_commands; i++) { - if (strcmp(command, commands[i].text) == 0) { - ret = commands[i].fn(telemetry, action, data); - if (ret < 0) { - TELEMETRY_LOG_ERR("Command Function for %s failed", - commands[i].text); - return -1; - } - return 0; - } - } - - TELEMETRY_LOG_WARN("\"%s\" command not found", command); - - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - - return -1; -} - -int32_t -rte_telemetry_parse(struct telemetry_impl *telemetry, char *socket_rx_data) -{ - int ret, action_int; - json_error_t error; - json_t *root, *action, *command, *data; - - if (telemetry == NULL) { - TELEMETRY_LOG_ERR("Invalid telemetry argument"); - return -1; - } - - root = json_loads(socket_rx_data, 0, &error); - if (root == NULL) { - TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s", - error.text); - ret = rte_telemetry_send_error_response(telemetry, -EPERM); - if (ret < 0) - TELEMETRY_LOG_ERR("Could not send error"); - return -EPERM; - } else if (!json_is_object(root)) { - TELEMETRY_LOG_WARN("JSON Request is not a JSON object"); - json_decref(root); - goto einval_fail; - } - - action = json_object_get(root, "action"); - if (action == NULL) { - TELEMETRY_LOG_WARN("Request does not have action field"); - goto einval_fail; - } else if (!json_is_integer(action)) { - TELEMETRY_LOG_WARN("Action value is not an integer"); - goto einval_fail; - } - - command = json_object_get(root, "command"); - if (command == NULL) { - TELEMETRY_LOG_WARN("Request does not have command field"); - goto einval_fail; - } else if (!json_is_string(command)) { - TELEMETRY_LOG_WARN("Command value is not a string"); - goto einval_fail; - } - - action_int = json_integer_value(action); - if (action_int != ACTION_GET && action_int != ACTION_DELETE) { - TELEMETRY_LOG_WARN("Invalid action code"); - goto einval_fail; - } - - const char *command_string = json_string_value(command); - data = json_object_get(root, "data"); - if (data == NULL) { - TELEMETRY_LOG_WARN("Request does not have data field"); - goto einval_fail; - } - - ret = rte_telemetry_parse_command(telemetry, action_int, command_string, - data); - if (ret < 0) { - TELEMETRY_LOG_WARN("Could not parse command"); - return -EINVAL; - } - - return 0; - -einval_fail: - ret = rte_telemetry_send_error_response(telemetry, -EINVAL); - if (ret < 0) { - TELEMETRY_LOG_ERR("Could not send error"); - return -EPERM; - } - return -EINVAL; -} diff --git a/lib/librte_telemetry/rte_telemetry_parser.h b/lib/librte_telemetry/rte_telemetry_parser.h deleted file mode 100644 index 28b808d8a..000000000 --- a/lib/librte_telemetry/rte_telemetry_parser.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include "rte_telemetry_internal.h" -#include "rte_compat.h" - -#ifndef _RTE_TELEMETRY_PARSER_H_ -#define _RTE_TELEMETRY_PARSER_H_ - -__rte_experimental -int32_t -rte_telemetry_parse(struct telemetry_impl *telemetry, char *socket_rx_data); - -#endif diff --git a/lib/librte_telemetry/rte_telemetry_parser_test.c b/lib/librte_telemetry/rte_telemetry_parser_test.c deleted file mode 100644 index 6164ef83e..000000000 --- a/lib/librte_telemetry/rte_telemetry_parser_test.c +++ /dev/null @@ -1,533 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "rte_telemetry_parser.h" -#include "rte_telemetry_internal.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" - -static 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_SEQPACKET, 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; -} - -static 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; -} - -static int32_t -rte_telemetry_create_json_request(int action, const 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; -} - -static int32_t -rte_telemetry_send_get_ports_and_stats_request(struct telemetry_impl *telemetry, - int action_choice, const char *command_choice, int inv_choice) -{ - int ret; - char *request; - const 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; -} - -static 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; - } - - const 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; -} - -static 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; - const 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; -} - -static 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; - } - - const 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" - }; - - - uint32_t i; - for (i = 0; i < RTE_DIM(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_socket_tests.h b/lib/librte_telemetry/rte_telemetry_socket_tests.h deleted file mode 100644 index db9167c5d..000000000 --- a/lib/librte_telemetry/rte_telemetry_socket_tests.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#include - -#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 2db0a5a44..d7ed1fe11 100644 --- a/lib/librte_telemetry/rte_telemetry_version.map +++ b/lib/librte_telemetry/rte_telemetry_version.map @@ -1,14 +1,8 @@ EXPERIMENTAL { global: - rte_telemetry_cleanup; rte_telemetry_init; - rte_telemetry_parse; - rte_telemetry_selftest; - rte_telemetry_set_metrics_fns; - rte_telemetry_new_init; rte_telemetry_register_cmd; - rte_telemetry_legacy_init; rte_telemetry_legacy_register; local: *; diff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c index e77672b48..a81cad4ec 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "rte_telemetry.h" #include "rte_telemetry_legacy.h" @@ -225,7 +226,7 @@ create_socket(char *path) return -1; } -static int __rte_unused /* will be used in future commit */ +static int telemetry_legacy_init(const char *runtime_dir, const char **err_str) { pthread_t t_old; @@ -278,12 +279,26 @@ telemetry_v2_init(const char *runtime_dir, const char **err_str) } int32_t -rte_telemetry_new_init(void) +rte_telemetry_init(void) { const char *error_str; if (telemetry_v2_init(rte_eal_get_runtime_dir(), &error_str) != 0) { printf("Error initialising telemetry - %s", error_str); return -1; } + if (telemetry_legacy_init(rte_eal_get_runtime_dir(), &error_str) + != 0) + printf("No telemetry legacy support- %s", error_str); return 0; } + +static struct rte_option option = { + .name = "telemetry", + .usage = "Enable telemetry backend", + .cb = &rte_telemetry_init, + .enabled = 0 +}; + +RTE_INIT(telemetry_register_op) { + rte_option_register(&option); +} From patchwork Thu Mar 19 17:19:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66950 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6D4A8A0583; Thu, 19 Mar 2020 18:37:44 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1A0771C10E; Thu, 19 Mar 2020 18:35:18 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id DF3A41C0D4 for ; Thu, 19 Mar 2020 18:35:14 +0100 (CET) IronPort-SDR: RiwwFsuX7xH+FanJWQlNagb0i4o6TnqUDBFVgUFW5YfxZNNpwou41sOu16OX/bzZc1L59gpjeg 6bBXnsEXI4Bw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:14 -0700 IronPort-SDR: 0J20rF+xXwh4/EferB+X6EgBp2S/siIO/iwztoxc6flpXtFH47qnjurL1k6psdzajsC73puDno QzP25yfqcNkA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872751" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:12 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Ciara Power , Bruce Richardson Date: Thu, 19 Mar 2020 17:19:06 +0000 Message-Id: <20200319171907.60891-12-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 11/12] lib: add telemetry as eal dependency X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch moves telemetry further down the build, and adds it as a dependency for EAL. Telemetry is now configured to build by default, and has EAL flags, shown below: "--telemetry" = Enables telemetry (this is default if no flags given) "--no-telemetry" = Disables telemetry When telemetry is enabled, it will attempt to open the new socket version, and also the legacy support socket (this will depend on Jansson external dependency, as before). Signed-off-by: Ciara Power Signed-off-by: Bruce Richardson --- config/common_base | 2 +- lib/Makefile | 5 ++--- lib/librte_eal/common/eal_common_options.c | 9 ++++++++ lib/librte_eal/common/eal_internal_cfg.h | 1 + lib/librte_eal/common/eal_options.h | 4 ++++ lib/librte_eal/freebsd/eal/Makefile | 1 + lib/librte_eal/freebsd/eal/eal.c | 9 ++++++++ lib/librte_eal/freebsd/eal/meson.build | 2 +- lib/librte_eal/linux/eal/Makefile | 1 + lib/librte_eal/linux/eal/eal.c | 9 ++++++++ lib/librte_eal/linux/eal/meson.build | 2 +- lib/librte_eal/meson.build | 2 +- lib/librte_telemetry/Makefile | 1 - lib/librte_telemetry/meson.build | 1 - lib/librte_telemetry/rte_telemetry.h | 2 +- lib/librte_telemetry/telemetry.c | 24 +++++----------------- lib/meson.build | 2 +- mk/rte.app.mk | 3 ++- 18 files changed, 49 insertions(+), 31 deletions(-) diff --git a/config/common_base b/config/common_base index 7ca2f28b1..b48f4469e 100644 --- a/config/common_base +++ b/config/common_base @@ -919,7 +919,7 @@ CONFIG_RTE_LIBRTE_LATENCY_STATS=y # # Compile librte_telemetry # -CONFIG_RTE_LIBRTE_TELEMETRY=n +CONFIG_RTE_LIBRTE_TELEMETRY=y # # Compile librte_rcu diff --git a/lib/Makefile b/lib/Makefile index 31b943817..51a1e3b7a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,8 +4,9 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal -DEPDIRS-librte_eal := librte_kvargs +DEPDIRS-librte_eal := librte_kvargs librte_telemetry DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring @@ -22,8 +23,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile DEPDIRS-librte_cfgfile := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DEPDIRS-librte_cmdline := librte_eal librte_net -DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry -DEPDIRS-librte_telemetry := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ethdev DEPDIRS-librte_ethdev := librte_net librte_eal librte_mempool librte_ring DEPDIRS-librte_ethdev += librte_mbuf diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c index 75974dd5b..386566b3d 100644 --- a/lib/librte_eal/common/eal_common_options.c +++ b/lib/librte_eal/common/eal_common_options.c @@ -86,6 +86,8 @@ eal_long_options[] = { {OPT_LEGACY_MEM, 0, NULL, OPT_LEGACY_MEM_NUM }, {OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM}, {OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM}, + {OPT_TELEMETRY, 0, NULL, OPT_TELEMETRY_NUM }, + {OPT_NO_TELEMETRY, 0, NULL, OPT_NO_TELEMETRY_NUM }, {0, 0, NULL, 0 } }; @@ -1455,6 +1457,11 @@ eal_parse_common_option(int opt, const char *optarg, return -1; } break; + case OPT_TELEMETRY_NUM: + break; + case OPT_NO_TELEMETRY_NUM: + conf->no_telemetry = 1; + break; /* don't know what to do, leave this to caller */ default: @@ -1698,6 +1705,8 @@ eal_common_usage(void) " --"OPT_IN_MEMORY" Operate entirely in memory. This will\n" " disable secondary process support\n" " --"OPT_BASE_VIRTADDR" Base virtual address\n" + " --"OPT_TELEMETRY" Enable telemetry support (on by default)\n" + " --"OPT_NO_TELEMETRY" Disable telemetry support\n" "\nEAL options for DEBUG use only:\n" " --"OPT_HUGE_UNLINK" Unlink hugepage files after init\n" " --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n" diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h index a42f34923..c650bc081 100644 --- a/lib/librte_eal/common/eal_internal_cfg.h +++ b/lib/librte_eal/common/eal_internal_cfg.h @@ -82,6 +82,7 @@ struct internal_config { rte_cpuset_t ctrl_cpuset; /**< cpuset for ctrl threads */ volatile unsigned int init_complete; /**< indicates whether EAL has completed initialization */ + unsigned int no_telemetry; /**< true to disable Telemetry */ }; extern struct internal_config internal_config; /**< Global EAL configuration. */ diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h index 9855429e5..225ad4bb5 100644 --- a/lib/librte_eal/common/eal_options.h +++ b/lib/librte_eal/common/eal_options.h @@ -69,6 +69,10 @@ enum { OPT_IOVA_MODE_NUM, #define OPT_MATCH_ALLOCATIONS "match-allocations" OPT_MATCH_ALLOCATIONS_NUM, +#define OPT_TELEMETRY "telemetry" + OPT_TELEMETRY_NUM, +#define OPT_NO_TELEMETRY "no-telemetry" + OPT_NO_TELEMETRY_NUM, OPT_LONG_MAX_NUM }; diff --git a/lib/librte_eal/freebsd/eal/Makefile b/lib/librte_eal/freebsd/eal/Makefile index b160b5790..cf31cd16e 100644 --- a/lib/librte_eal/freebsd/eal/Makefile +++ b/lib/librte_eal/freebsd/eal/Makefile @@ -19,6 +19,7 @@ LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s LDLIBS += -lrte_kvargs +LDLIBS += -lrte_telemetry EXPORT_MAP := ../../rte_eal_version.map diff --git a/lib/librte_eal/freebsd/eal/eal.c b/lib/librte_eal/freebsd/eal/eal.c index 6ae37e7e6..54acafc31 100644 --- a/lib/librte_eal/freebsd/eal/eal.c +++ b/lib/librte_eal/freebsd/eal/eal.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "eal_private.h" #include "eal_thread.h" @@ -952,6 +953,14 @@ rte_eal_init(int argc, char **argv) rte_eal_init_alert("Cannot clear runtime directory\n"); return -1; } + if (!internal_config.no_telemetry) { + const char *error_str; + if (rte_telemetry_init(rte_eal_get_runtime_dir(), + &error_str) != 0) { + rte_eal_init_alert(error_str); + return -1; + } + } eal_mcfg_complete(); diff --git a/lib/librte_eal/freebsd/eal/meson.build b/lib/librte_eal/freebsd/eal/meson.build index 1426f7e5f..9960837c2 100644 --- a/lib/librte_eal/freebsd/eal/meson.build +++ b/lib/librte_eal/freebsd/eal/meson.build @@ -19,4 +19,4 @@ env_sources = files('eal_alarm.c', 'eal_dev.c' ) -deps += ['kvargs'] +deps += ['kvargs', 'telemetry'] diff --git a/lib/librte_eal/linux/eal/Makefile b/lib/librte_eal/linux/eal/Makefile index e70cf104a..570e9229b 100644 --- a/lib/librte_eal/linux/eal/Makefile +++ b/lib/librte_eal/linux/eal/Makefile @@ -23,6 +23,7 @@ LDLIBS += -lpthread LDLIBS += -lgcc_s LDLIBS += -lrt LDLIBS += -lrte_kvargs +LDLIBS += -lrte_telemetry ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c index 9530ee55f..8eeffe9aa 100644 --- a/lib/librte_eal/linux/eal/eal.c +++ b/lib/librte_eal/linux/eal/eal.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "eal_private.h" #include "eal_thread.h" @@ -1291,6 +1292,14 @@ rte_eal_init(int argc, char **argv) rte_eal_init_alert("Cannot clear runtime directory\n"); return -1; } + if (!internal_config.no_telemetry) { + const char *error_str; + if (rte_telemetry_init(rte_eal_get_runtime_dir(), + &error_str) != 0) { + rte_eal_init_alert(error_str); + return -1; + } + } eal_mcfg_complete(); diff --git a/lib/librte_eal/linux/eal/meson.build b/lib/librte_eal/linux/eal/meson.build index b02b0695f..67ef2fca8 100644 --- a/lib/librte_eal/linux/eal/meson.build +++ b/lib/librte_eal/linux/eal/meson.build @@ -25,7 +25,7 @@ env_sources = files('eal_alarm.c', 'eal_dev.c', ) -deps += ['kvargs'] +deps += ['kvargs', 'telemetry'] if has_libnuma == 1 dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true) endif diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build index 4be5118ce..83ce2dec0 100644 --- a/lib/librte_eal/meson.build +++ b/lib/librte_eal/meson.build @@ -13,7 +13,7 @@ dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1) subdir(exec_env + '/eal') allow_experimental_apis = true -deps += 'kvargs' +deps += ['kvargs', 'telemetry'] if dpdk_conf.has('RTE_USE_LIBBSD') ext_deps += libbsd endif diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index 4982aa457..e9b00a3bb 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -14,7 +14,6 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/ CFLAGS += -pthread -LDLIBS += -lrte_eal LDLIBS += -lpthread EXPORT_MAP := rte_telemetry_version.map diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build index 5d5ac8925..9c24c2066 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -8,4 +8,3 @@ sources = files('telemetry.c', 'telemetry_legacy.c') headers = files('rte_telemetry.h') cflags += '-DALLOW_EXPERIMENTAL_API' includes += include_directories('../librte_metrics') -dpdk_app_link_libraries += ['telemetry'] diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h index 2b988e6cb..094e3006c 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -75,6 +75,6 @@ int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); * -1 on failure. */ __rte_experimental -int rte_telemetry_init(void); +int rte_telemetry_init(const char *runtime_dir, const char **err_str); #endif diff --git a/lib/librte_telemetry/telemetry.c b/lib/librte_telemetry/telemetry.c index a81cad4ec..d4ced4c0c 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "rte_telemetry.h" #include "rte_telemetry_legacy.h" @@ -279,26 +278,13 @@ telemetry_v2_init(const char *runtime_dir, const char **err_str) } int32_t -rte_telemetry_init(void) +rte_telemetry_init(const char *runtime_dir, const char **err_str) { - const char *error_str; - if (telemetry_v2_init(rte_eal_get_runtime_dir(), &error_str) != 0) { - printf("Error initialising telemetry - %s", error_str); + if (telemetry_v2_init(runtime_dir, err_str) != 0) { + printf("Error initialising telemetry - %s", *err_str); return -1; } - if (telemetry_legacy_init(rte_eal_get_runtime_dir(), &error_str) - != 0) - printf("No telemetry legacy support- %s", error_str); + if (telemetry_legacy_init(runtime_dir, err_str) != 0) + printf("No telemetry legacy support- %s", *err_str); return 0; } - -static struct rte_option option = { - .name = "telemetry", - .usage = "Enable telemetry backend", - .cb = &rte_telemetry_init, - .enabled = 0 -}; - -RTE_INIT(telemetry_register_op) { - rte_option_register(&option); -} diff --git a/lib/meson.build b/lib/meson.build index 77bed670e..a2ffc59d9 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -10,8 +10,8 @@ # core libs which are widely reused, so their deps are kept to a minimum. libraries = [ 'kvargs', # eal depends on kvargs + 'telemetry', # basic info querying capability about dpdk processes 'eal', # everything depends on eal - 'telemetry', 'ring', 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core 'cmdline', 'metrics', # bitrate/latency stats depends on this diff --git a/mk/rte.app.mk b/mk/rte.app.mk index fdaf3ec2c..12fe3ce08 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -52,6 +52,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += -lrte_acl _LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += -lrte_jobstats _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-y += $(shell $(PKG_CONFIG) --libs jansson 2> /dev/null) _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += --no-whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats @@ -74,6 +75,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_HASH) += -lrte_hash _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMBER) += -lrte_member _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lrte_vhost _LDLIBS-$(CONFIG_RTE_LIBRTE_KVARGS) += -lrte_kvargs +_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += -lrte_telemetry _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF) += -lrte_mbuf _LDLIBS-$(CONFIG_RTE_LIBRTE_NET) += -lrte_net _LDLIBS-$(CONFIG_RTE_LIBRTE_ETHER) += -lrte_ethdev @@ -90,7 +92,6 @@ _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING) += -lrte_mempool_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_MEMPOOL) += -lrte_mempool_octeontx2 _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci -_LDLIBS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += -lrte_telemetry -ljansson _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder From patchwork Thu Mar 19 17:19:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 66951 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6759AA0583; Thu, 19 Mar 2020 18:37:57 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 5D6401C116; Thu, 19 Mar 2020 18:35:19 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 170401C10D for ; Thu, 19 Mar 2020 18:35:17 +0100 (CET) IronPort-SDR: 1AOGyXua16ojn6xx+tOAu8Ju5z2GBpq27KV0mdRBz+zwrI4zvcEcjEHAIXkGz3Dx0kaTS5TsuS ny6tm5sZDN7Q== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2020 10:35:17 -0700 IronPort-SDR: OazyGZVBF71YT0fF04766aCZeZ37nRB+CjmnnrQ/r2us0vU9lQsO7AHK1ogw+LEvm1DeZmSWFj cCQ/BBpEO7Jw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="391872779" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by orsmga004.jf.intel.com with ESMTP; 19 Mar 2020 10:35:14 -0700 From: Ciara Power To: kevin.laatz@intel.com Cc: dev@dpdk.org, reshma.pattan@intel.com, Bruce Richardson , Ciara Power Date: Thu, 19 Mar 2020 17:19:07 +0000 Message-Id: <20200319171907.60891-13-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319171907.60891-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH 12/12] eal: add eal telemetry callbacks X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson EAL now registers commands to provide some basic info from EAL. Example: Connecting to /var/run/dpdk/rte/dpdk_telemetry.66307 --> / {"/": ["/", "/eal/app_params", "/eal/params", "/eal/version", "/ethdev/list", "/ethdev/stats", "/rawdev/list", "/rawdev/stats"]} --> /eal/app_params {"/eal/app_params": ["-i"]} --> /eal/params {"/eal/params": ["./app/dpdk-testpmd", "--telemetry"]} --> /eal/version {"/eal/version": "DPDK 20.05.0-rc0"} Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- lib/librte_eal/common/eal_common_options.c | 70 ++++++++++++++++++++++ lib/librte_eal/common/eal_options.h | 3 + lib/librte_eal/freebsd/eal/eal.c | 5 ++ lib/librte_eal/linux/eal/eal.c | 5 ++ 4 files changed, 83 insertions(+) diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c index 386566b3d..78cd1f825 100644 --- a/lib/librte_eal/common/eal_common_options.c +++ b/lib/librte_eal/common/eal_common_options.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "eal_internal_cfg.h" #include "eal_options.h" @@ -132,6 +133,75 @@ static int master_lcore_parsed; static int mem_parsed; static int core_parsed; +static char **eal_args; +static char **eal_app_args; + +#define EAL_PARAM_REQ "/eal/params" +#define EAL_APP_PARAM_REQ "/eal/app_params" + +/* callback handler for telemetry library to report out EAL flags */ +int +handle_eal_info_request(const char *cmd, const char *params __rte_unused, + char *buffer, int buf_len) +{ + char **args; + int used = 0; + int i = 0; + + if (strcmp(cmd, EAL_PARAM_REQ) == 0) + args = eal_args; + else if (strcmp(cmd, EAL_APP_PARAM_REQ) == 0) + args = eal_app_args; + else /* version */ + return snprintf(buffer, buf_len, "\"%s\"", rte_version()); + + if (args == NULL || args[0] == NULL) + return snprintf(buffer, buf_len, "[]"); /* empty list */ + + used = strlcpy(buffer, "[", buf_len); + while (args[i] != NULL) + used += snprintf(buffer + used, buf_len - used, "\"%s\",", + args[i++]); + buffer[used - 1] = ']'; + return used; +} + +int +eal_save_args(int argc, char **argv) +{ + int i, j; + + /* clone argv to report out later. We overprovision, but + * this does not waste huge amounts of memory + */ + eal_args = calloc(argc + 1, sizeof(*eal_args)); + if (eal_args == NULL) + return -1; + + for (i = 0; i < argc; i++) { + eal_args[i] = strdup(argv[i]); + if (strcmp(argv[i], "--") == 0) + break; + } + eal_args[i++] = NULL; /* always finish with NULL */ + rte_telemetry_register_cmd(EAL_PARAM_REQ, handle_eal_info_request); + + /* allow reporting of any app args we know about too */ + if (i == argc) + return 0; + + eal_app_args = calloc(argc - i + 1, sizeof(*eal_args)); + if (eal_app_args == NULL) + return -1; + + for (j = 0; i < argc; j++, i++) + eal_app_args[j] = strdup(argv[i]); + eal_app_args[j] = NULL; + rte_telemetry_register_cmd(EAL_APP_PARAM_REQ, handle_eal_info_request); + + return 0; +} + static int eal_option_device_add(enum rte_devtype type, const char *optarg) { diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h index 225ad4bb5..5373e9f5e 100644 --- a/lib/librte_eal/common/eal_options.h +++ b/lib/librte_eal/common/eal_options.h @@ -88,5 +88,8 @@ int eal_check_common_options(struct internal_config *internal_cfg); void eal_common_usage(void); enum rte_proc_type_t eal_proc_type_detect(void); int eal_plugins_init(void); +int eal_save_args(int argc, char **argv); +int handle_eal_info_request(const char *cmd, const char *params __rte_unused, + char *buffer, int buf_len); #endif /* EAL_OPTIONS_H */ diff --git a/lib/librte_eal/freebsd/eal/eal.c b/lib/librte_eal/freebsd/eal/eal.c index 54acafc31..e18bf59f9 100644 --- a/lib/librte_eal/freebsd/eal/eal.c +++ b/lib/librte_eal/freebsd/eal/eal.c @@ -725,6 +725,9 @@ rte_eal_init(int argc, char **argv) eal_reset_internal_config(&internal_config); + /* clone argv to report out later in telemetry */ + eal_save_args(argc, argv); + /* set log level as early as possible */ eal_log_level_parse(argc, argv); @@ -960,6 +963,8 @@ rte_eal_init(int argc, char **argv) rte_eal_init_alert(error_str); return -1; } + rte_telemetry_register_cmd("/eal/version", + handle_eal_info_request); } eal_mcfg_complete(); diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c index 8eeffe9aa..a68b66a1e 100644 --- a/lib/librte_eal/linux/eal/eal.c +++ b/lib/librte_eal/linux/eal/eal.c @@ -992,6 +992,9 @@ rte_eal_init(int argc, char **argv) /* set log level as early as possible */ eal_log_level_parse(argc, argv); + /* clone argv to report out later in telemetry */ + eal_save_args(argc, argv); + if (rte_eal_cpu_init() < 0) { rte_eal_init_alert("Cannot detect lcores."); rte_errno = ENOTSUP; @@ -1299,6 +1302,8 @@ rte_eal_init(int argc, char **argv) rte_eal_init_alert(error_str); return -1; } + rte_telemetry_register_cmd("/eal/version", + handle_eal_info_request); } eal_mcfg_complete();