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"
17 typedef int (*command_func)(struct telemetry_impl *, int, json_t *);
19 struct rte_telemetry_command {
25 rte_telemetry_command_clients(struct telemetry_impl *telemetry, int action,
30 if (telemetry == NULL) {
31 TELEMETRY_LOG_ERR("Invalid telemetry argument");
35 if (action != ACTION_DELETE) {
36 TELEMETRY_LOG_WARN("Invalid action for this command");
40 if (!json_is_object(data)) {
41 TELEMETRY_LOG_WARN("Invalid data provided for this command");
45 json_t *client_path = json_object_get(data, "client_path");
46 if (!json_is_string(client_path)) {
47 TELEMETRY_LOG_WARN("Command value is not a string");
51 ret = rte_telemetry_unregister_client(telemetry,
52 json_string_value(client_path));
54 TELEMETRY_LOG_ERR("Could not unregister client");
61 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
63 TELEMETRY_LOG_ERR("Could not send error");
68 rte_telemetry_command_ports(struct telemetry_impl *telemetry, int action,
73 if (telemetry == NULL) {
74 TELEMETRY_LOG_ERR("Invalid telemetry argument");
78 if (!json_is_null(data)) {
79 TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'ports' command");
83 if (action != ACTION_GET) {
84 TELEMETRY_LOG_WARN("Invalid action for this command");
91 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
93 TELEMETRY_LOG_ERR("Could not send error");
98 rte_telemetry_command_ports_details(struct telemetry_impl *telemetry,
99 int action, json_t *data)
101 json_t *value, *port_ids_json = json_object_get(data, "ports");
102 uint64_t num_port_ids = json_array_size(port_ids_json);
103 int ret, port_ids[num_port_ids];
104 RTE_SET_USED(port_ids);
107 if (telemetry == NULL) {
108 TELEMETRY_LOG_ERR("Invalid telemetry argument");
112 if (action != ACTION_GET) {
113 TELEMETRY_LOG_WARN("Invalid action for this command");
117 if (!json_is_object(data)) {
118 TELEMETRY_LOG_WARN("Invalid data provided for this command");
122 if (!json_is_array(port_ids_json)) {
123 TELEMETRY_LOG_WARN("Invalid Port ID array");
127 json_array_foreach(port_ids_json, index, value) {
128 if (!json_is_integer(value)) {
129 TELEMETRY_LOG_WARN("Port ID given is invalid");
132 port_ids[index] = json_integer_value(value);
138 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
140 TELEMETRY_LOG_ERR("Could not send error");
145 rte_telemetry_command_port_stats(struct telemetry_impl *telemetry, int action,
150 if (telemetry == NULL) {
151 TELEMETRY_LOG_ERR("Invalid telemetry argument");
155 if (!json_is_null(data)) {
156 TELEMETRY_LOG_WARN("Data should be NULL JSON object for 'port_stats' command");
160 if (action != ACTION_GET) {
161 TELEMETRY_LOG_WARN("Invalid action for this command");
168 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
170 TELEMETRY_LOG_ERR("Could not send error");
175 rte_telemetry_stat_names_to_ids(struct telemetry_impl *telemetry,
176 const char * const *stat_names, uint32_t *stat_ids,
177 uint64_t num_stat_names)
179 struct rte_metric_name *names;
180 int ret, num_metrics;
183 if (stat_names == NULL) {
184 TELEMETRY_LOG_WARN("Invalid stat_names argument");
188 if (num_stat_names <= 0) {
189 TELEMETRY_LOG_WARN("Invalid num_stat_names argument");
193 num_metrics = rte_metrics_get_names(NULL, 0);
194 if (num_metrics < 0) {
195 TELEMETRY_LOG_ERR("Cannot get metrics count");
197 } else if (num_metrics == 0) {
198 TELEMETRY_LOG_WARN("No metrics have been registered");
202 names = malloc(sizeof(struct rte_metric_name) * num_metrics);
204 TELEMETRY_LOG_ERR("Cannot allocate memory for names");
206 ret = rte_telemetry_send_error_response(telemetry, -ENOMEM);
208 TELEMETRY_LOG_ERR("Could not send error");
213 ret = rte_metrics_get_names(names, num_metrics);
214 if (ret < 0 || ret > num_metrics) {
215 TELEMETRY_LOG_ERR("Cannot get metrics names");
221 for (i = 0; i < (uint32_t)num_stat_names; i++) {
223 for (j = 0; j < (uint32_t)num_metrics; j++) {
224 if (strcmp(stat_names[i], names[j].name) == 0) {
232 if (k != num_stat_names) {
233 TELEMETRY_LOG_WARN("Invalid stat names provided");
242 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
244 TELEMETRY_LOG_ERR("Could not send error");
248 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
250 TELEMETRY_LOG_ERR("Could not send error");
255 rte_telemetry_command_ports_all_stat_values(struct telemetry_impl *telemetry,
256 int action, json_t *data)
258 int ret, num_metrics, i, p;
259 struct rte_metric_value *values;
260 uint64_t num_port_ids = 0;
261 struct telemetry_encode_param ep;
263 memset(&ep, 0, sizeof(ep));
264 if (telemetry == NULL) {
265 TELEMETRY_LOG_ERR("Invalid telemetry argument");
269 if (action != ACTION_GET) {
270 TELEMETRY_LOG_WARN("Invalid action for this command");
271 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
273 TELEMETRY_LOG_ERR("Could not send error");
277 if (json_is_object(data)) {
278 TELEMETRY_LOG_WARN("Invalid data provided for this command");
279 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
281 TELEMETRY_LOG_ERR("Could not send error");
285 num_metrics = rte_metrics_get_values(0, NULL, 0);
286 if (num_metrics < 0) {
287 TELEMETRY_LOG_ERR("Cannot get metrics count");
289 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
291 TELEMETRY_LOG_ERR("Could not send error");
294 } else if (num_metrics == 0) {
295 TELEMETRY_LOG_ERR("No metrics to display (none have been registered)");
297 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
299 TELEMETRY_LOG_ERR("Could not send error");
304 values = malloc(sizeof(struct rte_metric_value) * num_metrics);
305 if (values == NULL) {
306 TELEMETRY_LOG_ERR("Cannot allocate memory");
307 ret = rte_telemetry_send_error_response(telemetry,
310 TELEMETRY_LOG_ERR("Could not send error");
314 RTE_ETH_FOREACH_DEV(p) {
315 ep.pp.port_ids[num_port_ids] = p;
320 TELEMETRY_LOG_WARN("No active ports");
322 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
324 TELEMETRY_LOG_ERR("Could not send error");
329 ret = rte_metrics_get_values(ep.pp.port_ids[0], values, num_metrics);
331 TELEMETRY_LOG_ERR("Could not get stat values");
332 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
334 TELEMETRY_LOG_ERR("Could not send error");
337 for (i = 0; i < num_metrics; i++)
338 ep.pp.metric_ids[i] = values[i].key;
340 ep.pp.num_port_ids = num_port_ids;
341 ep.pp.num_metric_ids = num_metrics;
342 ep.type = PORT_STATS;
344 ret = rte_telemetry_send_ports_stats_values(&ep, telemetry);
346 TELEMETRY_LOG_ERR("Sending ports stats values failed");
359 rte_telemetry_command_global_stat_values(struct telemetry_impl *telemetry,
360 int action, json_t *data)
362 int ret, num_metrics, i;
363 struct rte_metric_value *values;
364 struct telemetry_encode_param ep;
366 memset(&ep, 0, sizeof(ep));
367 if (telemetry == NULL) {
368 TELEMETRY_LOG_ERR("Invalid telemetry argument");
372 if (action != ACTION_GET) {
373 TELEMETRY_LOG_WARN("Invalid action for this command");
374 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
376 TELEMETRY_LOG_ERR("Could not send error");
380 if (json_is_object(data)) {
381 TELEMETRY_LOG_WARN("Invalid data provided for this command");
382 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
384 TELEMETRY_LOG_ERR("Could not send error");
388 num_metrics = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0);
389 if (num_metrics < 0) {
390 TELEMETRY_LOG_ERR("Cannot get metrics count");
392 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
394 TELEMETRY_LOG_ERR("Could not send error");
397 } else if (num_metrics == 0) {
398 TELEMETRY_LOG_ERR("No metrics to display (none have been registered)");
400 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
402 TELEMETRY_LOG_ERR("Could not send error");
407 values = malloc(sizeof(struct rte_metric_value) * num_metrics);
408 if (values == NULL) {
409 TELEMETRY_LOG_ERR("Cannot allocate memory");
410 ret = rte_telemetry_send_error_response(telemetry,
413 TELEMETRY_LOG_ERR("Could not send error");
417 ret = rte_metrics_get_values(RTE_METRICS_GLOBAL, values, num_metrics);
419 TELEMETRY_LOG_ERR("Could not get stat values");
420 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
422 TELEMETRY_LOG_ERR("Could not send error");
425 for (i = 0; i < num_metrics; i++)
426 ep.gp.metric_ids[i] = values[i].key;
428 ep.gp.num_metric_ids = num_metrics;
429 ep.type = GLOBAL_STATS;
431 ret = rte_telemetry_send_global_stats_values(&ep, telemetry);
433 TELEMETRY_LOG_ERR("Sending global stats values failed");
446 rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl
447 *telemetry, int action, json_t *data)
450 json_t *port_ids_json = json_object_get(data, "ports");
451 json_t *stat_names_json = json_object_get(data, "stats");
452 uint64_t num_stat_names = json_array_size(stat_names_json);
453 const char *stat_names[num_stat_names];
454 struct telemetry_encode_param ep;
458 ep.pp.num_port_ids = json_array_size(port_ids_json);
459 ep.pp.num_metric_ids = num_stat_names;
460 memset(&ep, 0, sizeof(ep));
461 if (telemetry == NULL) {
462 TELEMETRY_LOG_ERR("Invalid telemetry argument");
466 if (action != ACTION_GET) {
467 TELEMETRY_LOG_WARN("Invalid action for this command");
468 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
470 TELEMETRY_LOG_ERR("Could not send error");
474 if (!json_is_object(data)) {
475 TELEMETRY_LOG_WARN("Invalid data provided for this command");
476 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
478 TELEMETRY_LOG_ERR("Could not send error");
482 if (!json_is_array(port_ids_json) ||
483 !json_is_array(stat_names_json)) {
484 TELEMETRY_LOG_WARN("Invalid input data array(s)");
485 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
487 TELEMETRY_LOG_ERR("Could not send error");
491 json_array_foreach(port_ids_json, index, value) {
492 if (!json_is_integer(value)) {
493 TELEMETRY_LOG_WARN("Port ID given is not valid");
494 ret = rte_telemetry_send_error_response(telemetry,
497 TELEMETRY_LOG_ERR("Could not send error");
500 ep.pp.port_ids[index] = json_integer_value(value);
501 ret = rte_telemetry_is_port_active(ep.pp.port_ids[index]);
503 ret = rte_telemetry_send_error_response(telemetry,
506 TELEMETRY_LOG_ERR("Could not send error");
511 json_array_foreach(stat_names_json, index, value) {
512 if (!json_is_string(value)) {
513 TELEMETRY_LOG_WARN("Stat Name given is not a string");
515 ret = rte_telemetry_send_error_response(telemetry,
518 TELEMETRY_LOG_ERR("Could not send error");
522 stat_names[index] = json_string_value(value);
525 ret = rte_telemetry_stat_names_to_ids(telemetry, stat_names,
526 ep.pp.metric_ids, num_stat_names);
528 TELEMETRY_LOG_ERR("Could not convert stat names to IDs");
532 ep.type = PORT_STATS;
533 ret = rte_telemetry_send_ports_stats_values(&ep, telemetry);
535 TELEMETRY_LOG_ERR("Sending ports stats values failed");
543 rte_telemetry_parse_command(struct telemetry_impl *telemetry, int action,
544 const char *command, json_t *data)
549 if (telemetry == NULL) {
550 TELEMETRY_LOG_ERR("Invalid telemetry argument");
554 struct rte_telemetry_command commands[] = {
557 .fn = &rte_telemetry_command_clients
561 .fn = &rte_telemetry_command_ports
564 .text = "ports_details",
565 .fn = &rte_telemetry_command_ports_details
568 .text = "port_stats",
569 .fn = &rte_telemetry_command_port_stats
572 .text = "ports_stats_values_by_name",
573 .fn = &rte_telemetry_command_ports_stats_values_by_name
576 .text = "ports_all_stat_values",
577 .fn = &rte_telemetry_command_ports_all_stat_values
580 .text = "global_stat_values",
581 .fn = &rte_telemetry_command_global_stat_values
585 const uint32_t num_commands = RTE_DIM(commands);
587 for (i = 0; i < num_commands; i++) {
588 if (strcmp(command, commands[i].text) == 0) {
589 ret = commands[i].fn(telemetry, action, data);
591 TELEMETRY_LOG_ERR("Command Function for %s failed",
599 TELEMETRY_LOG_WARN("\"%s\" command not found", command);
601 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
603 TELEMETRY_LOG_ERR("Could not send error");
608 int32_t __rte_experimental
609 rte_telemetry_parse(struct telemetry_impl *telemetry, char *socket_rx_data)
613 json_t *root, *action, *command, *data;
615 if (telemetry == NULL) {
616 TELEMETRY_LOG_ERR("Invalid telemetry argument");
620 root = json_loads(socket_rx_data, 0, &error);
622 TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s",
624 ret = rte_telemetry_send_error_response(telemetry, -EPERM);
626 TELEMETRY_LOG_ERR("Could not send error");
628 } else if (!json_is_object(root)) {
629 TELEMETRY_LOG_WARN("JSON Request is not a JSON object");
634 action = json_object_get(root, "action");
635 if (action == NULL) {
636 TELEMETRY_LOG_WARN("Request does not have action field");
638 } else if (!json_is_integer(action)) {
639 TELEMETRY_LOG_WARN("Action value is not an integer");
643 command = json_object_get(root, "command");
644 if (command == NULL) {
645 TELEMETRY_LOG_WARN("Request does not have command field");
647 } else if (!json_is_string(command)) {
648 TELEMETRY_LOG_WARN("Command value is not a string");
652 action_int = json_integer_value(action);
653 if (action_int != ACTION_GET && action_int != ACTION_DELETE) {
654 TELEMETRY_LOG_WARN("Invalid action code");
658 const char *command_string = json_string_value(command);
659 data = json_object_get(root, "data");
661 TELEMETRY_LOG_WARN("Request does not have data field");
665 ret = rte_telemetry_parse_command(telemetry, action_int, command_string,
668 TELEMETRY_LOG_WARN("Could not parse command");
675 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
677 TELEMETRY_LOG_ERR("Could not send error");