xref: /dpdk/app/test/test_telemetry_data.c (revision 97b914f4e715565d53d38ac6e04815b9be5e58a9)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Intel Corporation
3  */
4 
5 #include <string.h>
6 #include <sys/socket.h>
7 #ifndef RTE_EXEC_ENV_WINDOWS
8 #include <sys/un.h>
9 #endif
10 #include <unistd.h>
11 #include <limits.h>
12 
13 #include <rte_eal.h>
14 #include <rte_common.h>
15 #include <rte_telemetry.h>
16 #include <rte_string_fns.h>
17 
18 #include "test.h"
19 #include "telemetry_data.h"
20 
21 #define TELEMETRY_VERSION "v2"
22 #define REQUEST_CMD "/test"
23 #define BUF_SIZE 1024
24 #define TEST_OUTPUT(exp) test_output(__func__, exp)
25 
26 static struct rte_tel_data response_data;
27 static int sock;
28 
29 /*
30  * This function is the callback registered with Telemetry to be used when
31  * the /test command is requested. This callback returns the global data built
32  * up by the individual test cases.
33  */
34 static int
35 test_cb(const char *cmd __rte_unused, const char *params __rte_unused,
36 		struct rte_tel_data *d)
37 {
38 	*d = response_data;
39 	return 0;
40 }
41 
42 /*
43  * This function is called by each test case function. It communicates with
44  * the telemetry socket by requesting the /test command, and reading the
45  * response. The expected response is passed in by the test case function,
46  * and is compared to the actual response received from Telemetry.
47  */
48 static int
49 test_output(const char *func_name, const char *expected)
50 {
51 	int bytes;
52 	char buf[BUF_SIZE * 16];
53 	if (write(sock, REQUEST_CMD, strlen(REQUEST_CMD)) < 0) {
54 		printf("%s: Error with socket write - %s\n", __func__,
55 				strerror(errno));
56 		return -1;
57 	}
58 	bytes = read(sock, buf, sizeof(buf) - 1);
59 	if (bytes < 0) {
60 		printf("%s: Error with socket read - %s\n", __func__,
61 				strerror(errno));
62 		return -1;
63 	}
64 	buf[bytes] = '\0';
65 	printf("%s: buf = '%s', expected = '%s'\n", func_name, buf, expected);
66 	return strncmp(expected, buf, sizeof(buf));
67 }
68 
69 static int
70 test_dict_with_array_int_values(void)
71 {
72 	int i;
73 
74 	struct rte_tel_data *child_data = rte_tel_data_alloc();
75 	rte_tel_data_start_array(child_data, RTE_TEL_INT_VAL);
76 
77 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
78 	rte_tel_data_start_array(child_data2, RTE_TEL_INT_VAL);
79 
80 	memset(&response_data, 0, sizeof(response_data));
81 	rte_tel_data_start_dict(&response_data);
82 
83 	for (i = 0; i < 5; i++) {
84 		rte_tel_data_add_array_int(child_data, i);
85 		rte_tel_data_add_array_int(child_data2, i);
86 	}
87 
88 	rte_tel_data_add_dict_container(&response_data, "dict_0",
89 	 child_data, 0);
90 	rte_tel_data_add_dict_container(&response_data, "dict_1",
91 	 child_data2, 0);
92 
93 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":[0,1,2,3,4],"
94 			"\"dict_1\":[0,1,2,3,4]}}");
95 }
96 
97 static int
98 test_array_with_array_int_values(void)
99 {
100 	int i;
101 
102 	struct rte_tel_data *child_data = rte_tel_data_alloc();
103 	rte_tel_data_start_array(child_data, RTE_TEL_INT_VAL);
104 
105 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
106 	rte_tel_data_start_array(child_data2, RTE_TEL_INT_VAL);
107 
108 	memset(&response_data, 0, sizeof(response_data));
109 	rte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);
110 
111 	for (i = 0; i < 5; i++) {
112 		rte_tel_data_add_array_int(child_data, i);
113 		rte_tel_data_add_array_int(child_data2, i);
114 	}
115 	rte_tel_data_add_array_container(&response_data, child_data, 0);
116 	rte_tel_data_add_array_container(&response_data, child_data2, 0);
117 
118 	return TEST_OUTPUT("{\"/test\":[[0,1,2,3,4],[0,1,2,3,4]]}");
119 }
120 
121 static int
122 test_case_array_int(void)
123 {
124 	int i;
125 	memset(&response_data, 0, sizeof(response_data));
126 	rte_tel_data_start_array(&response_data, RTE_TEL_INT_VAL);
127 	for (i = 0; i < 5; i++)
128 		rte_tel_data_add_array_int(&response_data, i);
129 	return TEST_OUTPUT("{\"/test\":[0,1,2,3,4]}");
130 }
131 
132 static int
133 test_case_add_dict_int(void)
134 {
135 	int i = 0;
136 	char name_of_value[8];
137 
138 	memset(&response_data, 0, sizeof(response_data));
139 	rte_tel_data_start_dict(&response_data);
140 
141 	for (i = 0; i < 5; i++) {
142 		sprintf(name_of_value, "dict_%d", i);
143 		rte_tel_data_add_dict_int(&response_data, name_of_value, i);
144 	}
145 
146 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":0,\"dict_1\":1,\"dict_2\":2,"
147 			"\"dict_3\":3,\"dict_4\":4}}");
148 }
149 
150 static int
151 test_case_array_string(void)
152 {
153 	memset(&response_data, 0, sizeof(response_data));
154 	rte_tel_data_start_array(&response_data, RTE_TEL_STRING_VAL);
155 	rte_tel_data_add_array_string(&response_data, "aaaa");
156 	rte_tel_data_add_array_string(&response_data, "bbbb");
157 	rte_tel_data_add_array_string(&response_data, "cccc");
158 	rte_tel_data_add_array_string(&response_data, "dddd");
159 	rte_tel_data_add_array_string(&response_data, "eeee");
160 
161 	return TEST_OUTPUT("{\"/test\":[\"aaaa\",\"bbbb\",\"cccc\",\"dddd\","
162 			"\"eeee\"]}");
163 }
164 
165 static int
166 test_case_add_dict_string(void)
167 {
168 	memset(&response_data, 0, sizeof(response_data));
169 	rte_tel_data_start_dict(&response_data);
170 
171 	rte_tel_data_add_dict_string(&response_data, "dict_0", "aaaa");
172 	rte_tel_data_add_dict_string(&response_data, "dict_1", "bbbb");
173 	rte_tel_data_add_dict_string(&response_data, "dict_2", "cccc");
174 	rte_tel_data_add_dict_string(&response_data, "dict_3", "dddd");
175 
176 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":\"aaaa\",\"dict_1\":"
177 			"\"bbbb\",\"dict_2\":\"cccc\",\"dict_3\":\"dddd\"}}");
178 }
179 
180 
181 static int
182 test_dict_with_array_string_values(void)
183 {
184 	struct rte_tel_data *child_data = rte_tel_data_alloc();
185 	rte_tel_data_start_array(child_data, RTE_TEL_STRING_VAL);
186 
187 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
188 	rte_tel_data_start_array(child_data2, RTE_TEL_STRING_VAL);
189 
190 	memset(&response_data, 0, sizeof(response_data));
191 	rte_tel_data_start_dict(&response_data);
192 
193 	rte_tel_data_add_array_string(child_data, "aaaa");
194 	rte_tel_data_add_array_string(child_data2, "bbbb");
195 
196 	rte_tel_data_add_dict_container(&response_data, "dict_0",
197 	 child_data, 0);
198 	rte_tel_data_add_dict_container(&response_data, "dict_1",
199 	 child_data2, 0);
200 
201 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":[\"aaaa\"],\"dict_1\":"
202 			"[\"bbbb\"]}}");
203 }
204 
205 static int
206 test_dict_with_dict_values(void)
207 {
208 	struct rte_tel_data *dict_of_dicts = rte_tel_data_alloc();
209 	rte_tel_data_start_dict(dict_of_dicts);
210 
211 	struct rte_tel_data *child_data = rte_tel_data_alloc();
212 	rte_tel_data_start_array(child_data, RTE_TEL_STRING_VAL);
213 
214 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
215 	rte_tel_data_start_array(child_data2, RTE_TEL_STRING_VAL);
216 
217 	memset(&response_data, 0, sizeof(response_data));
218 	rte_tel_data_start_dict(&response_data);
219 
220 	rte_tel_data_add_array_string(child_data, "aaaa");
221 	rte_tel_data_add_array_string(child_data2, "bbbb");
222 	rte_tel_data_add_dict_container(dict_of_dicts, "dict_0",
223 			child_data, 0);
224 	rte_tel_data_add_dict_container(dict_of_dicts, "dict_1",
225 			child_data2, 0);
226 	rte_tel_data_add_dict_container(&response_data, "dict_of_dicts",
227 			dict_of_dicts, 0);
228 
229 	return TEST_OUTPUT("{\"/test\":{\"dict_of_dicts\":{\"dict_0\":"
230 			"[\"aaaa\"],\"dict_1\":[\"bbbb\"]}}}");
231 }
232 
233 static int
234 test_array_with_array_string_values(void)
235 {
236 	struct rte_tel_data *child_data = rte_tel_data_alloc();
237 	rte_tel_data_start_array(child_data, RTE_TEL_STRING_VAL);
238 
239 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
240 	rte_tel_data_start_array(child_data2, RTE_TEL_STRING_VAL);
241 
242 	memset(&response_data, 0, sizeof(response_data));
243 	rte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);
244 
245 	rte_tel_data_add_array_string(child_data, "aaaa");
246 	rte_tel_data_add_array_string(child_data2, "bbbb");
247 
248 	rte_tel_data_add_array_container(&response_data, child_data, 0);
249 	rte_tel_data_add_array_container(&response_data, child_data2, 0);
250 
251 	return TEST_OUTPUT("{\"/test\":[[\"aaaa\"],[\"bbbb\"]]}");
252 }
253 
254 static int
255 test_case_array_u64(void)
256 {
257 	int i;
258 	memset(&response_data, 0, sizeof(response_data));
259 	rte_tel_data_start_array(&response_data, RTE_TEL_U64_VAL);
260 	for (i = 0; i < 5; i++)
261 		rte_tel_data_add_array_u64(&response_data, i);
262 	return TEST_OUTPUT("{\"/test\":[0,1,2,3,4]}");
263 }
264 
265 static int
266 test_case_add_dict_u64(void)
267 {
268 	int i = 0;
269 	char name_of_value[8];
270 
271 	memset(&response_data, 0, sizeof(response_data));
272 	rte_tel_data_start_dict(&response_data);
273 
274 	for (i = 0; i < 5; i++) {
275 		sprintf(name_of_value, "dict_%d", i);
276 		rte_tel_data_add_dict_u64(&response_data, name_of_value, i);
277 	}
278 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":0,\"dict_1\":1,\"dict_2\":2,"
279 			"\"dict_3\":3,\"dict_4\":4}}");
280 }
281 
282 static int
283 test_dict_with_array_u64_values(void)
284 {
285 	int i;
286 
287 	struct rte_tel_data *child_data = rte_tel_data_alloc();
288 	rte_tel_data_start_array(child_data, RTE_TEL_U64_VAL);
289 
290 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
291 	rte_tel_data_start_array(child_data2, RTE_TEL_U64_VAL);
292 
293 	memset(&response_data, 0, sizeof(response_data));
294 	rte_tel_data_start_dict(&response_data);
295 
296 	for (i = 0; i < 10; i++) {
297 		rte_tel_data_add_array_u64(child_data, i);
298 		rte_tel_data_add_array_u64(child_data2, i);
299 	}
300 
301 	rte_tel_data_add_dict_container(&response_data, "dict_0",
302 	 child_data, 0);
303 	rte_tel_data_add_dict_container(&response_data, "dict_1",
304 	 child_data2, 0);
305 
306 	return TEST_OUTPUT("{\"/test\":{\"dict_0\":[0,1,2,3,4,5,6,7,8,9],"
307 			"\"dict_1\":[0,1,2,3,4,5,6,7,8,9]}}");
308 }
309 
310 static int
311 test_array_with_array_u64_values(void)
312 {
313 	int i;
314 
315 	struct rte_tel_data *child_data = rte_tel_data_alloc();
316 	rte_tel_data_start_array(child_data, RTE_TEL_U64_VAL);
317 
318 	struct rte_tel_data *child_data2 = rte_tel_data_alloc();
319 	rte_tel_data_start_array(child_data2, RTE_TEL_U64_VAL);
320 
321 	memset(&response_data, 0, sizeof(response_data));
322 	rte_tel_data_start_array(&response_data, RTE_TEL_CONTAINER);
323 
324 	for (i = 0; i < 5; i++) {
325 		rte_tel_data_add_array_u64(child_data, i);
326 		rte_tel_data_add_array_u64(child_data2, i);
327 	}
328 	rte_tel_data_add_array_container(&response_data, child_data, 0);
329 	rte_tel_data_add_array_container(&response_data, child_data2, 0);
330 
331 	return TEST_OUTPUT("{\"/test\":[[0,1,2,3,4],[0,1,2,3,4]]}");
332 }
333 
334 static int
335 connect_to_socket(void)
336 {
337 	char buf[BUF_SIZE];
338 	int sock, bytes;
339 	struct sockaddr_un telem_addr;
340 
341 	sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
342 	if (sock < 0) {
343 		printf("\n%s: Error creating socket: %s\n", __func__,
344 				strerror(errno));
345 		return -1;
346 	}
347 	telem_addr.sun_family = AF_UNIX;
348 	snprintf(telem_addr.sun_path, sizeof(telem_addr.sun_path),
349 			"%s/dpdk_telemetry.%s",	rte_eal_get_runtime_dir(),
350 			TELEMETRY_VERSION);
351 	if (connect(sock, (struct sockaddr *) &telem_addr,
352 			sizeof(telem_addr)) < 0) {
353 		printf("\n%s: Error connecting to socket: %s\n", __func__,
354 				strerror(errno));
355 		close(sock);
356 		return -1;
357 	}
358 
359 	bytes = read(sock, buf, sizeof(buf) - 1);
360 	if (bytes < 0) {
361 		printf("%s: Error with socket read - %s\n", __func__,
362 				strerror(errno));
363 		close(sock);
364 		return -1;
365 	}
366 	buf[bytes] = '\0';
367 	printf("\n%s: %s\n", __func__, buf);
368 	return sock;
369 }
370 
371 static int
372 test_telemetry_data(void)
373 {
374 	typedef int (*test_case)(void);
375 	unsigned int i = 0;
376 
377 	sock = connect_to_socket();
378 	if (sock <= 0)
379 		return -1;
380 
381 	test_case test_cases[] = {test_case_array_string,
382 			test_case_array_int, test_case_array_u64,
383 			test_case_add_dict_int, test_case_add_dict_u64,
384 			test_case_add_dict_string,
385 			test_dict_with_array_int_values,
386 			test_dict_with_array_u64_values,
387 			test_dict_with_array_string_values,
388 			test_dict_with_dict_values,
389 			test_array_with_array_int_values,
390 			test_array_with_array_u64_values,
391 			test_array_with_array_string_values };
392 
393 	rte_telemetry_register_cmd(REQUEST_CMD, test_cb, "Test");
394 	for (i = 0; i < RTE_DIM(test_cases); i++) {
395 		if (test_cases[i]() != 0) {
396 			close(sock);
397 			return -1;
398 		}
399 	}
400 	close(sock);
401 	return 0;
402 }
403 
404 REGISTER_TEST_COMMAND(telemetry_data_autotest, test_telemetry_data);
405