1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
11 #include <rte_metrics.h>
12 #include <rte_common.h>
13 #include <rte_ethdev.h>
15 #include "rte_telemetry_internal.h"
16 #include "rte_telemetry_parser.h"
18 typedef int (*command_func)(struct telemetry_impl *, int, json_t *);
20 struct rte_telemetry_command {
26 rte_telemetry_command_clients(struct telemetry_impl *telemetry, int action,
31 if (telemetry == NULL) {
32 TELEMETRY_LOG_ERR("Invalid telemetry argument");
36 if (action != ACTION_DELETE) {
37 TELEMETRY_LOG_WARN("Invalid action for this command");
41 if (!json_is_object(data)) {
42 TELEMETRY_LOG_WARN("Invalid data provided for this command");
46 json_t *client_path = json_object_get(data, "client_path");
47 if (!json_is_string(client_path)) {
48 TELEMETRY_LOG_WARN("Command value is not a string");
52 ret = rte_telemetry_unregister_client(telemetry,
53 json_string_value(client_path));
55 TELEMETRY_LOG_ERR("Could not unregister client");
62 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
64 TELEMETRY_LOG_ERR("Could not send error");
69 rte_telemetry_command_ports(struct telemetry_impl *telemetry, int action,
74 if (telemetry == NULL) {
75 TELEMETRY_LOG_ERR("Invalid telemetry argument");
79 if (!json_is_null(data)) {
80 TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'ports' command");
84 if (action != ACTION_GET) {
85 TELEMETRY_LOG_WARN("Invalid action for this command");
92 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
94 TELEMETRY_LOG_ERR("Could not send error");
99 rte_telemetry_command_ports_details(struct telemetry_impl *telemetry,
100 int action, json_t *data)
102 json_t *value, *port_ids_json = json_object_get(data, "ports");
103 uint64_t num_port_ids = json_array_size(port_ids_json);
104 int ret, port_ids[num_port_ids];
105 RTE_SET_USED(port_ids);
108 if (telemetry == NULL) {
109 TELEMETRY_LOG_ERR("Invalid telemetry argument");
113 if (action != ACTION_GET) {
114 TELEMETRY_LOG_WARN("Invalid action for this command");
118 if (!json_is_object(data)) {
119 TELEMETRY_LOG_WARN("Invalid data provided for this command");
123 if (!json_is_array(port_ids_json)) {
124 TELEMETRY_LOG_WARN("Invalid Port ID array");
128 json_array_foreach(port_ids_json, index, value) {
129 if (!json_is_integer(value)) {
130 TELEMETRY_LOG_WARN("Port ID given is invalid");
133 port_ids[index] = json_integer_value(value);
139 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
141 TELEMETRY_LOG_ERR("Could not send error");
146 rte_telemetry_command_port_stats(struct telemetry_impl *telemetry, int action,
151 if (telemetry == NULL) {
152 TELEMETRY_LOG_ERR("Invalid telemetry argument");
156 if (!json_is_null(data)) {
157 TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'port_stats' command");
161 if (action != ACTION_GET) {
162 TELEMETRY_LOG_WARN("Invalid action for this command");
169 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
171 TELEMETRY_LOG_ERR("Could not send error");
176 rte_telemetry_stat_names_to_ids(struct telemetry_impl *telemetry,
177 const char * const *stat_names, uint32_t *stat_ids,
178 uint64_t num_stat_names)
180 struct rte_metric_name *names;
181 int ret, num_metrics;
184 if (stat_names == NULL) {
185 TELEMETRY_LOG_WARN("Invalid stat_names argument");
189 if (num_stat_names <= 0) {
190 TELEMETRY_LOG_WARN("Invalid num_stat_names argument");
194 num_metrics = rte_metrics_get_names(NULL, 0);
195 if (num_metrics < 0) {
196 TELEMETRY_LOG_ERR("Cannot get metrics count");
198 } else if (num_metrics == 0) {
199 TELEMETRY_LOG_WARN("No metrics have been registered");
203 names = malloc(sizeof(struct rte_metric_name) * num_metrics);
205 TELEMETRY_LOG_ERR("Cannot allocate memory for names");
207 ret = rte_telemetry_send_error_response(telemetry, -ENOMEM);
209 TELEMETRY_LOG_ERR("Could not send error");
214 ret = rte_metrics_get_names(names, num_metrics);
215 if (ret < 0 || ret > num_metrics) {
216 TELEMETRY_LOG_ERR("Cannot get metrics names");
222 for (i = 0; i < (uint32_t)num_stat_names; i++) {
224 for (j = 0; j < (uint32_t)num_metrics; j++) {
225 if (strcmp(stat_names[i], names[j].name) == 0) {
233 if (k != num_stat_names) {
234 TELEMETRY_LOG_WARN("Invalid stat names provided");
243 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
245 TELEMETRY_LOG_ERR("Could not send error");
249 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
251 TELEMETRY_LOG_ERR("Could not send error");
256 rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry,
257 int action, json_t *data)
259 int ret, num_metrics, i, p;
260 struct rte_metric_value *values;
261 uint64_t num_port_ids = 0;
262 struct telemetry_encode_param ep;
264 memset(&ep, 0, sizeof(ep));
265 if (telemetry == NULL) {
266 TELEMETRY_LOG_ERR("Invalid telemetry argument");
270 if (action != ACTION_GET) {
271 TELEMETRY_LOG_WARN("Invalid action for this command");
272 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
274 TELEMETRY_LOG_ERR("Could not send error");
278 if (json_is_object(data)) {
279 TELEMETRY_LOG_WARN("Invalid data provided for this command");
280 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
282 TELEMETRY_LOG_ERR("Could not send error");
286 num_metrics = rte_metrics_get_values(0, NULL, 0);
287 if (num_metrics < 0) {
288 TELEMETRY_LOG_ERR("Cannot get metrics count");
290 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
292 TELEMETRY_LOG_ERR("Could not send error");
295 } else if (num_metrics == 0) {
296 TELEMETRY_LOG_ERR("No metrics to display (none have been registered)");
298 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
300 TELEMETRY_LOG_ERR("Could not send error");
305 values = malloc(sizeof(struct rte_metric_value) * num_metrics);
306 if (values == NULL) {
307 TELEMETRY_LOG_ERR("Cannot allocate memory");
308 ret = rte_telemetry_send_error_response(telemetry,
311 TELEMETRY_LOG_ERR("Could not send error");
315 RTE_ETH_FOREACH_DEV(p) {
316 ep.pp.port_ids[num_port_ids] = p;
321 TELEMETRY_LOG_WARN("No active ports");
323 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
325 TELEMETRY_LOG_ERR("Could not send error");
330 ret = rte_metrics_get_values(ep.pp.port_ids[0], values, num_metrics);
332 TELEMETRY_LOG_ERR("Could not get stat values");
333 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
335 TELEMETRY_LOG_ERR("Could not send error");
338 for (i = 0; i < num_metrics; i++)
339 ep.pp.metric_ids[i] = values[i].key;
341 ep.pp.num_port_ids = num_port_ids;
342 ep.pp.num_metric_ids = num_metrics;
343 ep.type = PORT_STATS;
345 ret = rte_telemetry_send_ports_stats_values(&ep, telemetry);
347 TELEMETRY_LOG_ERR("Sending ports stats values failed");
360 rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry,
361 int action, json_t *data)
363 int ret, num_metrics, i;
364 struct rte_metric_value *values;
365 struct telemetry_encode_param ep;
367 memset(&ep, 0, sizeof(ep));
368 if (telemetry == NULL) {
369 TELEMETRY_LOG_ERR("Invalid telemetry argument");
373 if (action != ACTION_GET) {
374 TELEMETRY_LOG_WARN("Invalid action for this command");
375 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
377 TELEMETRY_LOG_ERR("Could not send error");
381 if (json_is_object(data)) {
382 TELEMETRY_LOG_WARN("Invalid data provided for this command");
383 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
385 TELEMETRY_LOG_ERR("Could not send error");
389 num_metrics = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0);
390 if (num_metrics < 0) {
391 TELEMETRY_LOG_ERR("Cannot get metrics count");
393 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
395 TELEMETRY_LOG_ERR("Could not send error");
398 } else if (num_metrics == 0) {
399 TELEMETRY_LOG_ERR("No metrics to display (none have been registered)");
401 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
403 TELEMETRY_LOG_ERR("Could not send error");
408 values = malloc(sizeof(struct rte_metric_value) * num_metrics);
409 if (values == NULL) {
410 TELEMETRY_LOG_ERR("Cannot allocate memory");
411 ret = rte_telemetry_send_error_response(telemetry,
414 TELEMETRY_LOG_ERR("Could not send error");
418 ret = rte_metrics_get_values(RTE_METRICS_GLOBAL, values, num_metrics);
420 TELEMETRY_LOG_ERR("Could not get stat values");
421 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
423 TELEMETRY_LOG_ERR("Could not send error");
426 for (i = 0; i < num_metrics; i++)
427 ep.gp.metric_ids[i] = values[i].key;
429 ep.gp.num_metric_ids = num_metrics;
430 ep.type = GLOBAL_STATS;
432 ret = rte_telemetry_send_global_stats_values(&ep, telemetry);
434 TELEMETRY_LOG_ERR("Sending global stats values failed");
447 rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl
448 *telemetry, int action, json_t *data)
451 json_t *port_ids_json = json_object_get(data, "ports");
452 json_t *stat_names_json = json_object_get(data, "stats");
453 uint64_t num_stat_names = json_array_size(stat_names_json);
454 const char *stat_names[num_stat_names];
455 struct telemetry_encode_param ep;
459 memset(&ep, 0, sizeof(ep));
460 ep.pp.num_port_ids = json_array_size(port_ids_json);
461 ep.pp.num_metric_ids = num_stat_names;
462 if (telemetry == NULL) {
463 TELEMETRY_LOG_ERR("Invalid telemetry argument");
467 if (action != ACTION_GET) {
468 TELEMETRY_LOG_WARN("Invalid action for this command");
469 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
471 TELEMETRY_LOG_ERR("Could not send error");
475 if (!json_is_object(data)) {
476 TELEMETRY_LOG_WARN("Invalid data provided for this command");
477 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
479 TELEMETRY_LOG_ERR("Could not send error");
483 if (!json_is_array(port_ids_json) ||
484 !json_is_array(stat_names_json)) {
485 TELEMETRY_LOG_WARN("Invalid input data array(s)");
486 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
488 TELEMETRY_LOG_ERR("Could not send error");
492 json_array_foreach(port_ids_json, index, value) {
493 if (!json_is_integer(value)) {
494 TELEMETRY_LOG_WARN("Port ID given is not valid");
495 ret = rte_telemetry_send_error_response(telemetry,
498 TELEMETRY_LOG_ERR("Could not send error");
501 ep.pp.port_ids[index] = json_integer_value(value);
502 ret = rte_telemetry_is_port_active(ep.pp.port_ids[index]);
504 ret = rte_telemetry_send_error_response(telemetry,
507 TELEMETRY_LOG_ERR("Could not send error");
512 json_array_foreach(stat_names_json, index, value) {
513 if (!json_is_string(value)) {
514 TELEMETRY_LOG_WARN("Stat Name given is not a string");
516 ret = rte_telemetry_send_error_response(telemetry,
519 TELEMETRY_LOG_ERR("Could not send error");
523 stat_names[index] = json_string_value(value);
526 ret = rte_telemetry_stat_names_to_ids(telemetry, stat_names,
527 ep.pp.metric_ids, num_stat_names);
529 TELEMETRY_LOG_ERR("Could not convert stat names to IDs");
533 ep.type = PORT_STATS;
534 ret = rte_telemetry_send_ports_stats_values(&ep, telemetry);
536 TELEMETRY_LOG_ERR("Sending ports stats values failed");
544 rte_telemetry_parse_command(struct telemetry_impl *telemetry, int action,
545 const char *command, json_t *data)
550 if (telemetry == NULL) {
551 TELEMETRY_LOG_ERR("Invalid telemetry argument");
555 struct rte_telemetry_command commands[] = {
558 .fn = &rte_telemetry_command_clients
562 .fn = &rte_telemetry_command_ports
565 .text = "ports_details",
566 .fn = &rte_telemetry_command_ports_details
569 .text = "port_stats",
570 .fn = &rte_telemetry_command_port_stats
573 .text = "ports_stats_values_by_name",
574 .fn = &rte_telemetry_command_ports_stats_values_by_name
577 .text = "ports_all_stat_values",
578 .fn = &rte_telemetry_command_ports_all_stat_values
581 .text = "global_stat_values",
582 .fn = &rte_telemetry_command_global_stat_values
586 const uint32_t num_commands = RTE_DIM(commands);
588 for (i = 0; i < num_commands; i++) {
589 if (strcmp(command, commands[i].text) == 0) {
590 ret = commands[i].fn(telemetry, action, data);
592 TELEMETRY_LOG_ERR("Command Function for %s failed",
600 TELEMETRY_LOG_WARN("\"%s\" command not found", command);
602 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
604 TELEMETRY_LOG_ERR("Could not send error");
610 rte_telemetry_parse(struct telemetry_impl *telemetry, char *socket_rx_data)
614 json_t *root, *action, *command, *data;
616 if (telemetry == NULL) {
617 TELEMETRY_LOG_ERR("Invalid telemetry argument");
621 root = json_loads(socket_rx_data, 0, &error);
623 TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s",
625 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
627 TELEMETRY_LOG_ERR("Could not send error");
629 } else if (!json_is_object(root)) {
630 TELEMETRY_LOG_WARN("JSON Request is not a JSON object");
635 action = json_object_get(root, "action");
636 if (action == NULL) {
637 TELEMETRY_LOG_WARN("Request does not have action field");
639 } else if (!json_is_integer(action)) {
640 TELEMETRY_LOG_WARN("Action value is not an integer");
644 command = json_object_get(root, "command");
645 if (command == NULL) {
646 TELEMETRY_LOG_WARN("Request does not have command field");
648 } else if (!json_is_string(command)) {
649 TELEMETRY_LOG_WARN("Command value is not a string");
653 action_int = json_integer_value(action);
654 if (action_int != ACTION_GET && action_int != ACTION_DELETE) {
655 TELEMETRY_LOG_WARN("Invalid action code");
659 const char *command_string = json_string_value(command);
660 data = json_object_get(root, "data");
662 TELEMETRY_LOG_WARN("Request does not have data field");
666 ret = rte_telemetry_parse_command(telemetry, action_int, command_string,
669 TELEMETRY_LOG_WARN("Could not parse command");
676 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
678 TELEMETRY_LOG_ERR("Could not send error");