1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
8 #include <sys/socket.h>
13 #include <rte_ethdev.h>
14 #include <rte_metrics.h>
15 #include <rte_option.h>
16 #include <rte_string_fns.h>
18 #include "rte_telemetry.h"
19 #include "rte_telemetry_internal.h"
20 #include "rte_telemetry_parser.h"
21 #include "rte_telemetry_socket_tests.h"
27 #define SELFTEST_VALID_CLIENT "/var/run/dpdk/valid_client"
28 #define SELFTEST_INVALID_CLIENT "/var/run/dpdk/invalid_client"
29 #define SOCKET_TEST_CLIENT_PATH "/var/run/dpdk/client"
31 static telemetry_impl *static_telemetry;
33 struct telemetry_message_test {
34 const char *test_name;
35 int (*test_func_ptr)(struct telemetry_impl *telemetry, int fd);
47 rte_telemetry_get_runtime_dir(char *socket_path, size_t size)
49 snprintf(socket_path, size, "%s/telemetry", rte_eal_get_runtime_dir());
53 rte_telemetry_write_to_socket(struct telemetry_impl *telemetry,
54 const char *json_string)
58 if (telemetry == NULL) {
59 TELEMETRY_LOG_ERR("Could not initialise TELEMETRY_API");
63 if (telemetry->request_client == NULL) {
64 TELEMETRY_LOG_ERR("No client has been chosen to write to");
68 if (json_string == NULL) {
69 TELEMETRY_LOG_ERR("Invalid JSON string!");
73 ret = send(telemetry->request_client->fd,
74 json_string, strlen(json_string), 0);
76 TELEMETRY_LOG_ERR("Failed to write to socket for client: %s",
77 telemetry->request_client->file_path);
85 rte_telemetry_send_error_response(struct telemetry_impl *telemetry,
89 const char *status_code, *json_buffer;
92 if (error_type == -EPERM)
93 status_code = "Status Error: Unknown";
94 else if (error_type == -EINVAL)
95 status_code = "Status Error: Invalid Argument 404";
96 else if (error_type == -ENOMEM)
97 status_code = "Status Error: Memory Allocation Error";
99 TELEMETRY_LOG_ERR("Invalid error type");
103 root = json_object();
106 TELEMETRY_LOG_ERR("Could not create root JSON object");
110 ret = json_object_set_new(root, "status_code", json_string(status_code));
112 TELEMETRY_LOG_ERR("Status code field cannot be set");
117 ret = json_object_set_new(root, "data", json_null());
119 TELEMETRY_LOG_ERR("Data field cannot be set");
124 json_buffer = json_dumps(root, 0);
127 ret = rte_telemetry_write_to_socket(telemetry, json_buffer);
129 TELEMETRY_LOG_ERR("Could not write to socket");
137 rte_telemetry_send_global_stats_values(struct telemetry_encode_param *ep,
138 struct telemetry_impl *telemetry)
141 char *json_buffer = NULL;
143 if (telemetry == NULL) {
144 TELEMETRY_LOG_ERR("Invalid telemetry argument");
148 if (ep->gp.num_metric_ids < 0) {
149 TELEMETRY_LOG_ERR("Invalid num_metric_ids, must be positive");
153 ret = rte_metrics_tel_encode_json_format(ep, &json_buffer);
155 TELEMETRY_LOG_ERR("JSON encode function failed");
156 ret = rte_telemetry_send_error_response(telemetry, ret);
158 TELEMETRY_LOG_ERR("Could not send error");
162 ret = rte_telemetry_write_to_socket(telemetry, json_buffer);
164 TELEMETRY_LOG_ERR("Could not write to socket");
171 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
173 TELEMETRY_LOG_ERR("Could not send error");
178 rte_telemetry_send_ports_stats_values(struct telemetry_encode_param *ep,
179 struct telemetry_impl *telemetry)
182 char *json_buffer = NULL;
184 if (telemetry == NULL) {
185 TELEMETRY_LOG_ERR("Invalid telemetry argument");
190 TELEMETRY_LOG_ERR("Invalid encode param argument");
194 if (ep->pp.num_metric_ids < 0) {
195 TELEMETRY_LOG_ERR("Invalid num_metric_ids, must be positive");
199 if (ep->pp.num_port_ids < 0) {
200 TELEMETRY_LOG_ERR("Invalid num_port_ids, must be positive");
204 ret = rte_metrics_tel_get_ports_stats_json(ep, telemetry->reg_index,
207 TELEMETRY_LOG_ERR("Function for get_ports_stats_json"
209 ret = rte_telemetry_send_error_response(telemetry, ret);
211 TELEMETRY_LOG_ERR("Could not send error");
215 ret = rte_telemetry_write_to_socket(telemetry, json_buffer);
217 TELEMETRY_LOG_ERR("Could not write to socket");
224 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
226 TELEMETRY_LOG_ERR("Could not send error");
231 rte_telemetry_initial_accept(struct telemetry_impl *telemetry)
236 ret = rte_metrics_tel_reg_all_ethdev(
237 &telemetry->metrics_register_done,
238 telemetry->reg_index);
240 TELEMETRY_LOG_ERR("Failed to register ethdev metrics");
241 ret = rte_telemetry_send_error_response(telemetry, ret);
243 TELEMETRY_LOG_ERR("Could not send error");
248 ret = rte_telemetry_socket_messaging_testing(telemetry->reg_index[0],
249 telemetry->server_fd);
253 ret = rte_telemetry_parser_test(telemetry);
255 TELEMETRY_LOG_ERR("Parser Tests Failed");
259 TELEMETRY_LOG_INFO("Success - All Parser Tests Passed");
266 rte_telemetry_read_client(struct telemetry_impl *telemetry)
269 int ret, buffer_read;
271 buffer_read = read(telemetry->accept_fd, buf, BUF_SIZE-1);
273 if (buffer_read == -1) {
274 TELEMETRY_LOG_ERR("Read error");
276 } else if (buffer_read == 0) {
279 buf[buffer_read] = '\0';
280 ret = rte_telemetry_parse_client_message(telemetry, buf);
282 TELEMETRY_LOG_WARN("Parse message failed");
287 if (close(telemetry->accept_fd) < 0) {
288 TELEMETRY_LOG_ERR("Close TELEMETRY socket failed");
292 telemetry->accept_fd = 0;
298 rte_telemetry_accept_new_client(struct telemetry_impl *telemetry)
302 if (telemetry->accept_fd <= 0) {
303 ret = listen(telemetry->server_fd, 1);
305 TELEMETRY_LOG_ERR("Listening error with server fd");
309 telemetry->accept_fd = accept(telemetry->server_fd, NULL, NULL);
310 if (telemetry->accept_fd >= 0 &&
311 telemetry->metrics_register_done == 0) {
312 ret = rte_telemetry_initial_accept(telemetry);
314 TELEMETRY_LOG_ERR("Failed to run initial configurations/tests");
319 ret = rte_telemetry_read_client(telemetry);
321 TELEMETRY_LOG_ERR("Failed to read socket buffer");
330 rte_telemetry_read_client_sockets(struct telemetry_impl *telemetry)
333 telemetry_client *client;
334 char client_buf[BUF_SIZE];
337 TAILQ_FOREACH(client, &telemetry->client_list_head, client_list) {
338 bytes = read(client->fd, client_buf, BUF_SIZE-1);
341 client_buf[bytes] = '\0';
342 telemetry->request_client = client;
343 ret = rte_telemetry_parse(telemetry, client_buf);
345 TELEMETRY_LOG_WARN("Parse socket input failed: %i",
356 rte_telemetry_run(void *userdata)
359 struct telemetry_impl *telemetry = userdata;
361 if (telemetry == NULL) {
362 TELEMETRY_LOG_WARN("TELEMETRY could not be initialised");
366 ret = rte_telemetry_accept_new_client(telemetry);
368 TELEMETRY_LOG_ERR("Accept and read new client failed");
372 ret = rte_telemetry_read_client_sockets(telemetry);
374 TELEMETRY_LOG_ERR("Client socket read failed");
382 *rte_telemetry_run_thread_func(void *userdata)
385 struct telemetry_impl *telemetry = userdata;
387 if (telemetry == NULL) {
388 TELEMETRY_LOG_ERR("%s passed a NULL instance", __func__);
392 while (telemetry->thread_status) {
393 rte_telemetry_run(telemetry);
394 ret = usleep(SLEEP_TIME);
396 TELEMETRY_LOG_ERR("Calling thread could not be put to sleep");
402 rte_telemetry_set_socket_nonblock(int fd)
407 TELEMETRY_LOG_ERR("Invalid fd provided");
411 flags = fcntl(fd, F_GETFL, 0);
415 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
419 rte_telemetry_create_socket(struct telemetry_impl *telemetry)
422 struct sockaddr_un addr;
423 char socket_path[BUF_SIZE];
425 if (telemetry == NULL)
428 telemetry->server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
429 if (telemetry->server_fd == -1) {
430 TELEMETRY_LOG_ERR("Failed to open socket");
434 ret = rte_telemetry_set_socket_nonblock(telemetry->server_fd);
436 TELEMETRY_LOG_ERR("Could not set socket to NONBLOCK");
440 addr.sun_family = AF_UNIX;
441 rte_telemetry_get_runtime_dir(socket_path, sizeof(socket_path));
442 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
445 if (bind(telemetry->server_fd, (struct sockaddr *)&addr,
447 TELEMETRY_LOG_ERR("Socket binding error");
454 if (close(telemetry->server_fd) < 0) {
455 TELEMETRY_LOG_ERR("Close TELEMETRY socket failed");
463 rte_telemetry_init(void)
467 const char *telemetry_ctrl_thread = "telemetry";
469 if (static_telemetry) {
470 TELEMETRY_LOG_WARN("TELEMETRY structure already initialised");
474 static_telemetry = calloc(1, sizeof(struct telemetry_impl));
475 if (static_telemetry == NULL) {
476 TELEMETRY_LOG_ERR("Memory could not be allocated");
480 static_telemetry->socket_id = rte_socket_id();
481 rte_metrics_init(static_telemetry->socket_id);
483 ret = pthread_attr_init(&attr);
485 TELEMETRY_LOG_ERR("Pthread attribute init failed");
489 ret = rte_telemetry_create_socket(static_telemetry);
491 ret = rte_telemetry_cleanup();
493 TELEMETRY_LOG_ERR("TELEMETRY cleanup failed");
496 TAILQ_INIT(&static_telemetry->client_list_head);
498 ret = rte_ctrl_thread_create(&static_telemetry->thread_id,
499 telemetry_ctrl_thread, &attr, rte_telemetry_run_thread_func,
500 (void *)static_telemetry);
501 static_telemetry->thread_status = 1;
504 ret = rte_telemetry_cleanup();
506 TELEMETRY_LOG_ERR("TELEMETRY cleanup failed");
514 rte_telemetry_client_cleanup(struct telemetry_client *client)
518 ret = close(client->fd);
519 free(client->file_path);
523 TELEMETRY_LOG_ERR("Close client socket failed");
531 rte_telemetry_cleanup(void)
534 struct telemetry_impl *telemetry = static_telemetry;
535 telemetry_client *client, *temp_client;
537 TAILQ_FOREACH_SAFE(client, &telemetry->client_list_head, client_list,
539 TAILQ_REMOVE(&telemetry->client_list_head, client, client_list);
540 ret = rte_telemetry_client_cleanup(client);
542 TELEMETRY_LOG_ERR("Client cleanup failed");
547 ret = close(telemetry->server_fd);
549 TELEMETRY_LOG_ERR("Close TELEMETRY socket failed");
554 telemetry->thread_status = 0;
555 pthread_join(telemetry->thread_id, NULL);
557 static_telemetry = NULL;
563 rte_telemetry_unregister_client(struct telemetry_impl *telemetry,
564 const char *client_path)
567 telemetry_client *client, *temp_client;
569 if (telemetry == NULL) {
570 TELEMETRY_LOG_WARN("TELEMETRY is not initialised");
574 if (client_path == NULL) {
575 TELEMETRY_LOG_ERR("Invalid client path");
579 if (TAILQ_EMPTY(&telemetry->client_list_head)) {
580 TELEMETRY_LOG_ERR("There are no clients currently registered");
584 TAILQ_FOREACH_SAFE(client, &telemetry->client_list_head, client_list,
586 if (strcmp(client_path, client->file_path) == 0) {
587 TAILQ_REMOVE(&telemetry->client_list_head, client,
589 ret = rte_telemetry_client_cleanup(client);
592 TELEMETRY_LOG_ERR("Client cleanup failed");
600 TELEMETRY_LOG_WARN("Couldn't find client, possibly not registered yet.");
604 ret = rte_telemetry_send_error_response(telemetry, -EINVAL);
606 TELEMETRY_LOG_ERR("Could not send error");
611 rte_telemetry_register_client(struct telemetry_impl *telemetry,
612 const char *client_path)
615 struct sockaddr_un addrs;
617 if (telemetry == NULL) {
618 TELEMETRY_LOG_ERR("Could not initialize TELEMETRY API");
622 if (client_path == NULL) {
623 TELEMETRY_LOG_ERR("Invalid client path");
627 telemetry_client *client;
628 TAILQ_FOREACH(client, &telemetry->client_list_head, client_list) {
629 if (strcmp(client_path, client->file_path) == 0) {
630 TELEMETRY_LOG_WARN("'%s' already registered",
636 fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
638 TELEMETRY_LOG_ERR("Client socket error");
642 ret = rte_telemetry_set_socket_nonblock(fd);
644 TELEMETRY_LOG_ERR("Could not set socket to NONBLOCK");
648 addrs.sun_family = AF_UNIX;
649 strlcpy(addrs.sun_path, client_path, sizeof(addrs.sun_path));
650 telemetry_client *new_client = malloc(sizeof(telemetry_client));
651 new_client->file_path = strdup(client_path);
654 if (connect(fd, (struct sockaddr *)&addrs, sizeof(addrs)) == -1) {
655 TELEMETRY_LOG_ERR("TELEMETRY client connect to %s didn't work",
657 ret = rte_telemetry_client_cleanup(new_client);
659 TELEMETRY_LOG_ERR("Client cleanup failed");
665 TAILQ_INSERT_HEAD(&telemetry->client_list_head, new_client, client_list);
671 rte_telemetry_parse_client_message(struct telemetry_impl *telemetry, char *buf)
675 json_t *root = json_loads(buf, 0, &error);
678 TELEMETRY_LOG_WARN("Could not load JSON object from data passed in : %s",
681 } else if (!json_is_object(root)) {
682 TELEMETRY_LOG_WARN("JSON Request is not a JSON object");
686 json_t *action = json_object_get(root, "action");
687 if (action == NULL) {
688 TELEMETRY_LOG_WARN("Request does not have action field");
690 } else if (!json_is_integer(action)) {
691 TELEMETRY_LOG_WARN("Action value is not an integer");
695 json_t *command = json_object_get(root, "command");
696 if (command == NULL) {
697 TELEMETRY_LOG_WARN("Request does not have command field");
699 } else if (!json_is_string(command)) {
700 TELEMETRY_LOG_WARN("Command value is not a string");
704 action_int = json_integer_value(action);
705 if (action_int != ACTION_POST) {
706 TELEMETRY_LOG_WARN("Invalid action code");
710 if (strcmp(json_string_value(command), "clients") != 0) {
711 TELEMETRY_LOG_WARN("Invalid command");
715 json_t *data = json_object_get(root, "data");
717 TELEMETRY_LOG_WARN("Request does not have data field");
721 json_t *client_path = json_object_get(data, "client_path");
722 if (client_path == NULL) {
723 TELEMETRY_LOG_WARN("Request does not have client_path field");
727 if (!json_is_string(client_path)) {
728 TELEMETRY_LOG_WARN("Client_path value is not a string");
732 ret = rte_telemetry_register_client(telemetry,
733 json_string_value(client_path));
735 TELEMETRY_LOG_ERR("Could not register client");
736 telemetry->register_fail_count++;
743 TELEMETRY_LOG_WARN("Client attempted to register with invalid message");
749 rte_telemetry_dummy_client_socket(const char *valid_client_path)
751 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
752 struct sockaddr_un addr = {0};
755 TELEMETRY_LOG_ERR("Test socket creation failure");
759 addr.sun_family = AF_UNIX;
760 strlcpy(addr.sun_path, valid_client_path, sizeof(addr.sun_path));
761 unlink(valid_client_path);
763 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
764 TELEMETRY_LOG_ERR("Test socket binding failure");
768 if (listen(sockfd, 1) < 0) {
769 TELEMETRY_LOG_ERR("Listen failure");
777 rte_telemetry_selftest(void)
779 const char *invalid_client_path = SELFTEST_INVALID_CLIENT;
780 const char *valid_client_path = SELFTEST_VALID_CLIENT;
783 TELEMETRY_LOG_INFO("Selftest");
785 ret = rte_telemetry_init();
787 TELEMETRY_LOG_ERR("Valid initialisation test failed");
791 TELEMETRY_LOG_INFO("Success - Valid initialisation test passed");
793 ret = rte_telemetry_init();
794 if (ret != -EALREADY) {
795 TELEMETRY_LOG_ERR("Invalid initialisation test failed");
799 TELEMETRY_LOG_INFO("Success - Invalid initialisation test passed");
801 ret = rte_telemetry_unregister_client(static_telemetry,
802 invalid_client_path);
804 TELEMETRY_LOG_ERR("Invalid unregister test failed");
808 TELEMETRY_LOG_INFO("Success - Invalid unregister test passed");
810 sockfd = rte_telemetry_dummy_client_socket(valid_client_path);
812 TELEMETRY_LOG_ERR("Test socket creation failed");
816 ret = rte_telemetry_register_client(static_telemetry, valid_client_path);
818 TELEMETRY_LOG_ERR("Valid register test failed: %i", ret);
822 accept(sockfd, NULL, NULL);
823 TELEMETRY_LOG_INFO("Success - Valid register test passed");
825 ret = rte_telemetry_register_client(static_telemetry, valid_client_path);
826 if (ret != -EINVAL) {
827 TELEMETRY_LOG_ERR("Invalid register test failed: %i", ret);
831 TELEMETRY_LOG_INFO("Success - Invalid register test passed");
833 ret = rte_telemetry_unregister_client(static_telemetry,
834 invalid_client_path);
836 TELEMETRY_LOG_ERR("Invalid unregister test failed: %i", ret);
840 TELEMETRY_LOG_INFO("Success - Invalid unregister test passed");
842 ret = rte_telemetry_unregister_client(static_telemetry, valid_client_path);
844 TELEMETRY_LOG_ERR("Valid unregister test failed: %i", ret);
848 TELEMETRY_LOG_INFO("Success - Valid unregister test passed");
850 ret = rte_telemetry_cleanup();
852 TELEMETRY_LOG_ERR("Cleanup test failed");
856 TELEMETRY_LOG_INFO("Success - Valid cleanup test passed");
862 rte_telemetry_socket_messaging_testing(int index, int socket)
864 struct telemetry_impl *telemetry = calloc(1, sizeof(telemetry_impl));
865 int fd, bad_send_fd, send_fd, bad_fd, bad_recv_fd, recv_fd, ret;
867 if (telemetry == NULL) {
868 TELEMETRY_LOG_ERR("Could not initialize Telemetry API");
872 telemetry->server_fd = socket;
873 telemetry->reg_index[0] = index;
874 TELEMETRY_LOG_INFO("Beginning Telemetry socket message Selftest");
875 rte_telemetry_socket_test_setup(telemetry, &send_fd, &recv_fd);
876 TELEMETRY_LOG_INFO("Register valid client test");
878 ret = rte_telemetry_socket_register_test(telemetry, &fd, send_fd,
881 TELEMETRY_LOG_ERR("Register valid client test failed!");
886 TELEMETRY_LOG_INFO("Success - Register valid client test passed!");
888 TELEMETRY_LOG_INFO("Register invalid/same client test");
889 ret = rte_telemetry_socket_test_setup(telemetry, &bad_send_fd,
891 ret = rte_telemetry_socket_register_test(telemetry, &bad_fd,
892 bad_send_fd, bad_recv_fd);
894 TELEMETRY_LOG_ERR("Register invalid/same client test failed!");
899 TELEMETRY_LOG_INFO("Success - Register invalid/same client test passed!");
901 ret = rte_telemetry_json_socket_message_test(telemetry, fd);
912 rte_telemetry_socket_register_test(struct telemetry_impl *telemetry, int *fd,
913 int send_fd, int recv_fd)
916 char good_req_string[BUF_SIZE];
918 snprintf(good_req_string, sizeof(good_req_string),
919 "{\"action\":1,\"command\":\"clients\",\"data\":{\"client_path\""
920 ":\"%s\"}}", SOCKET_TEST_CLIENT_PATH);
924 ret = send(send_fd, good_req_string, strlen(good_req_string), 0);
926 TELEMETRY_LOG_ERR("Could not send message over socket");
930 rte_telemetry_run(telemetry);
932 if (telemetry->register_fail_count != 0)
935 *fd = accept(recv_fd, NULL, NULL);
941 rte_telemetry_socket_test_setup(struct telemetry_impl *telemetry, int *send_fd,
945 const char *client_path = SOCKET_TEST_CLIENT_PATH;
946 char socket_path[BUF_SIZE];
947 struct sockaddr_un addr = {0};
948 struct sockaddr_un addrs = {0};
949 *send_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
950 *recv_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
952 listen(telemetry->server_fd, 5);
953 addr.sun_family = AF_UNIX;
954 rte_telemetry_get_runtime_dir(socket_path, sizeof(socket_path));
955 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
957 ret = connect(*send_fd, (struct sockaddr *) &addr, sizeof(addr));
959 TELEMETRY_LOG_ERR("Could not connect socket");
963 telemetry->accept_fd = accept(telemetry->server_fd, NULL, NULL);
965 addrs.sun_family = AF_UNIX;
966 strlcpy(addrs.sun_path, client_path, sizeof(addrs.sun_path));
969 ret = bind(*recv_fd, (struct sockaddr *)&addrs, sizeof(addrs));
971 TELEMETRY_LOG_ERR("Could not bind socket");
979 rte_telemetry_stat_parse(char *buf, struct json_data *json_data_struct)
982 json_t *root = json_loads(buf, 0, &error);
984 json_t *status, *dataArray, *port, *stats, *name, *value, *dataArrayObj,
992 TELEMETRY_LOG_ERR("JSON message is NULL");
997 TELEMETRY_LOG_ERR("Could not load JSON object from data passed in : %s",
1000 } else if (!json_is_object(root)) {
1001 TELEMETRY_LOG_ERR("JSON Request is not a JSON object");
1006 status = json_object_get(root, "status_code");
1008 TELEMETRY_LOG_ERR("Request does not have status field");
1010 } else if (!json_is_string(status)) {
1011 TELEMETRY_LOG_ERR("Status value is not a string");
1015 json_data_struct->status_code = strdup(json_string_value(status));
1017 dataArray = json_object_get(root, "data");
1018 if (dataArray == NULL) {
1019 TELEMETRY_LOG_ERR("Request does not have data field");
1023 arraylen = json_array_size(dataArray);
1024 if (arraylen == 0) {
1025 json_data_struct->data = "null";
1029 for (i = 0; i < arraylen; i++) {
1030 dataArrayObj = json_array_get(dataArray, i);
1031 port = json_object_get(dataArrayObj, "port");
1032 stats = json_object_get(dataArrayObj, "stats");
1036 TELEMETRY_LOG_ERR("Request does not have port field");
1040 if (!json_is_integer(port)) {
1041 TELEMETRY_LOG_ERR("Port value is not an integer");
1045 json_data_struct->port = json_integer_value(port);
1047 if (stats == NULL) {
1048 TELEMETRY_LOG_ERR("Request does not have stats field");
1052 arraylen = json_array_size(stats);
1053 for (i = 0; i < arraylen; i++) {
1054 statsArrayObj = json_array_get(stats, i);
1055 name = json_object_get(statsArrayObj, "name");
1056 value = json_object_get(statsArrayObj, "value");
1060 TELEMETRY_LOG_ERR("Request does not have name field");
1064 if (!json_is_string(name)) {
1065 TELEMETRY_LOG_ERR("Stat name value is not a string");
1069 json_data_struct->stat_name = strdup(json_string_value(name));
1071 if (value == NULL) {
1072 TELEMETRY_LOG_ERR("Request does not have value field");
1076 if (!json_is_integer(value)) {
1077 TELEMETRY_LOG_ERR("Stat value is not an integer");
1081 json_data_struct->stat_value = json_integer_value(value);
1087 rte_telemetry_free_test_data(struct json_data *data)
1089 free(data->status_code);
1090 free(data->stat_name);
1095 rte_telemetry_valid_json_test(struct telemetry_impl *telemetry, int fd)
1101 int buffer_read = 0;
1103 struct json_data *data_struct;
1105 const char *status = "Status OK: 200";
1106 const char *name = "rx_good_packets";
1107 const char *valid_json_message = "{\"action\":0,\"command\":"
1108 "\"ports_stats_values_by_name\",\"data\":{\"ports\""
1109 ":[0],\"stats\":[\"rx_good_packets\"]}}";
1111 ret = send(fd, valid_json_message, strlen(valid_json_message), 0);
1113 TELEMETRY_LOG_ERR("Could not send message over socket");
1117 rte_telemetry_run(telemetry);
1118 buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
1120 if (buffer_read == -1) {
1121 TELEMETRY_LOG_ERR("Read error");
1125 buf[buffer_read] = '\0';
1126 data_struct = calloc(1, sizeof(struct json_data));
1127 ret = rte_telemetry_stat_parse(buf, data_struct);
1130 TELEMETRY_LOG_ERR("Could not parse stats");
1134 if (strcmp(data_struct->status_code, status) != 0) {
1135 TELEMETRY_LOG_ERR("Status code is invalid");
1139 if (data_struct->port != port) {
1140 TELEMETRY_LOG_ERR("Port is invalid");
1144 if (strcmp(data_struct->stat_name, name) != 0) {
1145 TELEMETRY_LOG_ERR("Stat name is invalid");
1149 if (data_struct->stat_value != value) {
1150 TELEMETRY_LOG_ERR("Stat value is invalid");
1154 rte_telemetry_free_test_data(data_struct);
1158 TELEMETRY_LOG_INFO("Success - Passed valid JSON message test passed");
1164 rte_telemetry_invalid_json_test(struct telemetry_impl *telemetry, int fd)
1169 const char *invalid_json = "{]";
1170 const char *status = "Status Error: Unknown";
1171 const char *data = "null";
1172 struct json_data *data_struct;
1173 int buffer_read = 0;
1176 ret = send(fd, invalid_json, strlen(invalid_json), 0);
1178 TELEMETRY_LOG_ERR("Could not send message over socket");
1182 rte_telemetry_run(telemetry);
1183 buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
1185 if (buffer_read == -1) {
1186 TELEMETRY_LOG_ERR("Read error");
1190 buf[buffer_read] = '\0';
1192 data_struct = calloc(1, sizeof(struct json_data));
1193 ret = rte_telemetry_stat_parse(buf, data_struct);
1196 TELEMETRY_LOG_ERR("Could not parse stats");
1198 if (strcmp(data_struct->status_code, status) != 0) {
1199 TELEMETRY_LOG_ERR("Status code is invalid");
1203 if (strcmp(data_struct->data, data) != 0) {
1204 TELEMETRY_LOG_ERR("Data status is invalid");
1208 rte_telemetry_free_test_data(data_struct);
1212 TELEMETRY_LOG_INFO("Success - Passed invalid JSON message test");
1218 rte_telemetry_json_contents_test(struct telemetry_impl *telemetry, int fd)
1223 const char *status = "Status Error: Invalid Argument 404";
1224 const char *data = "null";
1225 struct json_data *data_struct;
1226 const char *invalid_contents = "{\"action\":0,\"command\":"
1227 "\"ports_stats_values_by_name\",\"data\":{\"ports\""
1228 ":[0],\"stats\":[\"some_invalid_param\","
1229 "\"another_invalid_param\"]}}";
1230 int buffer_read = 0;
1233 ret = send(fd, invalid_contents, strlen(invalid_contents), 0);
1235 TELEMETRY_LOG_ERR("Could not send message over socket");
1239 rte_telemetry_run(telemetry);
1240 buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
1242 if (buffer_read == -1) {
1243 TELEMETRY_LOG_ERR("Read error");
1247 buf[buffer_read] = '\0';
1248 data_struct = calloc(1, sizeof(struct json_data));
1249 ret = rte_telemetry_stat_parse(buf, data_struct);
1252 TELEMETRY_LOG_ERR("Could not parse stats");
1254 if (strcmp(data_struct->status_code, status) != 0) {
1255 TELEMETRY_LOG_ERR("Status code is invalid");
1259 if (strcmp(data_struct->data, data) != 0) {
1260 TELEMETRY_LOG_ERR("Data status is invalid");
1264 rte_telemetry_free_test_data(data_struct);
1268 TELEMETRY_LOG_INFO("Success - Passed invalid JSON content test");
1274 rte_telemetry_json_empty_test(struct telemetry_impl *telemetry, int fd)
1279 const char *status = "Status Error: Invalid Argument 404";
1280 const char *data = "null";
1281 struct json_data *data_struct;
1282 const char *empty_json = "{}";
1283 int buffer_read = 0;
1286 ret = (send(fd, empty_json, strlen(empty_json), 0));
1288 TELEMETRY_LOG_ERR("Could not send message over socket");
1292 rte_telemetry_run(telemetry);
1293 buffer_read = recv(fd, buf, BUF_SIZE-1, 0);
1295 if (buffer_read == -1) {
1296 TELEMETRY_LOG_ERR("Read error");
1300 buf[buffer_read] = '\0';
1301 data_struct = calloc(1, sizeof(struct json_data));
1302 ret = rte_telemetry_stat_parse(buf, data_struct);
1305 TELEMETRY_LOG_ERR("Could not parse stats");
1307 if (strcmp(data_struct->status_code, status) != 0) {
1308 TELEMETRY_LOG_ERR("Status code is invalid");
1312 if (strcmp(data_struct->data, data) != 0) {
1313 TELEMETRY_LOG_ERR("Data status is invalid");
1317 rte_telemetry_free_test_data(data_struct);
1322 TELEMETRY_LOG_INFO("Success - Passed JSON empty message test");
1328 rte_telemetry_json_socket_message_test(struct telemetry_impl *telemetry, int fd)
1331 int ret, fail_count;
1334 struct telemetry_message_test socket_json_tests[] = {
1335 {.test_name = "Invalid JSON test",
1336 .test_func_ptr = rte_telemetry_invalid_json_test},
1337 {.test_name = "Valid JSON test",
1338 .test_func_ptr = rte_telemetry_valid_json_test},
1339 {.test_name = "JSON contents test",
1340 .test_func_ptr = rte_telemetry_json_contents_test},
1341 {.test_name = "JSON empty tests",
1342 .test_func_ptr = rte_telemetry_json_empty_test}
1345 #define NUM_TESTS RTE_DIM(socket_json_tests)
1347 for (i = 0; i < NUM_TESTS; i++) {
1348 TELEMETRY_LOG_INFO("%s", socket_json_tests[i].test_name);
1349 ret = (socket_json_tests[i].test_func_ptr)
1352 TELEMETRY_LOG_ERR("%s failed",
1353 socket_json_tests[i].test_name);
1358 if (fail_count > 0) {
1359 TELEMETRY_LOG_ERR("Failed %i JSON socket message test(s)",
1364 TELEMETRY_LOG_INFO("Success - All JSON tests passed");
1369 int telemetry_log_level;
1371 static struct rte_option option = {
1372 .name = "telemetry",
1373 .usage = "Enable telemetry backend",
1374 .cb = &rte_telemetry_init,
1378 RTE_INIT(rte_telemetry_register)
1380 telemetry_log_level = rte_log_register("lib.telemetry");
1381 if (telemetry_log_level >= 0)
1382 rte_log_set_level(telemetry_log_level, RTE_LOG_ERR);
1384 rte_option_register(&option);