diff --git a/lib/Makefile b/lib/Makefile index 9d24609d38..559fb03dc9 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..aa4d8546f3 100644 --- a/lib/librte_metrics/Makefile +++ b/lib/librte_metrics/Makefile @@ -14,6 +14,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..a39bc7a2a6 100644 --- a/lib/librte_metrics/meson.build +++ b/lib/librte_metrics/meson.build @@ -3,3 +3,11 @@ 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 db619c5e3f..3f1a448c5e 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