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 uint32_t port_ids
[RTE_MAX_ETHPORTS
];
263 if (telemetry
== NULL
) {
264 TELEMETRY_LOG_ERR("Invalid telemetry argument");
268 if (action
!= ACTION_GET
) {
269 TELEMETRY_LOG_WARN("Invalid action for this command");
270 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
272 TELEMETRY_LOG_ERR("Could not send error");
276 if (json_is_object(data
)) {
277 TELEMETRY_LOG_WARN("Invalid data provided for this command");
278 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
280 TELEMETRY_LOG_ERR("Could not send error");
284 num_metrics
= rte_metrics_get_values(0, NULL
, 0);
285 if (num_metrics
< 0) {
286 TELEMETRY_LOG_ERR("Cannot get metrics count");
288 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
290 TELEMETRY_LOG_ERR("Could not send error");
293 } else if (num_metrics
== 0) {
294 TELEMETRY_LOG_ERR("No metrics to display (none have been registered)");
296 ret
= rte_telemetry_send_error_response(telemetry
, -EPERM
);
298 TELEMETRY_LOG_ERR("Could not send error");
303 values
= malloc(sizeof(struct rte_metric_value
) * num_metrics
);
304 if (values
== NULL
) {
305 TELEMETRY_LOG_ERR("Cannot allocate memory");
306 ret
= rte_telemetry_send_error_response(telemetry
,
309 TELEMETRY_LOG_ERR("Could not send error");
313 uint32_t stat_ids
[num_metrics
];
315 RTE_ETH_FOREACH_DEV(p
) {
316 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(port_ids
[0], values
, num_metrics
);
332 TELEMETRY_LOG_ERR("Could not get stat values");
335 for (i
= 0; i
< num_metrics
; i
++)
336 stat_ids
[i
] = values
[i
].key
;
338 ret
= rte_telemetry_send_ports_stats_values(stat_ids
, num_metrics
,
339 port_ids
, num_port_ids
, telemetry
);
341 TELEMETRY_LOG_ERR("Sending ports stats values failed");
353 rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl
354 *telemetry
, int action
, json_t
*data
)
357 json_t
*port_ids_json
= json_object_get(data
, "ports");
358 json_t
*stat_names_json
= json_object_get(data
, "stats");
359 uint64_t num_port_ids
= json_array_size(port_ids_json
);
360 uint64_t num_stat_names
= json_array_size(stat_names_json
);
361 const char *stat_names
[num_stat_names
];
362 uint32_t port_ids
[num_port_ids
], stat_ids
[num_stat_names
];
366 if (telemetry
== NULL
) {
367 TELEMETRY_LOG_ERR("Invalid telemetry argument");
371 if (action
!= ACTION_GET
) {
372 TELEMETRY_LOG_WARN("Invalid action for this command");
373 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
375 TELEMETRY_LOG_ERR("Could not send error");
379 if (!json_is_object(data
)) {
380 TELEMETRY_LOG_WARN("Invalid data provided for this command");
381 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
383 TELEMETRY_LOG_ERR("Could not send error");
387 if (!json_is_array(port_ids_json
) ||
388 !json_is_array(stat_names_json
)) {
389 TELEMETRY_LOG_WARN("Invalid input data array(s)");
390 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
392 TELEMETRY_LOG_ERR("Could not send error");
396 json_array_foreach(port_ids_json
, index
, value
) {
397 if (!json_is_integer(value
)) {
398 TELEMETRY_LOG_WARN("Port ID given is not valid");
399 ret
= rte_telemetry_send_error_response(telemetry
,
402 TELEMETRY_LOG_ERR("Could not send error");
405 port_ids
[index
] = json_integer_value(value
);
406 ret
= rte_telemetry_is_port_active(port_ids
[index
]);
408 ret
= rte_telemetry_send_error_response(telemetry
,
411 TELEMETRY_LOG_ERR("Could not send error");
416 json_array_foreach(stat_names_json
, index
, value
) {
417 if (!json_is_string(value
)) {
418 TELEMETRY_LOG_WARN("Stat Name given is not a string");
420 ret
= rte_telemetry_send_error_response(telemetry
,
423 TELEMETRY_LOG_ERR("Could not send error");
427 stat_names
[index
] = json_string_value(value
);
430 ret
= rte_telemetry_stat_names_to_ids(telemetry
, stat_names
, stat_ids
,
433 TELEMETRY_LOG_ERR("Could not convert stat names to IDs");
437 ret
= rte_telemetry_send_ports_stats_values(stat_ids
, num_stat_names
,
438 port_ids
, num_port_ids
, telemetry
);
440 TELEMETRY_LOG_ERR("Sending ports stats values failed");
448 rte_telemetry_parse_command(struct telemetry_impl
*telemetry
, int action
,
449 const char *command
, json_t
*data
)
454 if (telemetry
== NULL
) {
455 TELEMETRY_LOG_ERR("Invalid telemetry argument");
459 struct rte_telemetry_command commands
[] = {
462 .fn
= &rte_telemetry_command_clients
466 .fn
= &rte_telemetry_command_ports
469 .text
= "ports_details",
470 .fn
= &rte_telemetry_command_ports_details
473 .text
= "port_stats",
474 .fn
= &rte_telemetry_command_port_stats
477 .text
= "ports_stats_values_by_name",
478 .fn
= &rte_telemetry_command_ports_stats_values_by_name
481 .text
= "ports_all_stat_values",
482 .fn
= &rte_telemetry_command_ports_all_stat_values
486 const uint32_t num_commands
= RTE_DIM(commands
);
488 for (i
= 0; i
< num_commands
; i
++) {
489 if (strcmp(command
, commands
[i
].text
) == 0) {
490 ret
= commands
[i
].fn(telemetry
, action
, data
);
492 TELEMETRY_LOG_ERR("Command Function for %s failed",
500 TELEMETRY_LOG_WARN("\"%s\" command not found", command
);
502 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
504 TELEMETRY_LOG_ERR("Could not send error");
509 int32_t __rte_experimental
510 rte_telemetry_parse(struct telemetry_impl
*telemetry
, char *socket_rx_data
)
514 json_t
*root
, *action
, *command
, *data
;
516 if (telemetry
== NULL
) {
517 TELEMETRY_LOG_ERR("Invalid telemetry argument");
521 root
= json_loads(socket_rx_data
, 0, &error
);
523 TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s",
525 ret
= rte_telemetry_send_error_response(telemetry
, -EPERM
);
527 TELEMETRY_LOG_ERR("Could not send error");
529 } else if (!json_is_object(root
)) {
530 TELEMETRY_LOG_WARN("JSON Request is not a JSON object");
535 action
= json_object_get(root
, "action");
536 if (action
== NULL
) {
537 TELEMETRY_LOG_WARN("Request does not have action field");
539 } else if (!json_is_integer(action
)) {
540 TELEMETRY_LOG_WARN("Action value is not an integer");
544 command
= json_object_get(root
, "command");
545 if (command
== NULL
) {
546 TELEMETRY_LOG_WARN("Request does not have command field");
548 } else if (!json_is_string(command
)) {
549 TELEMETRY_LOG_WARN("Command value is not a string");
553 action_int
= json_integer_value(action
);
554 if (action_int
!= ACTION_GET
&& action_int
!= ACTION_DELETE
) {
555 TELEMETRY_LOG_WARN("Invalid action code");
559 const char *command_string
= json_string_value(command
);
560 data
= json_object_get(root
, "data");
562 TELEMETRY_LOG_WARN("Request does not have data field");
566 ret
= rte_telemetry_parse_command(telemetry
, action_int
, command_string
,
569 TELEMETRY_LOG_WARN("Could not parse command");
576 ret
= rte_telemetry_send_error_response(telemetry
, -EINVAL
);
578 TELEMETRY_LOG_ERR("Could not send error");