From patchwork Wed Apr 8 16:49:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68012 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 E766CA0597; Wed, 8 Apr 2020 19:08:06 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 677551C0CE; Wed, 8 Apr 2020 19:08:06 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 3D5B11C0CE for ; Wed, 8 Apr 2020 19:08:05 +0200 (CEST) IronPort-SDR: NEANW/DOokQCPohDp9YxzjUb0pn4oD2xnIeeRsv1viZZjE33915awjuZhmwkpPnzgRoTev9UgY 9bzoqK0p1Tag== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:04 -0700 IronPort-SDR: gBpXldPraETZs5JIRuuq/snWRL4MtaIfKAgsc7RzhHTrorAdofC8+gS6q4cMkUOHKG7jkCPJsR JVnj246JNSXg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880154" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:01 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson Date: Wed, 8 Apr 2020 17:49:41 +0100 Message-Id: <20200408164956.47864-2-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 01/16] build: add arch-specific header path to global includes 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 global include path, which is used by anything built before EAL, points to the EAL header files so they utility macros etc. can be used anywhere in DPDK. This path included the OS-specific EAL header files, but not the architecture-specific ones. This patch moves the selection of target architecture to the top-level meson.build file so that the global include can reference that. Signed-off-by: Bruce Richardson --- config/meson.build | 7 ------- lib/librte_eal/arm/include/meson.build | 2 -- lib/librte_eal/ppc/include/meson.build | 2 -- lib/librte_eal/x86/include/meson.build | 2 -- meson.build | 9 +++++++++ 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/config/meson.build b/config/meson.build index 58421342b1..49482091d5 100644 --- a/config/meson.build +++ b/config/meson.build @@ -229,13 +229,6 @@ dpdk_conf.set('RTE_LIBRTE_DPAA2_USE_PHYS_IOVA', true) compile_time_cpuflags = [] -if host_machine.cpu_family().startswith('x86') - arch_subdir = 'x86' -elif host_machine.cpu_family().startswith('arm') or host_machine.cpu_family().startswith('aarch') - arch_subdir = 'arm' -elif host_machine.cpu_family().startswith('ppc') - arch_subdir = 'ppc' -endif subdir(arch_subdir) dpdk_conf.set('RTE_COMPILE_TIME_CPUFLAGS', ','.join(compile_time_cpuflags)) diff --git a/lib/librte_eal/arm/include/meson.build b/lib/librte_eal/arm/include/meson.build index 1721743240..73b750a18f 100644 --- a/lib/librte_eal/arm/include/meson.build +++ b/lib/librte_eal/arm/include/meson.build @@ -1,8 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation. -includes += include_directories('.') - arch_headers = files( 'rte_atomic_32.h', 'rte_atomic_64.h', diff --git a/lib/librte_eal/ppc/include/meson.build b/lib/librte_eal/ppc/include/meson.build index 3a91c984c4..230c44aa95 100644 --- a/lib/librte_eal/ppc/include/meson.build +++ b/lib/librte_eal/ppc/include/meson.build @@ -1,8 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Luca Boccassi -includes += include_directories('.') - arch_headers = files( 'rte_atomic.h', 'rte_byteorder.h', diff --git a/lib/librte_eal/x86/include/meson.build b/lib/librte_eal/x86/include/meson.build index d336d522c0..f0e998c2fe 100644 --- a/lib/librte_eal/x86/include/meson.build +++ b/lib/librte_eal/x86/include/meson.build @@ -1,8 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -includes += include_directories('.') - arch_headers = files( 'rte_atomic_32.h', 'rte_atomic_64.h', diff --git a/meson.build b/meson.build index d36580438e..8ee79f78d5 100644 --- a/meson.build +++ b/meson.build @@ -24,12 +24,21 @@ dpdk_libs_disabled = [] dpdk_drvs_disabled = [] abi_version_file = files('ABI_VERSION') +if host_machine.cpu_family().startswith('x86') + arch_subdir = 'x86' +elif host_machine.cpu_family().startswith('arm') or host_machine.cpu_family().startswith('aarch') + arch_subdir = 'arm' +elif host_machine.cpu_family().startswith('ppc') + arch_subdir = 'ppc' +endif + # configure the build, and make sure configs here and in config folder are # able to be included in any file. We also store a global array of include dirs # for passing to pmdinfogen scripts global_inc = include_directories('.', 'config', 'lib/librte_eal/include', 'lib/librte_eal/@0@/include'.format(host_machine.system()), + 'lib/librte_eal/@0@/include'.format(arch_subdir), ) subdir('config') From patchwork Wed Apr 8 16:49:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68014 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 33F7BA0597; Wed, 8 Apr 2020 19:08:31 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 17A251C12A; Wed, 8 Apr 2020 19:08:10 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id E63EF1C112 for ; Wed, 8 Apr 2020 19:08:07 +0200 (CEST) IronPort-SDR: mbygkDZNv/cUa8w6xAJTO71473TDNV1zkhHNHb2Bkwj02GWP+/bFXFWYpQPxdg3ak1Ma7YfePZ H+tXgH/NyAGQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:06 -0700 IronPort-SDR: /jdZqCZCSRAS+GYPw70Bi9NT+X8v24tUldjyWVwL3scxrhhQaYFS4+uV1IkqkL+8SJnC7UUYDV P4TxsIHJ23eQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880171" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:04 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power Date: Wed, 8 Apr 2020 17:49:42 +0100 Message-Id: <20200408164956.47864-3-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v2 02/16] 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 | 10 + 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 + 12 files changed, 859 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 46b91ae1a4..07b1ec0b6b 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 6b385f5cf1..252e4745f5 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,15 @@ EXPORT_MAP := rte_metrics_version.map # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +SRCS-y += rte_metrics_telemetry.c +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics_telemetry.h + +LDLIBS += -lrte_ethdev +LDLIBS += -ljansson + +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 e26d1f46c1..0f9f2e0e6f 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 df5e32c59f..9b38d7787c 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 77bffe08e4..466ca98c31 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 0000000000..a6b2616714 --- /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 0000000000..4104f15681 --- /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 85663f356e..c88939b117 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 eb20cc6515..1867b61f6f 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 3f8dbc2db5..ca70e2ed77 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 e8c269e85e..11edf79e81 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 d295ca0a52..e683686147 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 From patchwork Wed Apr 8 16:49:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68015 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 B970AA0597; Wed, 8 Apr 2020 19:08:47 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id C92CA1C194; Wed, 8 Apr 2020 19:08:12 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id F07D51C128 for ; Wed, 8 Apr 2020 19:08:09 +0200 (CEST) IronPort-SDR: 0/w8XuHmnF7jcZQfJF28hFhOrsGa6ykzIprBXCgkZRlLA2dSvkfv4SmVQGCsrazMcbKxPvZYSh Q+AOZ7Maadtg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:09 -0700 IronPort-SDR: mT8oWNGFtlGFjxCLuzdnTUyj6FK+1Wo8RACqxtsy7SXal+txJNpEY535xW1bZ19gIKHEomG6Kg KH/xg1I42JRw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880181" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:07 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power , Bruce Richardson Date: Wed, 8 Apr 2020 17:49:43 +0100 Message-Id: <20200408164956.47864-4-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 03/16] 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 a6b2616714..78c21663df 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 4104f15681..6c2391c563 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 1867b61f6f..2022ce68eb 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 11edf79e81..4e236e1e6a 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 Wed Apr 8 16:49:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68016 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 41A86A0597; Wed, 8 Apr 2020 19:09:00 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 33EAC1C129; Wed, 8 Apr 2020 19:08:15 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 5D5E51C192 for ; Wed, 8 Apr 2020 19:08:12 +0200 (CEST) IronPort-SDR: bM02RDgqnu2yIwNFNyoyvd2DVXovBFJZ3uIN9xmM8qIZJ+MkUjOy3hDO1VCHlp+xIMWj//8nNx XY1bdC1UO57Q== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:12 -0700 IronPort-SDR: kCHFwNuhJEUv9Tn62xeJIOLEeUiLNpDyN7lX7XYO/+fgPfXXG4d96yyJItAd6u0qb2g/n494uZ YDaD9IWDqqRA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880189" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:09 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson Date: Wed, 8 Apr 2020 17:49:44 +0100 Message-Id: <20200408164956.47864-5-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v2 04/16] 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 07b1ec0b6b..31b943817c 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 252e4745f5..5a11b6198b 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -22,6 +22,7 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics_telemetry.h LDLIBS += -lrte_ethdev LDLIBS += -ljansson +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 0f9f2e0e6f..d116857e2d 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 9b38d7787c..e07670219f 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 466ca98c31..fbe64ddf2b 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 78c21663df..31d505551b 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 f364548556..17e651c412 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 26a331140b..b34661ac13 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 2022ce68eb..2fb8ffe873 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 ca70e2ed77..2ef72b1ec3 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 4e236e1e6a..7dc84c2cf3 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 fa62d7718c..a80058c59c 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 9c3cc55d5e..9f3f7dd432 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 e683686147..fdaf3ec2c0 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 Wed Apr 8 16:49:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68017 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 1CE55A0597; Wed, 8 Apr 2020 19:09:16 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 93F9E1C1AD; Wed, 8 Apr 2020 19:08:17 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 5709B1C19F for ; Wed, 8 Apr 2020 19:08:15 +0200 (CEST) IronPort-SDR: xHkTntpuYtPnONK5T2vrIp6xZ8ZhCLPUbtb+TPAw6Bodn8JJG255fzJUkhnA2PKdNlfzAiEXzX CZH1xpjPhuRw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:14 -0700 IronPort-SDR: srt62LsCv/ecYu82PEmkB6gk6AWiMdhNLChUsK+TqJYmLfH6iNq2dfY0VXnWGgSvM7NH7+0HZ4 62Xlv22dBwuQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880202" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:12 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson , Ciara Power Date: Wed, 8 Apr 2020 17:49:45 +0100 Message-Id: <20200408164956.47864-6-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 05/16] 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 --- v2: - Added DPDK information message on client connection. - Added /info command to get DPDK information post-connect. - Replaced pid in socket name with v2. - Increased output buffer size to 16k. - Telemetry default callbacks now registered by init function. --- lib/librte_telemetry/Makefile | 4 + lib/librte_telemetry/meson.build | 5 +- lib/librte_telemetry/rte_telemetry.c | 3 + lib/librte_telemetry/rte_telemetry.h | 70 ++++- .../rte_telemetry_version.map | 2 + lib/librte_telemetry/telemetry.c | 278 ++++++++++++++++++ 6 files changed, 360 insertions(+), 2 deletions(-) create mode 100644 lib/librte_telemetry/telemetry.c diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index 17e651c412..74a6e2d2f7 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/include +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(ARCH_DIR)/include +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 b34661ac13..710c119b7a 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -1,7 +1,10 @@ # 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] + +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 2fb8ffe873..45b6d9d948 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 aedb318598..d0230d4544 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -3,19 +3,59 @@ */ #include +#include #ifndef _RTE_TELEMETRY_H_ #define _RTE_TELEMETRY_H_ +/** Maximum number of telemetry callbacks. */ +#define TELEMETRY_MAX_CALLBACKS 64 + /** + * @warning + * @b EXPERIMENTAL: all functions in this file may change without prior notice + * * @file * 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. ***/ +/** + * 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. + * + * @param cmd + * The cmd that was requested by the client. + * @param params + * Contains data required by the callback function. + * @param buffer + * A buffer to hold the formatted response. + * @param buf_len + * Length of 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); + +/** + * Used for handling data received over a telemetry socket. + * + * @param sock_id + * ID for the socket to be used by the handler. + * + * @return + * Void. + */ +typedef void * (*handler)(void *sock_id); + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice @@ -66,4 +106,32 @@ __rte_experimental int32_t rte_telemetry_selftest(void); +/** + * Used when registering a command and callback function with telemetry. + * + * @param cmd + * The command to register with telemetry. + * @param fn + * Callback function to be called when the command is requested. + * + * @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); + +/** + * 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 a80058c59c..831bbd59ad 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 0000000000..2878c1dbd9 --- /dev/null +++ b/lib/librte_telemetry/telemetry.c @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 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 + +#include "rte_telemetry.h" + +#define MAX_CMD_LEN 56 +#define MAX_OUTPUT_LEN (1024 * 16) + +static int +list_commands(const char *cmd __rte_unused, const char *params __rte_unused, + char *buffer, int buf_len); + +static int +handle_info(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]; +static int num_callbacks; /* 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 int +handle_info(const char *cmd __rte_unused, const char *params __rte_unused, + char *buffer, int buf_len) +{ + int ret = snprintf(buffer, buf_len, + "{\"pid\":%d, \"version\":\"%s\", \"max_output_len\":%d}", + getpid(), rte_version(), MAX_OUTPUT_LEN); + return ret >= buf_len ? -1 : ret; +} + +static void +perform_command(telemetry_cb fn, const char *cmd, const char *param, int s) +{ + char out_buf[MAX_OUTPUT_LEN]; + + 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; + } + char info_buf[1024]; + if (handle_info(NULL, NULL, info_buf, sizeof(info_buf)) < 0) + strlcpy(info_buf, "{}", sizeof(info_buf)); + if (write(s_accepted, info_buf, strlen(info_buf)) < 0) + perror("Error writing to socket"); + 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, const int version) +{ + static char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/dpdk_telemetry.v%d", + strlen(runtime_dir) ? runtime_dir : "/tmp", version); + 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; + + rte_telemetry_register_cmd("/", list_commands); + rte_telemetry_register_cmd("/info", handle_info); + v2_socket.fn = client_handler; + if (strlcpy(v2_socket.path, get_socket_path(runtime_dir, 2), + 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 Wed Apr 8 16:49:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68018 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 18E9FA0597; Wed, 8 Apr 2020 19:09:31 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id F0F541C1B7; Wed, 8 Apr 2020 19:08:19 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 82D321C1A9 for ; Wed, 8 Apr 2020 19:08:17 +0200 (CEST) IronPort-SDR: 0pQlzp4MZjmyuL7dVA8YqCzKBD/4rpIqxkeB67hiubQ2X6PPQG+eBE1tufOERGIgU8dBq+Hhdo qOUMQXSMhdMQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:17 -0700 IronPort-SDR: 2urAisCo/MyBmQZJthVK5UeBUWp48XbeAzNH88V2Y7QuRcrW/bgWWHsJwoNZXTyu8mcHiqaEn0 TmyHVdzgh/mQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880208" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:15 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson Date: Wed, 8 Apr 2020 17:49:46 +0100 Message-Id: <20200408164956.47864-7-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 06/16] telemetry: add utility functions for creating json 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 functions added in this patch will make it easier for applications to build up correct JSON responses to telemetry requests. Signed-off-by: Bruce Richardson --- lib/librte_telemetry/Makefile | 1 + lib/librte_telemetry/meson.build | 2 +- lib/librte_telemetry/rte_telemetry.h | 1 + lib/librte_telemetry/rte_telemetry_json.h | 205 ++++++++++++++++++++++ 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 lib/librte_telemetry/rte_telemetry_json.h diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index 74a6e2d2f7..9012156c1b 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -29,5 +29,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c # export include files SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h +SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include += rte_telemetry_json.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build index 710c119b7a..cc0cdeb5f6 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -5,7 +5,7 @@ includes = [global_inc] 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') +headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h', 'rte_telemetry_json.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 d0230d4544..8b3df04292 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -4,6 +4,7 @@ #include #include +#include #ifndef _RTE_TELEMETRY_H_ #define _RTE_TELEMETRY_H_ diff --git a/lib/librte_telemetry/rte_telemetry_json.h b/lib/librte_telemetry/rte_telemetry_json.h new file mode 100644 index 0000000000..02fcafc73a --- /dev/null +++ b/lib/librte_telemetry/rte_telemetry_json.h @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#ifndef _RTE_TELEMETRY_JSON_H_ +#define _RTE_TELEMETRY_JSON_H_ + +#include +#include +#include + +/** + * @warning + * @b EXPERIMENTAL: all functions in this file may change without prior notice + * + * @file + * RTE Telemetry Utility Functions for Creating JSON Responses + * + * This file contains small inline functions to make it easier for applications + * to build up valid JSON responses to telemetry requests. + * + ***/ + +/** + * @internal + * + * Copies a value into a buffer if the buffer has enough available space. + * Nothing written to buffer if an overflow ocurs. + * This function is not for use for values larger than 1k. + * + * @param buf + * Buffer for data to be appended to. + * @param len + * Length of buffer. + * @param format + * Format string. + * @param ... + * Optional arguments that may be required by the format string. + * + * @return + * Number of characters added to buffer + */ +__attribute__((__format__(__printf__, 3, 4))) +static inline int +__json_snprintf(char *buf, const int len, const char *format, ...) +{ + char tmp[1024]; + va_list ap; + int ret; + + va_start(ap, format); + ret = vsnprintf(tmp, sizeof(tmp), format, ap); + va_end(ap); + if (ret > 0 && ret < (int)sizeof(tmp) && ret < len) { + strcpy(buf, tmp); + return ret; + } + return 0; /* nothing written or modified */ +} + +/** + * Copies an empty array into the provided buffer. + * + * @param buf + * Buffer to hold the empty array. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * + * @return + * Total number of characters in buffer. + */ +static inline int +rte_tel_json_empty_array(char *buf, const int len, const int used) +{ + return used + __json_snprintf(buf + used, len - used, "[]"); +} + +/** + * Copies an empty object into the provided buffer. + * + * @param buf + * Buffer to hold the empty object. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * + * @return + * Total number of characters in buffer + */ +static inline int +rte_tel_json_empty_obj(char *buf, const int len, const int used) +{ + return used + __json_snprintf(buf + used, len - used, "{}"); +} + +/** + * Copies a string into the provided buffer, in JSON format. + * + * @param buf + * Buffer to copy string into. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * @param str + * String value to copy into buffer. + * + * @return + * Total number of characters in buffer + */ +static inline int +rte_tel_json_str(char *buf, const int len, const int used, const char *str) +{ + return used + __json_snprintf(buf + used, len - used, "\"%s\"", str); +} + +/** + * Appends a string into the JSON array in the provided buffer. + * + * @param buf + * Buffer to append array string to. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * @param str + * String value to append to buffer. + * + * @return + * Total number of characters in buffer + */ +static inline int +rte_tel_json_add_array_string(char *buf, const int len, const int used, + const char *str) +{ + int ret, end = used - 1; /* strip off final delimiter */ + if (used <= 2) /* assume empty, since minimum is '[]' */ + return __json_snprintf(buf, len, "[\"%s\"]", str); + + ret = __json_snprintf(buf + end, len - end, ",\"%s\"]", str); + return ret == 0 ? used : end + ret; +} + +/** + * Appends an integer into the JSON array in the provided buffer. + * + * @param buf + * Buffer to append array integer to. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * @param val + * Integer value to append to buffer. + * + * @return + * Total number of characters in buffer + */ +static inline int +rte_tel_json_add_array_int(char *buf, const int len, const int used, int val) +{ + int ret, end = used - 1; /* strip off final delimiter */ + if (used <= 2) /* assume empty, since minimum is '[]' */ + return __json_snprintf(buf, len, "[%d]", val); + + ret = __json_snprintf(buf + end, len - end, ",%d]", val); + return ret == 0 ? used : end + ret; +} + +/** + * Add a new element with uint64_t value to the JSON object stored in the + * provided buffer. + * + * @param buf + * Buffer to append object element to. + * @param len + * Length of buffer. + * @param used + * The number of used characters in the buffer. + * @param name + * String for object element key. + * @param val + * Uint64_t for object element value. + * + * @return + * Total number of characters in buffer + */ +static inline int +rte_tel_json_add_obj_u64(char *buf, const int len, const int used, + const char *name, uint64_t val) +{ + int ret, end = used - 1; + if (used <= 2) /* assume empty, since minimum is '{}' */ + return __json_snprintf(buf, len, "{\"%s\":%"PRIu64"}", name, + val); + + ret = __json_snprintf(buf + end, len - end, ",\"%s\":%"PRIu64"}", + name, val); + return ret == 0 ? used : end + ret; +} + +#endif /*_RTE_TELEMETRY_JSON_H_*/ From patchwork Wed Apr 8 16:49:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68019 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 E70CCA0597; Wed, 8 Apr 2020 19:09:42 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4F5E91C193; Wed, 8 Apr 2020 19:08:22 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id BE54E1C1A4 for ; Wed, 8 Apr 2020 19:08:19 +0200 (CEST) IronPort-SDR: V2q201aTqH8qEabCjC2cDW5ara4vymI7YanjNrVPHWb7Grlwf3dY11kGOHoZ0ypuWZKnXalnO2 qpLg42kjbqzg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:19 -0700 IronPort-SDR: ttLPceHfPQEI3k/tcvRdn+ZW+QnaOuNDX3SUZZ++t4gP9ASoBCTj5FJ/e9V/tGogq+3EMCR6kR 3UBLcy/a/3ZQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880219" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:17 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson Date: Wed, 8 Apr 2020 17:49:47 +0100 Message-Id: <20200408164956.47864-8-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 07/16] app/test: add telemetry json tests 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 tests for the json utility functions in the telemetry library. Signed-off-by: Bruce Richardson --- app/test/Makefile | 2 + app/test/meson.build | 4 + app/test/test_telemetry_json.c | 136 +++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 app/test/test_telemetry_json.c diff --git a/app/test/Makefile b/app/test/Makefile index 1f080d1626..9697ef6858 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -136,6 +136,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_perf.c SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6_perf.c +SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += test_telemetry_json.c + SRCS-y += test_debug.c SRCS-y += test_errno.c SRCS-y += test_tailq.c diff --git a/app/test/meson.build b/app/test/meson.build index 351d29cb65..f4fe62b707 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -320,6 +320,10 @@ endif if dpdk_conf.has('RTE_LIBRTE_SKELETON_EVENTDEV_PMD') test_deps += 'pmd_skeleton_event' endif +if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') + test_sources += 'test_telemetry_json.c' + fast_tests += [['telemetry_json_autotest', true]] +endif # The following linkages of drivers are required because # they are used via a driver-specific API. diff --git a/app/test/test_telemetry_json.c b/app/test/test_telemetry_json.c new file mode 100644 index 0000000000..9e26807101 --- /dev/null +++ b/app/test/test_telemetry_json.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Intel Corporation + */ + +#include +#include + +#include "test.h" + +static int +test_basic_array(void) +{ + const char *expected = "[\"meaning of life\",42]"; + char buf[1024]; + int used = 0; + + printf("%s: ", __func__); + used = rte_tel_json_empty_array(buf, sizeof(buf), used); + if (used != 2 || strcmp(buf, "[]")) + return -1; + + used = rte_tel_json_add_array_string(buf, sizeof(buf), used, + "meaning of life"); + used = rte_tel_json_add_array_int(buf, sizeof(buf), used, 42); + + printf("buf = '%s', expected = '%s'\n", buf, expected); + if (used != (int)strlen(expected)) + return -1; + return strncmp(expected, buf, sizeof(buf)); +} + +static int +test_basic_obj(void) +{ + const char *expected = "{\"weddings\":4,\"funerals\":1}"; + char buf[1024]; + int used = 0; + + used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, + "weddings", 4); + used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, + "funerals", 1); + + printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected); + if (used != (int)strlen(expected)) + return -1; + return strncmp(expected, buf, sizeof(buf)); +} + +static int +test_overflow_array(void) +{ + static const char * const strs[] = {"Arsenal", "Chelsea", "Liverpool", + "Spurs"}; + const char *expected = "[\"Arsenal\",\"Chelsea\"]"; + char buf[25]; + int i, used = 0; + + for (i = 0; i < (int)RTE_DIM(strs); i++) + used = rte_tel_json_add_array_string(buf, sizeof(buf), used, + strs[i]); + + printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected); + if (buf[used - 1] != ']') + return -1; + if (used != (int)strlen(expected)) + return -1; + return strncmp(expected, buf, sizeof(buf)); +} + +static int +test_overflow_obj(void) +{ + static const char * const names[] = {"Italy", "Wales", "Scotland", + "Ireland", "England", "France"}; + const int vals[RTE_DIM(names)] = {20, 61, 10, 40, 55, 35}; + const char *expected = "{\"Italy\":20,\"Wales\":61}"; + char buf[25]; + int i, used = 0; + + for (i = 0; i < (int)RTE_DIM(names); i++) + used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, + names[i], vals[i]); + + printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected); + if (buf[used - 1] != '}') + return -1; + if (used != (int)strlen(expected)) + return -1; + return strncmp(expected, buf, sizeof(buf)); +} + +static int +test_large_array_element(void) +{ + const char *str = "A really long string to overflow buffer"; + /* buffer should be unmodified so initial value and expected are same */ + const char *expected = "ABC"; + char buf[sizeof(str) - 5] = "ABC"; + int used = 0; + + used = rte_tel_json_add_array_string(buf, sizeof(buf), used, str); + printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected); + + return strlen(buf) != 0; +} + +static int +test_large_obj_element(void) +{ + const char *str = "A really long string to overflow buffer"; + /* buffer should be unmodified so initial value and expected are same */ + const char *expected = "XYZ"; + char buf[sizeof(str) - 5] = "XYZ"; + int used = 0; + + used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, str, 0); + printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected); + + return strlen(buf) != 0; +} + +static int +test_telemetry_json(void) +{ + if (test_basic_array() < 0 || + test_basic_obj() < 0 || + test_overflow_array() < 0 || + test_overflow_obj() < 0 || + test_large_array_element() < 0 || ++ test_large_obj_element() < 0) + return -1; + return 0; +} + +REGISTER_TEST_COMMAND(telemetry_json_autotest, test_telemetry_json); From patchwork Wed Apr 8 16:49:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68020 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 C0653A0597; Wed, 8 Apr 2020 19:10:00 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E8A521C1CE; Wed, 8 Apr 2020 19:08:23 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 0BF7E1C0CD for ; Wed, 8 Apr 2020 19:08:21 +0200 (CEST) IronPort-SDR: zZfFOtoVTWwSY/K33PqWLMjPSHPo+SHnO7GKnooYxREptTAR8SG+/QNXg1g7+y1FUN/lW+4ijb g5qTOIS9rXxQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:21 -0700 IronPort-SDR: zjDt3vI5EtRYz5I1ECwoaTMa5/G2zYvBUHXGT1Us9dKSQvARcvRIxavuhQeeNDxj620CxiVqSn Dg59qTPR/mHw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880227" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:19 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson , Ciara Power Date: Wed, 8 Apr 2020 17:49:48 +0100 Message-Id: <20200408164956.47864-9-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 08/16] 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 and link status for a port to be queried. Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- v2: - Renamed stats to xstats for device specific stats. - Added link status command for ethdev ports. --- lib/librte_ethdev/Makefile | 4 ++ lib/librte_ethdev/meson.build | 4 ++ lib/librte_ethdev/rte_ethdev.c | 106 +++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile index b627e4e23b..4ba9cb8f47 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 3537f22f59..072805cf18 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 0854ef8832..f033d60152 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,112 @@ 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 port_id, used = 0; + + used = rte_tel_json_empty_array(buffer, buf_len, used); + RTE_ETH_FOREACH_DEV(port_id) + used = rte_tel_json_add_array_int(buffer, buf_len, used, + port_id); + return used; +} + +static int +handle_port_xstats(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; + + 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; + } + + used = rte_tel_json_empty_obj(buffer, buf_len, used); + for (i = 0; i < num_xstats; i++) + used = rte_tel_json_add_obj_u64(buffer, buf_len, used, + xstat_names[i].name, eth_xstats[i].value); + + return used; +} + +static int +handle_port_link_status(const char *cmd __rte_unused, + const char *params, + char *buffer, int buf_len) +{ + int ret, port_id; + struct rte_eth_link link; + + 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; + + ret = rte_eth_link_get(port_id, &link); + if (ret < 0) + return -1; + + if (link.link_status) + ret = snprintf(buffer, buf_len, + "{\"status\":\"%s\", \"speed\":%u, \"duplex\":" + "\"%s\"}", link.link_status ? "UP" : "DOWN:", + link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex")); + else + ret = snprintf(buffer, buf_len, "{\"status\":\"DOWN\"}"); + + return ret >= buf_len ? -1 : ret; +} +#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/xstats", handle_port_xstats); + rte_telemetry_register_cmd("/ethdev/link_status", + handle_port_link_status); +#endif } From patchwork Wed Apr 8 16:49:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68021 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 08427A0597; Wed, 8 Apr 2020 19:10:14 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 249421C1D8; Wed, 8 Apr 2020 19:08:26 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 5CBAC1C1D3 for ; Wed, 8 Apr 2020 19:08:24 +0200 (CEST) IronPort-SDR: JBzSQAIl2r+73ReWJJjpDqBfRxIl3SG6agOOSP8cgFg8sGrD+P+hJJBnCRChkEqgbXXvQ4+ba9 vqMLI9tfylAw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:24 -0700 IronPort-SDR: 6aT6j2UUgR5cU8v3Iz3jR/IkH16tXPc2NS8OVcfZfJCC2c82wzrAN/9GGMyKte0ygxkG9SFVJE rySg2qTL+9mg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880239" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:21 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson , Ciara Power Date: Wed, 8 Apr 2020 17:49:49 +0100 Message-Id: <20200408164956.47864-10-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 09/16] 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.v2 {"pid": 63724, "version": "DPDK 20.05.0-rc0", "max_output_len": 16384} --> / {"/": ["/", "/ethdev/link_status", "/ethdev/list", "/ethdev/xstats", \ "/info"]} --> /info {"/info": {"pid": 63724, "version": "DPDK 20.05.0-rc0", \ "max_output_len": 16384}} --> /ethdev/list {"/ethdev/list": [0, 1]} --> /ethdev/link_status,0 {"/ethdev/link_status": {"status": "UP", "speed": 10000, "duplex": \ "full-duplex"}} --> /ethdev/xstats,0 {"/ethdev/xstats": {"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 --- v2: - Renamed new python script to dpdk-telemetry.py. - Fixed script to validate input before sending to Telemetry. --- usertools/dpdk-telemetry.py | 44 +++++++++++++++++++++++++++++++++++++ usertools/meson.build | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100755 usertools/dpdk-telemetry.py diff --git a/usertools/dpdk-telemetry.py b/usertools/dpdk-telemetry.py new file mode 100755 index 0000000000..55fa532136 --- /dev/null +++ b/usertools/dpdk-telemetry.py @@ -0,0 +1,44 @@ +#! /usr/bin/python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020 Intel Corporation + +import socket +import os +import glob +import json + +telemetry_version = "v2" + +def read_socket(buf_len): + reply = fd.recv(buf_len).decode() + try: + print(json.dumps(json.loads(reply))) + return json.loads(reply) + except: + print("Error in reply: ", reply) + raise + +def handle_socket(path): + print("Connecting to " + path) + try: + fd.connect(path) + except OSError: + return + json_reply = read_socket(1024) + output_buf_len = json_reply["max_output_len"] + text = input('--> ').strip() + while (text != "quit"): + if text.startswith('/'): + fd.send(text.encode()) + read_socket(output_buf_len) + text = input('--> ').strip() + + 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.%s' % telemetry_version): + handle_socket(f) +# Path to sockets for processes run as a regular user +for f in glob.glob('/run/user/%d/dpdk/*/dpdk_telemetry.%s' % (os.getuid(), telemetry_version)): + handle_socket(f) diff --git a/usertools/meson.build b/usertools/meson.build index 149e788e3d..64e27238f4 100644 --- a/usertools/meson.build +++ b/usertools/meson.build @@ -1,4 +1,4 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -install_data(['dpdk-devbind.py', 'dpdk-pmdinfo.py'], install_dir: 'bin') +install_data(['dpdk-devbind.py', 'dpdk-pmdinfo.py', 'dpdk-telemetry.py'], install_dir: 'bin') From patchwork Wed Apr 8 16:49:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68022 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 E8269A0597; Wed, 8 Apr 2020 19:10:25 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 5F83E1C1E3; Wed, 8 Apr 2020 19:08:28 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id ABE0C1C1DD for ; Wed, 8 Apr 2020 19:08:26 +0200 (CEST) IronPort-SDR: l2d0gMVHkVy9B3PY677ilncftTGuetpf5bUAWJRIl0i16PypxWyhgba+EFzZ4+zH1DZ1omK0rK zmK+evOwLUhA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:26 -0700 IronPort-SDR: aUaqOtA5vze/Jtn3kaIHAGB+VeLgqd60wG8oktX+BxGRJdRG69ciyMIs28P155cd7gPGstOHF4 A8MYHlJQHE3A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880248" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:24 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power , Bruce Richardson Date: Wed, 8 Apr 2020 17:49:50 +0100 Message-Id: <20200408164956.47864-11-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 10/16] 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 xstats 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.v2 {"pid": 66100, "version": "DPDK 20.05.0-rc0", "max_output_len": 16384} --> / {"/": ["/", "/ethdev/link_status", "/ethdev/list", "/ethdev/xstats", \ "/info", "/rawdev/list", "/rawdev/xstats"]} --> /rawdev/list {"/rawdev/list": [0, 1, 2, 3, 4, 5]} --> /rawdev/xstats,0 {"/rawdev/xstats": {"failed_enqueues": 0, "successful_enqueues": 0, \ "copies_started": 0, "copies_completed": 0}} Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- v2: Renamed stats to xstats for device specific stats. --- lib/librte_rawdev/Makefile | 5 +++ lib/librte_rawdev/meson.build | 5 +++ lib/librte_rawdev/rte_rawdev.c | 81 ++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/lib/librte_rawdev/Makefile b/lib/librte_rawdev/Makefile index 7dd1197dcd..ccf68f60ec 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 a20fbdc048..3a0ea2a293 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 b6f1e1c779..61fe29110c 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,87 @@ 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 = rte_tel_json_empty_array(buffer, buf_len, used); + for (i = 0; i < rawdev_globals.nb_devs; i++) + if (rte_rawdevices[i].attached == RTE_RAWDEV_ATTACHED) + used = rte_tel_json_add_array_int(buffer, buf_len, used, + rte_rawdevices[i].dev_id); + + return used; +} + +static int +handle_dev_xstats(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; + + 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; + } + + used = rte_tel_json_empty_obj(buffer, buf_len, used); + for (i = 0; i < num_xstats; i++) + used = rte_tel_json_add_obj_u64(buffer, buf_len, used, + xstat_names[i].name, rawdev_xstats[i]); + + 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/xstats", handle_dev_xstats); +#endif } From patchwork Wed Apr 8 16:49:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68023 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 B621EA0597; Wed, 8 Apr 2020 19:10:35 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 813891C1D3; Wed, 8 Apr 2020 19:08:31 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 2C1281C1D3 for ; Wed, 8 Apr 2020 19:08:29 +0200 (CEST) IronPort-SDR: AKR2i6lgnJkL6UWGxZdoRnjtLZ0ORPyNS6Kz31aKkNQy+X05p4NGzVjmnHrB49vVRQRW7HpHq+ NBpHRHtBuVsw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:28 -0700 IronPort-SDR: YUWwf3QXkUvb96Mu7CCNBSmIme8kvTg3FyFzeiprgLN5VwYvX+amTTw1e2EmRbcvJnJ3DJ9nZY tudwCBngyOXQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880264" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:26 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power , david.hunt@intel.com, Bruce Richardson Date: Wed, 8 Apr 2020 17:49:51 +0100 Message-Id: <20200408164956.47864-12-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 11/16] 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.v2 {"pid": 6726, "version": "DPDK 20.05.0-rc0", "max_output_len": 16384} --> / {"/": ["/", "/ethdev/link_status", "/ethdev/list", "/ethdev/xstats", \ "/info", "/l3fwd-power/stats", "/rawdev/list", "/rawdev/xstats"]} --> /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. Cc: david.hunt@intel.com Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- examples/l3fwd-power/Makefile | 4 +++ examples/l3fwd-power/main.c | 57 ++++++++++++++++++++++++-------- examples/l3fwd-power/meson.build | 4 +++ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/examples/l3fwd-power/Makefile b/examples/l3fwd-power/Makefile index 729d49639b..531a1d81cb 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 c7fe0ec034..1435458b49 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,43 @@ 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 used = 0; + uint64_t values[3] = {0}; + uint32_t i; + + used = rte_tel_json_empty_obj(buffer, buf_len, used); + get_current_stat_values(values); + for (i = 0; i < NUM_TELSTATS; i++) + used = rte_tel_json_add_obj_u64(buffer, buf_len, used, + telstats_strings[i].name, values[i]); + + return used; +} +#endif static void telemetry_setup_timer(void) { @@ -2203,8 +2229,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 +2528,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 +2541,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 d5a3d4bb2f..e7c6be6477 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 Wed Apr 8 16:49:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68024 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 8D228A0597; Wed, 8 Apr 2020 19:10:46 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A306F1C1EF; Wed, 8 Apr 2020 19:08:34 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 0E9AD1C1EA for ; Wed, 8 Apr 2020 19:08:31 +0200 (CEST) IronPort-SDR: /72W8e+If5bD3XNJr2CfIQ6yJ5IKdbjPezHS/WfCx+3Vjgi72Fh9Bmk5vaSLLTKGG5+RkuWTH2 2b2kUxTzTL7A== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:31 -0700 IronPort-SDR: ijsVj+vq/Qeea3ufzI0INL6bOKAR3rAByis86CusCSvEeMhQkHRDxHJMnPJqR+mG3YUkV+sfvd 9rDnfiSVojqA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880293" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:28 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power Date: Wed, 8 Apr 2020 17:49:52 +0100 Message-Id: <20200408164956.47864-13-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 12/16] 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 | 63 +++++ .../rte_telemetry_version.map | 2 + lib/librte_telemetry/telemetry.c | 32 +++ lib/librte_telemetry/telemetry_legacy.c | 226 ++++++++++++++++++ 10 files changed, 442 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 5a11b6198b..fff5fe5a84 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -19,7 +19,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) 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 += -ljansson CFLAGS += -I$(RTE_SDK)/lib/librte_telemetry/ diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build index d116857e2d..1a7cbf29cc 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 31d505551b..49de9d74b5 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 9012156c1b..eea8023649 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 cc0cdeb5f6..752f4064d4 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -3,8 +3,8 @@ includes = [global_inc] -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', 'rte_telemetry_json.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 8b3df04292..7ecd1814ed 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -135,4 +135,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 0000000000..17053b9ff1 --- /dev/null +++ b/lib/librte_telemetry/rte_telemetry_legacy.h @@ -0,0 +1,63 @@ +/* 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" + +/** + * @internal + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + + * @file + * RTE Telemetry Legacy + * + ***/ + +/** + * @internal + * Value representing if data is required for the command + */ +enum rte_telemetry_legacy_data_req { + DATA_NOT_REQ = 0, + DATA_REQ +}; + +/** + * @internal + * Counter for the number of registered legacy callbacks + */ +extern int num_legacy_callbacks; + +/** + * @internal + * Used for handling data received over the legacy telemetry socket. + * + * @return + * Void. + */ +void *legacy_client_handler(void *sock_id); + +/** + * @internal + * + * 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 831bbd59ad..2db0a5a443 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 2878c1dbd9..f77e541ea2 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -16,6 +16,7 @@ #include #include "rte_telemetry.h" +#include "rte_telemetry_legacy.h" #define MAX_CMD_LEN 56 #define MAX_OUTPUT_LEN (1024 * 16) @@ -42,6 +43,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]; @@ -201,6 +203,8 @@ unlink_sockets(void) { if (v2_socket.path[0]) unlink(v2_socket.path); + if (v1_socket.path[0]) + unlink(v1_socket.path); } static int @@ -240,6 +244,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 0000000000..e7c01525b4 --- /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 Wed Apr 8 16:49:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68025 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 E579AA0597; Wed, 8 Apr 2020 19:11:01 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 48C2C1C1FB; Wed, 8 Apr 2020 19:08:38 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 136811C1F2 for ; Wed, 8 Apr 2020 19:08:34 +0200 (CEST) IronPort-SDR: hpm62e0zqL666f82cxbtbwwCSROy+0z00Q9tpZZBbCX4uuZadi/3XXe16IDGqUfxQiqe9xS3tJ Ld9mFJHCqx8g== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:34 -0700 IronPort-SDR: CBOjrDh/LOuoOG3BNmfshdvVl94fKOkg7FRU8vFwFoz3qfdcl53VQ3DuYj2KwKuD9AVoEuGQ+0 RSEbhl97mTxw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880297" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:31 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power Date: Wed, 8 Apr 2020 17:49:53 +0100 Message-Id: <20200408164956.47864-14-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v2 13/16] 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 | 55 +- 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, 23 insertions(+), 2603 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 49de9d74b5..5ef6f765a2 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 eea8023649..2cded733ba 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -15,16 +15,11 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(ARCH_DIR)/include 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 752f4064d4..1139e07136 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -3,17 +3,8 @@ includes = [global_inc] -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', 'rte_telemetry_json.h') +sources = files('telemetry.c', 'telemetry_legacy.c') +headers = files('rte_telemetry.h', 'rte_telemetry_json.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 45b6d9d948..0000000000 --- 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 7ecd1814ed..cbabf3cd85 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -22,6 +22,7 @@ * The telemetry library provides a method to retrieve statistics from * DPDK by sending a request message over a socket. DPDK will send * a JSON encoded response containing telemetry data. + * ***/ /** @@ -57,56 +58,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); - /** * Used when registering a command and callback function with telemetry. * @@ -126,7 +77,7 @@ __rte_experimental int rte_telemetry_register_cmd(const char *cmd, telemetry_cb fn); /** - * Initialize new version of Telemetry. + * Initialize Telemetry. * * @return * 0 on success. @@ -134,6 +85,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 2ef72b1ec3..0000000000 --- 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 7dc84c2cf3..0000000000 --- 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 28b808d8ad..0000000000 --- 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 6164ef83ec..0000000000 --- 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 db9167c5d5..0000000000 --- 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 2db0a5a443..d7ed1fe115 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 f77e541ea2..dd2050f57a 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "rte_telemetry.h" #include "rte_telemetry_legacy.h" @@ -244,7 +245,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; @@ -299,12 +300,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 Wed Apr 8 16:49:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68026 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 8E75DA0597; Wed, 8 Apr 2020 19:11:19 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 04FA61C20E; Wed, 8 Apr 2020 19:08:40 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 7EB0E1C127 for ; Wed, 8 Apr 2020 19:08:37 +0200 (CEST) IronPort-SDR: BCbiGbB4g7B1MxZewbW/zvrYzT1s93NVcj+C3rQaBKugLQz2ukBk3TCnZy6+hlD6MM5/rg9dLY Oc3rN5+Lyw5g== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:37 -0700 IronPort-SDR: BqBdBcoEgfEaV7qar30qDcc58ku7wgx/pviue5XIfnxCN2VmNE6sjh46nrn7O6lntLAGoHxoOq PPBmUPwa89Fw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880301" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:34 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power , Bruce Richardson Date: Wed, 8 Apr 2020 17:49:54 +0100 Message-Id: <20200408164956.47864-15-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 14/16] 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 V2 is now configured to build by default, and the legacy support is built when the telemetry config flag is set. Telemetry now 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 and telemetry config flag, as before). Signed-off-by: Ciara Power Signed-off-by: Bruce Richardson --- v2: Telemetry config flag now represents the legacy support being built, and is disabled by default, as in the existing telemetry. --- config/common_base | 2 +- examples/l3fwd-power/Makefile | 6 +----- examples/l3fwd-power/main.c | 8 ++------ examples/l3fwd-power/meson.build | 6 +----- 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/Makefile | 1 + lib/librte_eal/freebsd/eal.c | 9 ++++++++ lib/librte_eal/freebsd/meson.build | 2 +- lib/librte_eal/linux/Makefile | 1 + lib/librte_eal/linux/eal.c | 9 ++++++++ lib/librte_eal/linux/meson.build | 2 +- lib/librte_eal/meson.build | 5 ++++- lib/librte_ethdev/Makefile | 6 +----- lib/librte_ethdev/meson.build | 6 +----- lib/librte_ethdev/rte_ethdev.c | 6 ------ lib/librte_rawdev/Makefile | 6 +----- lib/librte_rawdev/meson.build | 6 ++---- lib/librte_rawdev/rte_rawdev.c | 6 ------ lib/librte_telemetry/Makefile | 9 ++++---- 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 | 5 ++++- 27 files changed, 67 insertions(+), 82 deletions(-) diff --git a/config/common_base b/config/common_base index c31175f9d6..d3cd7652e5 100644 --- a/config/common_base +++ b/config/common_base @@ -916,7 +916,7 @@ CONFIG_RTE_LIBRTE_BITRATE=y CONFIG_RTE_LIBRTE_LATENCY_STATS=y # -# Compile librte_telemetry +# Compile librte_telemetry legacy support # CONFIG_RTE_LIBRTE_TELEMETRY=n diff --git a/examples/l3fwd-power/Makefile b/examples/l3fwd-power/Makefile index 531a1d81cb..852877c1f2 100644 --- a/examples/l3fwd-power/Makefile +++ b/examples/l3fwd-power/Makefile @@ -60,7 +60,7 @@ else CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -LDLIBS += -lm +LDLIBS += -lm -lrte_telemetry # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 @@ -68,10 +68,6 @@ 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 1435458b49..64d76b4768 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -46,9 +46,7 @@ #include #include #include -#ifdef RTE_LIBRTE_TELEMETRY #include -#endif #include "perf_core.h" #include "main.h" @@ -2123,7 +2121,7 @@ update_telemetry(__attribute__((unused)) struct rte_timer *tim, 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, @@ -2141,7 +2139,7 @@ handle_app_stats(const char *cmd __rte_unused, return used; } -#endif + static void telemetry_setup_timer(void) { @@ -2541,10 +2539,8 @@ 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 e7c6be6477..4cd694710d 100644 --- a/examples/l3fwd-power/meson.build +++ b/examples/l3fwd-power/meson.build @@ -12,11 +12,7 @@ if not dpdk_conf.has('RTE_LIBRTE_POWER') endif allow_experimental_apis = true -deps += ['power', 'timer', 'lpm', 'hash', 'metrics'] +deps += ['power', 'timer', 'lpm', 'hash', 'metrics', 'telemetry'] sources = files( 'main.c', 'perf_core.c' ) - -if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') - deps += ['telemetry'] -endif diff --git a/lib/Makefile b/lib/Makefile index 31b943817c..5f32c2e5cb 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-y += 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 525e51e7de..ca10e0524d 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 a42f349232..c650bc0814 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 9855429e58..225ad4bb59 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/Makefile b/lib/librte_eal/freebsd/Makefile index e5d4d8ff26..7ff6346e47 100644 --- a/lib/librte_eal/freebsd/Makefile +++ b/lib/librte_eal/freebsd/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.c b/lib/librte_eal/freebsd/eal.c index 6ae37e7e69..54acafc312 100644 --- a/lib/librte_eal/freebsd/eal.c +++ b/lib/librte_eal/freebsd/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/meson.build b/lib/librte_eal/freebsd/meson.build index 22fc4e8074..e10fd8a16d 100644 --- a/lib/librte_eal/freebsd/meson.build +++ b/lib/librte_eal/freebsd/meson.build @@ -18,4 +18,4 @@ sources += files( 'eal_timer.c', ) -deps += ['kvargs'] +deps += ['kvargs', 'telemetry'] diff --git a/lib/librte_eal/linux/Makefile b/lib/librte_eal/linux/Makefile index e5f44959c6..3a2adb5395 100644 --- a/lib/librte_eal/linux/Makefile +++ b/lib/librte_eal/linux/Makefile @@ -20,6 +20,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.c b/lib/librte_eal/linux/eal.c index 9530ee55f8..8eeffe9aa3 100644 --- a/lib/librte_eal/linux/eal.c +++ b/lib/librte_eal/linux/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/meson.build b/lib/librte_eal/linux/meson.build index ca4f4e9785..7742aa4759 100644 --- a/lib/librte_eal/linux/meson.build +++ b/lib/librte_eal/linux/meson.build @@ -21,7 +21,7 @@ sources += files( 'eal_vfio_mp_sync.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 9d219a0e6e..098088d6cd 100644 --- a/lib/librte_eal/meson.build +++ b/lib/librte_eal/meson.build @@ -12,7 +12,10 @@ subdir(exec_env) subdir(arch_subdir) allow_experimental_apis = true -deps += 'kvargs' +deps += ['kvargs'] +if not is_windows + deps += ['telemetry'] +endif if dpdk_conf.has('RTE_USE_LIBBSD') ext_deps += libbsd endif diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile index 4ba9cb8f47..d059df994b 100644 --- a/lib/librte_ethdev/Makefile +++ b/lib/librte_ethdev/Makefile @@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf -lrte_kvargs -lrte_meter +LDLIBS += -lrte_mbuf -lrte_kvargs -lrte_meter -lrte_telemetry EXPORT_MAP := rte_ethdev_version.map @@ -24,10 +24,6 @@ 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 072805cf18..07f959baa8 100644 --- a/lib/librte_ethdev/meson.build +++ b/lib/librte_ethdev/meson.build @@ -25,8 +25,4 @@ headers = files('rte_ethdev.h', 'rte_tm.h', 'rte_tm_driver.h') -deps += ['net', 'kvargs', 'meter'] - -if dpdk_conf.has('RTE_LIBRTE_TELEMETRY') - deps += ['telemetry'] -endif +deps += ['net', 'kvargs', 'meter', 'telemetry'] diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index f033d60152..180847f84b 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -38,9 +38,7 @@ #include #include #include -#ifdef RTE_LIBRTE_TELEMETRY #include -#endif #include "rte_ethdev.h" #include "rte_ethdev_driver.h" @@ -5192,7 +5190,6 @@ 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, @@ -5287,17 +5284,14 @@ handle_port_link_status(const char *cmd __rte_unused, return ret >= buf_len ? -1 : ret; } -#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/xstats", handle_port_xstats); rte_telemetry_register_cmd("/ethdev/link_status", handle_port_link_status); -#endif } diff --git a/lib/librte_rawdev/Makefile b/lib/librte_rawdev/Makefile index ccf68f60ec..8bc02908f3 100644 --- a/lib/librte_rawdev/Makefile +++ b/lib/librte_rawdev/Makefile @@ -9,12 +9,8 @@ LIB = librte_rawdev.a # build flags CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -LDLIBS += -lrte_eal - -ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) CFLAGS += -DALLOW_EXPERIMENTAL_API -LDLIBS += -lrte_telemetry -endif +LDLIBS += -lrte_eal -lrte_telemetry # library source files SRCS-y += rte_rawdev.c diff --git a/lib/librte_rawdev/meson.build b/lib/librte_rawdev/meson.build index 3a0ea2a293..eef232d845 100644 --- a/lib/librte_rawdev/meson.build +++ b/lib/librte_rawdev/meson.build @@ -4,7 +4,5 @@ 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 +allow_experimental_apis = true +deps += ['telemetry'] diff --git a/lib/librte_rawdev/rte_rawdev.c b/lib/librte_rawdev/rte_rawdev.c index 61fe29110c..df2311701d 100644 --- a/lib/librte_rawdev/rte_rawdev.c +++ b/lib/librte_rawdev/rte_rawdev.c @@ -29,9 +29,7 @@ #include #include #include -#ifdef RTE_LIBRTE_TELEMETRY #include -#endif #include "rte_rawdev.h" #include "rte_rawdev_pmd.h" @@ -547,7 +545,6 @@ 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, @@ -619,15 +616,12 @@ handle_dev_xstats(const char *cmd __rte_unused, 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/xstats", handle_dev_xstats); -#endif } diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile index 2cded733ba..6d49f544eb 100644 --- a/lib/librte_telemetry/Makefile +++ b/lib/librte_telemetry/Makefile @@ -14,17 +14,16 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(ARCH_DIR)/include CFLAGS += -pthread -LDLIBS += -lrte_eal LDLIBS += -lpthread EXPORT_MAP := rte_telemetry_version.map # library source files -SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c -SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry_legacy.c +SRCS-y += telemetry.c +SRCS-y += telemetry_legacy.c # export include files -SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h -SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include += rte_telemetry_json.h +SYMLINK-y-include := rte_telemetry.h +SYMLINK-y-include += rte_telemetry_json.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build index 1139e07136..6856ef7fc7 100644 --- a/lib/librte_telemetry/meson.build +++ b/lib/librte_telemetry/meson.build @@ -7,4 +7,3 @@ sources = files('telemetry.c', 'telemetry_legacy.c') headers = files('rte_telemetry.h', 'rte_telemetry_json.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 cbabf3cd85..ddb3d70de7 100644 --- a/lib/librte_telemetry/rte_telemetry.h +++ b/lib/librte_telemetry/rte_telemetry.h @@ -85,6 +85,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 dd2050f57a..da6434c9cd 100644 --- a/lib/librte_telemetry/telemetry.c +++ b/lib/librte_telemetry/telemetry.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "rte_telemetry.h" #include "rte_telemetry_legacy.h" @@ -300,26 +299,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 9f3f7dd432..be0be3f929 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 fdaf3ec2c0..76e8bc95f9 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -52,6 +52,9 @@ _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 +ifeq ($(CONFIG_RTE_LIBRTE_TELEMETRY),y) +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -ljansson +endif _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 +77,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-y += -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 +94,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 Wed Apr 8 16:49:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68027 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 870B3A0597; Wed, 8 Apr 2020 19:11:31 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id AC6B91C1F5; Wed, 8 Apr 2020 19:08:42 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 4CB5B1C214 for ; Wed, 8 Apr 2020 19:08:40 +0200 (CEST) IronPort-SDR: 3Cr8LViFVJW3FiRwpacWCOIEMFQuKJqq/WTFiPRcviFK1mBxwhCJiT6vDVBgWw/St+LXh9iSaN cLel77ieCyiA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:39 -0700 IronPort-SDR: SAmGydFs08qDYPEy5ft+pqEKkTflSP9IYHG7q7f6OrgdjLd2a+IRYH46BMt+TvRkdqEbbdibWj 60ix5MVl+O2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880306" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:37 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Bruce Richardson , Ciara Power Date: Wed, 8 Apr 2020 17:49:55 +0100 Message-Id: <20200408164956.47864-16-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 15/16] 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.v2 {"pid": 926, "version": "DPDK 20.05.0-rc0", "max_output_len": 16384} --> / {"/": ["/", "/eal/app_params", "/eal/params", "/ethdev/link_status", \ "/ethdev/list", "/ethdev/xstats", "/info", "/rawdev/list", \ "/rawdev/xstats"]} --> /eal/app_params {"/eal/app_params": ["-i"]} --> /eal/params {"/eal/params": ["./app/dpdk-testpmd"]} Signed-off-by: Bruce Richardson Signed-off-by: Ciara Power --- v2: - Removed /eal/version command as /info replaces it. - Compile telemetry callbacks and include headers if not in Windows execution environment. --- lib/librte_eal/common/eal_common_options.c | 70 ++++++++++++++++++++++ lib/librte_eal/common/eal_options.h | 3 + lib/librte_eal/freebsd/eal.c | 3 + lib/librte_eal/linux/eal.c | 3 + 4 files changed, 79 insertions(+) diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c index ca10e0524d..4e2bd90147 100644 --- a/lib/librte_eal/common/eal_common_options.c +++ b/lib/librte_eal/common/eal_common_options.c @@ -29,6 +29,9 @@ #include #include #include +#ifndef RTE_EXEC_ENV_WINDOWS +#include +#endif #include "eal_internal_cfg.h" #include "eal_options.h" @@ -132,6 +135,73 @@ static int master_lcore_parsed; static int mem_parsed; static int core_parsed; +#ifndef RTE_EXEC_ENV_WINDOWS +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 + args = eal_app_args; + + if (args == NULL || args[0] == NULL) + return rte_tel_json_empty_array(buffer, buf_len, used); + + for ( ; args[i] != NULL; i++) + used = rte_tel_json_add_array_string(buffer, buf_len, used, + args[i]); + 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; +} +#endif + 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 225ad4bb59..5373e9f5e3 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.c b/lib/librte_eal/freebsd/eal.c index 54acafc312..d5017e86b2 100644 --- a/lib/librte_eal/freebsd/eal.c +++ b/lib/librte_eal/freebsd/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); diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c index 8eeffe9aa3..b80401df9a 100644 --- a/lib/librte_eal/linux/eal.c +++ b/lib/librte_eal/linux/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; From patchwork Wed Apr 8 16:49:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Power, Ciara" X-Patchwork-Id: 68028 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 79702A0597; Wed, 8 Apr 2020 19:11:45 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7D35E1C223; Wed, 8 Apr 2020 19:08:44 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 176AC1C219 for ; Wed, 8 Apr 2020 19:08:41 +0200 (CEST) IronPort-SDR: jN3vueO09Q3HF8Ww1wo/5yMDYfo+9jV48dsWc5ae21uRsQq2nusWHHy94mczY4pbL2uTPM9lNx /HooUrJUeWtA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Apr 2020 10:08:41 -0700 IronPort-SDR: IPAGA7DUoi31/1V8bg0ikqNEFpsq7jm21+ximijltbwG8/AsbUPC1hcFNtR0numM7cUlb9foZu 0KFPYrXfd2UQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880320" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.222.53]) by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:39 -0700 From: Ciara Power To: dev@dpdk.org, kevin.laatz@intel.com Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com, keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net, Ciara Power Date: Wed, 8 Apr 2020 17:49:56 +0100 Message-Id: <20200408164956.47864-17-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com> References: <20200319171907.60891-1-ciara.power@intel.com> <20200408164956.47864-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 16/16] doc: update telemetry documentation 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 existing documentation for Telemetry is updated, and further documentation is added. Signed-off-by: Ciara Power --- doc/api/doxy-api-index.md | 1 + doc/guides/howto/telemetry.rst | 108 ++++++++++------------ doc/guides/linux_gsg/eal_args.include.rst | 8 ++ doc/guides/linux_gsg/sys_reqs.rst | 2 - doc/guides/prog_guide/index.rst | 1 + doc/guides/prog_guide/telemetry_lib.rst | 62 +++++++++++++ doc/guides/rel_notes/release_20_05.rst | 15 +++ 7 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 doc/guides/prog_guide/telemetry_lib.rst diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index dff496be09..0bbdbe8706 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -170,6 +170,7 @@ The public API headers are grouped by topics: - **debug**: [jobstats] (@ref rte_jobstats.h), [telemetry] (@ref rte_telemetry.h), + [telemetry-json] (@ref rte_telemetry_json.h), [pdump] (@ref rte_pdump.h), [hexdump] (@ref rte_hexdump.h), [debug] (@ref rte_debug.h), diff --git a/doc/guides/howto/telemetry.rst b/doc/guides/howto/telemetry.rst index cacc082161..4f39a4df56 100644 --- a/doc/guides/howto/telemetry.rst +++ b/doc/guides/howto/telemetry.rst @@ -1,86 +1,80 @@ .. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2018 Intel Corporation. + Copyright(c) 2020 Intel Corporation. -DPDK Telemetry API User Guide + +DPDK Telemetry User Guide ============================== -This document describes how the Data Plane Development Kit(DPDK) Telemetry API -is used for querying port statistics from incoming traffic. +The Telemetry library provides users with the ability to query DPDK for +telemetry information, currently including information such as ethdev stats, +ethdev port list, and eal parameters. + +.. Note:: + + This library is experimental and the output format may change in the future. + -Introduction ------------- +Telemetry Interface +------------------- -The ``librte_telemetry`` provides the functionality so that users may query -metrics from incoming port traffic and global stats(application stats). -The application which initializes packet forwarding will act as the server, -sending metrics to the requesting application which acts as the client. +The :ref:`librte_telemetry ` opens a socket with path +*/dpdk_telemetry.*. The version represents the +telemetry version, the latest is v2. For example, a client would connect to a +socket with path */var/run/dpdk/\*/dpdk_telemetry.v2* (when the primary process +is run by a root user). -In DPDK, applications are used to initialize the ``telemetry``. To view incoming -traffic on featured ports, the application should be run first (ie. after ports -are configured). Once the application is running, the service assurance agent -(for example the collectd plugin) should be run to begin querying the API. +Telemetry Initialization +------------------------ -A client connects their Service Assurance application to the DPDK application -via a UNIX socket. Once a connection is established, a client can send JSON -messages to the DPDK application requesting metrics via another UNIX client. -This request is then handled and parsed if valid. The response is then -formatted in JSON and sent back to the requesting client. +The library is enabled by default, however an EAL flag to enable the library +exists, to provide backward compatibility for the previous telemetry library +interface. -Pre-requisites -~~~~~~~~~~~~~~ +.. code-block:: console -* Python >= 2.5 + --telemetry -* Jansson library for JSON serialization +A flag exists to disable Telemetry also. -Test Environment ----------------- +.. code-block:: console -``telemetry`` offers a range of selftests that a client can run within -the DPDK application. + --no-telemetry -Selftests are disabled by default. They can be enabled by setting the 'selftest' -variable to 1 in rte_telemetry_initial_accept(). -Note: this 'hardcoded' value is temporary. +Running Telemetry +----------------- -Configuration -------------- +The following steps show how to run an application with telemetry support, +and query information using the telemetry client python script. -Enable the telemetry API by modifying the following config option before -building DPDK:: +#. Launch testpmd as the primary application with telemetry. - CONFIG_RTE_LIBRTE_TELEMETRY=y + .. code-block:: console -Note: Meson will pick this up automatically if ``libjansson`` is available. + ./app/dpdk-testpmd -Running the Application ------------------------ +#. Launch the telemetry client script. -The following steps demonstrate how to run the ``telemetry`` API to query all -statistics on all active ports, using the ``telemetry_client`` python script -to query. -Note: This guide assumes packet generation is applicable and the user is -testing with testpmd as a DPDK primary application to forward packets, although -any DPDK application is applicable. + .. code-block:: console -#. Launch testpmd as the primary application with ``telemetry``.:: + python usertools/dpdk-telemetry.py - ./app/testpmd --telemetry +#. When connected, the script displays the following, waiting for user input. -#. Launch the ``telemetry`` python script with a client filepath.:: + .. code-block:: console - python usertools/telemetry_client.py /var/run/some_client + Connecting to /var/run/dpdk/rte/dpdk_telemetry.v2 + {"pid": 60285, "version": "DPDK 20.05.0-rc0", "max_output_len": 16384} + --> - The client filepath is going to be used to setup our UNIX connection with the - DPDK primary application, in this case ``testpmd`` - This will initialize a menu where a client can proceed to recursively query - statistics, request statistics once or unregister the file_path, thus exiting - the menu. +#. The user can now input commands to send across the socket, and receive the + response. -#. Send traffic to any or all available ports from a traffic generator. - Select a query option(recursive or singular polling or global stats). - The metrics will then be displayed on the client terminal in JSON format. + .. code-block:: console -#. Once finished, unregister the client using the menu command. + --> / + {"/": ["/", "/eal/app_params", "/eal/params", "/ethdev/list", + "/ethdev/link_status", "/ethdev/xstats", "/info"]} + --> /ethdev/list + {"/ethdev/list": [0, 1]} diff --git a/doc/guides/linux_gsg/eal_args.include.rst b/doc/guides/linux_gsg/eal_args.include.rst index ed8b0e35b0..a6938c160d 100644 --- a/doc/guides/linux_gsg/eal_args.include.rst +++ b/doc/guides/linux_gsg/eal_args.include.rst @@ -150,3 +150,11 @@ Other options * ``mbuf-pool-ops-name``: Pool ops name for mbuf to use. + +* ``--telemetry``: + + Enable telemetry (enabled by default). + +* ``--no-telemetry``: + + Disable telemetry. diff --git a/doc/guides/linux_gsg/sys_reqs.rst b/doc/guides/linux_gsg/sys_reqs.rst index 7c47ec04ce..a124656bcb 100644 --- a/doc/guides/linux_gsg/sys_reqs.rst +++ b/doc/guides/linux_gsg/sys_reqs.rst @@ -95,8 +95,6 @@ For libraries the additional dependencies include: * libarchive: for some unit tests using tar to get their resources. -* jansson: to compile and use the telemetry library. - * libelf: to compile and use the bpf library. For poll-mode drivers, the additional dependencies for each driver can be diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index fb250abf51..7e7b06ce5f 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -57,6 +57,7 @@ Programmer's Guide metrics_lib bpf_lib ipsec_lib + telemetry_lib source_org dev_kit_build_system dev_kit_root_make_help diff --git a/doc/guides/prog_guide/telemetry_lib.rst b/doc/guides/prog_guide/telemetry_lib.rst new file mode 100644 index 0000000000..cb4f058473 --- /dev/null +++ b/doc/guides/prog_guide/telemetry_lib.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2020 Intel Corporation. + +.. _telemetry_library: + + +Telemetry Library +================= + +The Telemetry library provides an interface to retrieve information from a +variety of DPDK libraries. The library provides this information via socket +connection, taking requests from a connected client and replying with the JSON +response containing the requested telemetry information. + +Telemetry is enabled to run by default when running a DPDK application, and the +telemetry information from enabled libraries is made available. Libraries are +responsible for registering their own commands, and providing the callback +function that will format the library specific stats into the correct JSON +response format, when requested. + + +Registering Commands +-------------------- + +Libraries and applications must register commands to make their information +available via the Telemetry library. This involves providing a string command +in the required format ("/library/command"), and the callback function that +will handle formatting the information when required. An example showing ethdev +commands being registered is shown below: + +.. code-block:: c + + rte_telemetry_register_cmd("/ethdev/list", handle_port_list); + rte_telemetry_register_cmd("/ethdev/xstats", handle_port_xstats); + + +Formatting JSON response +------------------------ + +The callback function provided by the library must format its telemetry +information in a valid JSON format. The Telemetry library provides a JSON +utilities API to build up the response. In the event of the output buffer being +too small to hold the telemetry information in full, the API functions maintain +correct JSON formatting regardless. For example, the ethdev library provides a +list of available ethdev ports in a JSON response, constructed using the +following functions to build up the list: + +.. code-block:: c + + used = rte_tel_json_empty_array(buffer, buf_len, used); + RTE_ETH_FOREACH_DEV(port_id) + used = rte_tel_json_add_array_int(buffer, buf_len, used, port_id); + +The resulting response that is returned to the client shows the list of ports +constructed above by the handler function in ethdev: + +.. code-block:: console + + {"/ethdev/list": [0, 1]} + +For more information on the range of JSON functions available in the API, +please refer to the docs. diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501e..083e706224 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,21 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Telemetry Library.** + + The updated Telemetry library has many improvements on the original version + to make it more accessible and scalable: + + * It enables DPDK libraries and applications provide their own specific + telemetry information, rather than being limited to what could be reported + through the metrics library. + + * It is no longer dependent on the external Jansson library, which allows + Telemetry be enabled by default. + + * The socket handling has been simplified making it easier for clients to + connect and retrieve information. + Removed Items -------------