New upstream version 18.11-rc1
[deb_dpdk.git] / lib / librte_telemetry / rte_telemetry_parser_test.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <jansson.h>
10 #include <sys/socket.h>
11 #include <sys/un.h>
12 #include <unistd.h>
13
14 #include <rte_common.h>
15 #include <rte_tailq.h>
16 #include <rte_string_fns.h>
17
18 #include "rte_telemetry_parser.h"
19
20 enum choices {
21         INV_ACTION_VAL,
22         INV_COMMAND_VAL,
23         INV_DATA_VAL,
24         INV_ACTION_FIELD,
25         INV_COMMAND_FIELD,
26         INV_DATA_FIELD,
27         INV_JSON_FORMAT,
28         VALID_REQ
29 };
30
31
32 #define TEST_CLIENT "/var/run/dpdk/test_client"
33
34 int32_t
35 rte_telemetry_create_test_socket(struct telemetry_impl *telemetry,
36         const char *test_client_path)
37 {
38         int ret, sockfd;
39         struct sockaddr_un addr = {0};
40         struct telemetry_client *client;
41
42         if (telemetry == NULL) {
43                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
44                 return -EINVAL;
45         }
46
47         sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
48         if (sockfd < 0) {
49                 TELEMETRY_LOG_ERR("Test socket creation failure");
50                 return -1;
51         }
52
53         addr.sun_family = AF_UNIX;
54         strlcpy(addr.sun_path, test_client_path, sizeof(addr.sun_path));
55         unlink(test_client_path);
56
57         if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
58                 TELEMETRY_LOG_ERR("Test socket binding failure");
59                 return -1;
60         }
61
62         if (listen(sockfd, 1) < 0) {
63                 TELEMETRY_LOG_ERR("Listen failure");
64                 return -1;
65         }
66
67         ret = rte_telemetry_register_client(telemetry, test_client_path);
68         if (ret < 0) {
69                 TELEMETRY_LOG_ERR("Register dummy client failed: %i", ret);
70                 return -1;
71         }
72
73         ret = accept(sockfd, NULL, NULL);
74         if (ret < 0) {
75                 TELEMETRY_LOG_ERR("Socket accept failed");
76                 return -1;
77         }
78
79         TAILQ_FOREACH(client, &telemetry->client_list_head, client_list)
80                 telemetry->request_client = client;
81
82         return 0;
83 }
84
85 int32_t
86 rte_telemetry_format_port_stat_ids(int *port_ids, int num_port_ids,
87         const char * const *stat_names, int num_stat_names, json_t **data)
88 {
89
90         int ret;
91         json_t *stat_names_json_array = NULL;
92         json_t *port_ids_json_array = NULL;
93         uint32_t i;
94
95         if (num_port_ids < 0) {
96                 TELEMETRY_LOG_ERR("Port Ids Count invalid");
97                 goto fail;
98         }
99
100         *data = json_object();
101         if (*data == NULL) {
102                 TELEMETRY_LOG_ERR("Data json object creation failed");
103                 goto fail;
104         }
105
106         port_ids_json_array = json_array();
107         if (port_ids_json_array == NULL) {
108                 TELEMETRY_LOG_ERR("port_ids_json_array creation failed");
109                 goto fail;
110         }
111
112         for (i = 0; i < (uint32_t)num_port_ids; i++) {
113                 ret = json_array_append(port_ids_json_array,
114                                 json_integer(port_ids[i]));
115                 if (ret < 0) {
116                         TELEMETRY_LOG_ERR("JSON array creation failed");
117                         goto fail;
118                 }
119         }
120
121         ret = json_object_set_new(*data, "ports", port_ids_json_array);
122         if (ret < 0) {
123                 TELEMETRY_LOG_ERR("Setting 'ports' value in data object failed");
124                 goto fail;
125         }
126
127         if (stat_names) {
128                 if (num_stat_names < 0) {
129                         TELEMETRY_LOG_ERR("Stat Names Count invalid");
130                         goto fail;
131                 }
132
133                 stat_names_json_array = json_array();
134                 if (stat_names_json_array == NULL) {
135                         TELEMETRY_LOG_ERR("stat_names_json_array creation failed");
136                         goto fail;
137                 }
138
139                 uint32_t i;
140                 for (i = 0; i < (uint32_t)num_stat_names; i++) {
141                         ret = json_array_append(stat_names_json_array,
142                                  json_string(stat_names[i]));
143                         if (ret < 0) {
144                                 TELEMETRY_LOG_ERR("JSON array creation failed");
145                                 goto fail;
146                         }
147                 }
148
149                 ret = json_object_set_new(*data, "stats", stat_names_json_array);
150                 if (ret < 0) {
151                         TELEMETRY_LOG_ERR("Setting 'stats' value in data object failed");
152                         goto fail;
153                 }
154         }
155
156         return 0;
157
158 fail:
159         if (*data)
160                 json_decref(*data);
161         if (stat_names_json_array)
162                 json_decref(stat_names_json_array);
163         if (port_ids_json_array)
164                 json_decref(port_ids_json_array);
165         return -1;
166 }
167
168 int32_t
169 rte_telemetry_create_json_request(int action, char *command,
170         const char *client_path, int *port_ids, int num_port_ids,
171         const char * const *stat_names, int num_stat_names, char **request,
172         int inv_choice)
173 {
174         int ret;
175         json_t *root = json_object();
176         json_t *data;
177
178         if (root == NULL) {
179                 TELEMETRY_LOG_ERR("Could not create root json object");
180                 goto fail;
181         }
182
183         if (inv_choice == INV_ACTION_FIELD) {
184                 ret = json_object_set_new(root, "ac--on", json_integer(action));
185                 if (ret < 0) {
186                         TELEMETRY_LOG_ERR("Setting invalid action field in root object failed");
187                         goto fail;
188                 }
189         } else {
190                 ret = json_object_set_new(root, "action", json_integer(action));
191                 if (ret < 0) {
192                         TELEMETRY_LOG_ERR("Setting valid action field in root object failed");
193                         goto fail;
194                 }
195         }
196
197         if (inv_choice == INV_COMMAND_FIELD) {
198                 ret = json_object_set_new(root, "co---nd", json_string(command));
199                 if (ret < 0) {
200                         TELEMETRY_LOG_ERR("Setting invalid command field in root object failed");
201                         goto fail;
202                 }
203         } else {
204                 ret = json_object_set_new(root, "command", json_string(command));
205                 if (ret < 0) {
206                         TELEMETRY_LOG_ERR("Setting valid command field in root object failed");
207                         goto fail;
208                 }
209         }
210
211         data = json_null();
212         if (client_path) {
213                 data = json_object();
214                 if (data == NULL) {
215                         TELEMETRY_LOG_ERR("Data json object creation failed");
216                         goto fail;
217                 }
218
219                 ret = json_object_set_new(data, "client_path",
220                                 json_string(client_path));
221                 if (ret < 0) {
222                         TELEMETRY_LOG_ERR("Setting valid client_path field in data object failed");
223                         goto fail;
224                 }
225
226         } else if (port_ids) {
227                 ret = rte_telemetry_format_port_stat_ids(port_ids, num_port_ids,
228                                 stat_names, num_stat_names, &data);
229                 if (ret < 0) {
230                         TELEMETRY_LOG_ERR("Formatting Port/Stat arrays failed");
231                         goto fail;
232                 }
233
234         }
235
236         if (inv_choice == INV_DATA_FIELD) {
237                 ret = json_object_set_new(root, "d--a", data);
238                 if (ret < 0) {
239                         TELEMETRY_LOG_ERR("Setting invalid data field in data object failed");
240                         goto fail;
241                 }
242         } else {
243                 ret = json_object_set_new(root, "data", data);
244                 if (ret < 0) {
245                         TELEMETRY_LOG_ERR("Setting valid data field in data object failed");
246                         goto fail;
247                 }
248         }
249
250         *request = json_dumps(root, 0);
251         if (*request == NULL) {
252                 TELEMETRY_LOG_ERR("Converting JSON root object to char* failed");
253                 goto fail;
254         }
255
256         json_decref(root);
257         return 0;
258
259 fail:
260         if (root)
261                 json_decref(root);
262         return -1;
263 }
264
265 int32_t
266 rte_telemetry_send_get_ports_and_stats_request(struct telemetry_impl *telemetry,
267         int action_choice, char *command_choice, int inv_choice)
268 {
269         int ret;
270         char *request;
271         char *client_path_data = NULL;
272
273         if (telemetry == NULL) {
274                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
275                 return -EINVAL;
276         }
277
278
279         if (inv_choice == INV_ACTION_VAL)
280                 action_choice = -1;
281         else if (inv_choice == INV_COMMAND_VAL)
282                 command_choice = "INVALID_COMMAND";
283         else if (inv_choice == INV_DATA_VAL)
284                 client_path_data = "INVALID_DATA";
285
286         ret = rte_telemetry_create_json_request(action_choice, command_choice,
287                 client_path_data, NULL, -1, NULL, -1, &request, inv_choice);
288         if (ret < 0) {
289                 TELEMETRY_LOG_ERR("Could not create JSON Request");
290                 return -1;
291         }
292
293         if (inv_choice == INV_JSON_FORMAT)
294                 request++;
295
296         ret = rte_telemetry_parse(telemetry, request);
297         if (ret < 0) {
298                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
299                 return -1;
300         }
301
302         return 0;
303 }
304
305 int32_t
306 rte_telemetry_send_get_ports_details_request(struct telemetry_impl *telemetry,
307         int action_choice, int *port_ids, int num_port_ids, int inv_choice)
308 {
309         int ret;
310         char *request;
311         if (telemetry == NULL) {
312                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
313                 return -EINVAL;
314         }
315
316         char *command = "ports_details";
317
318         if (inv_choice == INV_ACTION_VAL)
319                 action_choice = -1;
320         else if (inv_choice == INV_COMMAND_VAL)
321                 command = "INVALID_COMMAND";
322         else if (inv_choice == INV_DATA_VAL)
323                 port_ids = NULL;
324
325
326         ret = rte_telemetry_create_json_request(action_choice, command, NULL,
327                 port_ids, num_port_ids, NULL, -1, &request, inv_choice);
328         if (ret < 0) {
329                 TELEMETRY_LOG_ERR("Could not create JSON Request");
330                 return -1;
331         }
332
333         if (inv_choice == INV_JSON_FORMAT)
334                 request++;
335
336         ret = rte_telemetry_parse(telemetry, request);
337         if (ret < 0) {
338                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
339                 return -1;
340         }
341
342         return 0;
343 }
344
345 int32_t
346 rte_telemetry_send_stats_values_by_name_request(struct telemetry_impl
347         *telemetry, int action_choice, int *port_ids, int num_port_ids,
348         const char * const *stat_names, int num_stat_names,
349         int inv_choice)
350 {
351         int ret;
352         char *request;
353         char *command = "ports_stats_values_by_name";
354
355         if (telemetry == NULL) {
356                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
357                 return -EINVAL;
358         }
359
360         if (inv_choice == INV_ACTION_VAL)
361                 action_choice = -1;
362         else if (inv_choice == INV_COMMAND_VAL)
363                 command = "INVALID_COMMAND";
364         else if (inv_choice == INV_DATA_VAL) {
365                 port_ids = NULL;
366                 stat_names = NULL;
367         }
368
369         ret = rte_telemetry_create_json_request(action_choice, command, NULL,
370                 port_ids, num_port_ids, stat_names, num_stat_names, &request,
371                 inv_choice);
372         if (ret < 0) {
373                 TELEMETRY_LOG_ERR("Could not create JSON Request");
374                 return -1;
375         }
376
377         if (inv_choice == INV_JSON_FORMAT)
378                 request++;
379
380         ret = rte_telemetry_parse(telemetry, request);
381         if (ret < 0) {
382                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
383                 return -1;
384         }
385
386         return 0;
387 }
388
389 int32_t
390 rte_telemetry_send_unreg_request(struct telemetry_impl *telemetry,
391         int action_choice, const char *client_path, int inv_choice)
392 {
393         int ret;
394         char *request;
395
396         if (telemetry == NULL) {
397                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
398                 return -EINVAL;
399         }
400
401         char *command = "clients";
402
403         if (inv_choice == INV_ACTION_VAL)
404                 action_choice = -1;
405         else if (inv_choice == INV_COMMAND_VAL)
406                 command = "INVALID_COMMAND";
407         else if (inv_choice == INV_DATA_VAL)
408                 client_path = NULL;
409
410         ret = rte_telemetry_create_json_request(action_choice, command,
411                 client_path, NULL, -1, NULL, -1, &request, inv_choice);
412         if (ret < 0) {
413                 TELEMETRY_LOG_ERR("Could not create JSON Request");
414                 return -1;
415         }
416
417         if (inv_choice == INV_JSON_FORMAT)
418                 request++;
419
420         ret = rte_telemetry_parse(telemetry, request);
421         if (ret < 0) {
422                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
423                 return -1;
424         }
425
426         return 0;
427 }
428
429 int32_t
430 rte_telemetry_parser_test(struct telemetry_impl *telemetry)
431 {
432         int ret;
433         const char *client_path = TEST_CLIENT;
434
435         if (telemetry == NULL) {
436                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
437                 return -EINVAL;
438         }
439
440         ret = rte_telemetry_create_test_socket(telemetry, client_path);
441         if (ret < 0) {
442                 TELEMETRY_LOG_ERR("Could not create test request client socket");
443                 return -1;
444         }
445
446         int port_ids[] = {0, 1};
447         int num_port_ids = RTE_DIM(port_ids);
448
449         static const char * const stat_names[] = {"tx_good_packets",
450                 "rx_good_packets"};
451         int num_stat_names = RTE_DIM(stat_names);
452
453         static const char * const test_types[] = {
454                 "INVALID ACTION VALUE TESTS",
455                 "INVALID COMMAND VALUE TESTS",
456                 "INVALID DATA VALUE TESTS",
457                 "INVALID ACTION FIELD TESTS",
458                 "INVALID COMMAND FIELD TESTS",
459                 "INVALID DATA FIELD TESTS",
460                 "INVALID JSON FORMAT TESTS",
461                 "VALID TESTS"
462         };
463
464
465 #define NUM_TEST_TYPES (sizeof(test_types)/sizeof(const char * const))
466
467         uint32_t i;
468         for (i = 0; i < NUM_TEST_TYPES; i++) {
469                 TELEMETRY_LOG_INFO("%s", test_types[i]);
470
471                 ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
472                         ACTION_GET, "ports", i);
473                 if (ret != 0 && i == VALID_REQ) {
474                         TELEMETRY_LOG_ERR("Get ports valid test failed");
475                         return -EPERM;
476                 } else if (ret != -1 && i != VALID_REQ) {
477                         TELEMETRY_LOG_ERR("Get ports invalid test failed");
478                         return -EPERM;
479                 }
480
481                 TELEMETRY_LOG_INFO("Success - Get ports test passed");
482
483                 ret = rte_telemetry_send_get_ports_details_request(telemetry,
484                         ACTION_GET, port_ids, num_port_ids, i);
485                 if (ret != 0 && i == VALID_REQ) {
486                         TELEMETRY_LOG_ERR("Get ports details valid");
487                         return -EPERM;
488                 } else if (ret != -1 && i != VALID_REQ) {
489                         TELEMETRY_LOG_ERR("Get ports details invalid");
490                         return -EPERM;
491                 }
492
493                 TELEMETRY_LOG_INFO("Success - Get ports details test passed");
494
495                 ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
496                         ACTION_GET, "port_stats", i);
497                 if (ret != 0  && i == VALID_REQ) {
498                         TELEMETRY_LOG_ERR("Get port stats valid test");
499                         return -EPERM;
500                 } else if (ret != -1 && i != VALID_REQ) {
501                         TELEMETRY_LOG_ERR("Get ports stats invalid test failed");
502                         return -EPERM;
503                 }
504
505                 TELEMETRY_LOG_INFO("Success - Get ports stats test passed");
506
507                 ret = rte_telemetry_send_stats_values_by_name_request(telemetry,
508                         ACTION_GET, port_ids, num_port_ids, stat_names,
509                         num_stat_names, i);
510                 if (ret != 0 && i == VALID_REQ) {
511                         TELEMETRY_LOG_ERR("Get ports stats values by name valid test failed");
512                         return -EPERM;
513                 } else if (ret != -1 && i != VALID_REQ) {
514                         TELEMETRY_LOG_ERR("Get ports stats values by name invalid test failed");
515                         return -EPERM;
516                 }
517
518                 TELEMETRY_LOG_INFO("Success - Get ports stats values by name test passed");
519
520                 ret = rte_telemetry_send_unreg_request(telemetry, ACTION_DELETE,
521                         client_path, i);
522                 if (ret != 0 && i == VALID_REQ) {
523                         TELEMETRY_LOG_ERR("Deregister valid test failed");
524                         return -EPERM;
525                 } else if (ret != -1 && i != VALID_REQ) {
526                         TELEMETRY_LOG_ERR("Deregister invalid test failed");
527                         return -EPERM;
528                 }
529
530                 TELEMETRY_LOG_INFO("Success - Deregister test passed");
531         }
532
533         return 0;
534 }