xref: /dpdk/lib/eal/common/eal_common_trace_ctf.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2020 Marvell International Ltd.
3  */
4 
5 #include <inttypes.h>
6 #include <time.h>
7 
8 #include <rte_byteorder.h>
9 #include <rte_common.h>
10 #include <rte_time.h>
11 #include <rte_trace.h>
12 #include <rte_version.h>
13 
14 #include "eal_trace.h"
15 
16 __rte_format_printf(2, 0)
17 static int
18 metadata_printf(char **str, const char *fmt, ...)
19 {
20 	va_list ap;
21 	int rc;
22 
23 	*str = NULL;
24 	va_start(ap, fmt);
25 	rc = vasprintf(str, fmt, ap);
26 	va_end(ap);
27 
28 	return rc;
29 }
30 
31 static int
32 meta_copy(char **meta, int *offset, char *str, int rc)
33 {
34 	int count = *offset;
35 	char *ptr = *meta;
36 
37 	if (rc < 0)
38 		return rc;
39 
40 	ptr = realloc(ptr, count + rc + 1);
41 	if (ptr == NULL)
42 		goto free_str;
43 
44 	memcpy(RTE_PTR_ADD(ptr, count), str, rc);
45 	ptr[count + rc] = '\0';
46 	count += rc;
47 	free(str);
48 
49 	*meta = ptr;
50 	*offset = count;
51 
52 	return rc;
53 
54 free_str:
55 	if (str)
56 		free(str);
57 	return -ENOMEM;
58 }
59 
60 static int
61 meta_data_type_emit(char **meta, int *offset)
62 {
63 	char *str = NULL;
64 	int rc;
65 
66 	rc = metadata_printf(&str,
67 		"/* CTF 1.8 */\n"
68 		"typealias integer {size = 8; base = x;}:= uint8_t;\n"
69 		"typealias integer {size = 16; base = x;} := uint16_t;\n"
70 		"typealias integer {size = 32; base = x;} := uint32_t;\n"
71 		"typealias integer {size = 64; base = x;} := uint64_t;\n"
72 		"typealias integer {size = 8; signed = true;}  := int8_t;\n"
73 		"typealias integer {size = 16; signed = true;} := int16_t;\n"
74 		"typealias integer {size = 32; signed = true;} := int32_t;\n"
75 		"typealias integer {size = 64; signed = true;} := int64_t;\n"
76 #ifdef RTE_ARCH_64
77 		"typealias integer {size = 64; base = x;} := uintptr_t;\n"
78 #else
79 		"typealias integer {size = 32; base = x;} := uintptr_t;\n"
80 #endif
81 #ifdef RTE_ARCH_64
82 		"typealias integer {size = 64; base = x;} := long;\n"
83 #else
84 		"typealias integer {size = 32; base = x;} := long;\n"
85 #endif
86 		"typealias integer {size = 8; signed = false; encoding = ASCII; } := string_bounded_t;\n\n"
87 #ifdef RTE_ARCH_64
88 		"typealias integer {size = 64; base = x;} := size_t;\n"
89 #else
90 		"typealias integer {size = 32; base = x;} := size_t;\n"
91 #endif
92 		"typealias floating_point {\n"
93 		"    exp_dig = 8;\n"
94 		"    mant_dig = 24;\n"
95 		"} := float;\n\n"
96 		"typealias floating_point {\n"
97 		"    exp_dig = 11;\n"
98 		"    mant_dig = 53;\n"
99 		"} := double;\n\n");
100 
101 	return meta_copy(meta, offset, str, rc);
102 }
103 
104 static int
105 is_be(void)
106 {
107 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
108 	return 1;
109 #else
110 	return 0;
111 #endif
112 }
113 
114 static int
115 meta_header_emit(char **meta, int *offset)
116 {
117 	struct trace *trace = trace_obj_get();
118 	char uustr[RTE_UUID_STRLEN];
119 	char *str = NULL;
120 	int rc;
121 
122 	rte_uuid_unparse(trace->uuid, uustr, RTE_UUID_STRLEN);
123 	rc = metadata_printf(&str,
124 		"trace {\n"
125 		"    major = 1;\n"
126 		"    minor = 8;\n"
127 		"    uuid = \"%s\";\n"
128 		"    byte_order = %s;\n"
129 		"    packet.header := struct {\n"
130 		"	    uint32_t magic;\n"
131 		"	    uint8_t  uuid[16];\n"
132 		"    };\n"
133 		"};\n\n", uustr, is_be() ? "be" : "le");
134 	return meta_copy(meta, offset, str, rc);
135 }
136 
137 static int
138 meta_env_emit(char **meta, int *offset)
139 {
140 	char *str = NULL;
141 	int rc;
142 
143 	rc = metadata_printf(&str,
144 		"env {\n"
145 		"    dpdk_version = \"%s\";\n"
146 		"    tracer_name = \"dpdk\";\n"
147 		"};\n\n", rte_version());
148 	return meta_copy(meta, offset, str, rc);
149 }
150 
151 static int
152 meta_clock_pass1_emit(char **meta, int *offset)
153 {
154 	char *str = NULL;
155 	int rc;
156 
157 	rc = metadata_printf(&str,
158 		"clock {\n"
159 		"    name = \"dpdk\";\n"
160 		"    freq = ");
161 	return meta_copy(meta, offset, str, rc);
162 }
163 
164 static int
165 meta_clock_pass2_emit(char **meta, int *offset)
166 {
167 	char *str = NULL;
168 	int rc;
169 
170 	rc = metadata_printf(&str,
171 		"%20"PRIu64";\n"
172 		"    offset_s =", 0);
173 	return meta_copy(meta, offset, str, rc);
174 }
175 
176 static int
177 meta_clock_pass3_emit(char **meta, int *offset)
178 {
179 	char *str = NULL;
180 	int rc;
181 
182 	rc = metadata_printf(&str,
183 		"%20"PRIu64";\n"
184 		"    offset =", 0);
185 	return meta_copy(meta, offset, str, rc);
186 }
187 
188 static int
189 meta_clock_pass4_emit(char **meta, int *offset)
190 {
191 	char *str = NULL;
192 	int rc;
193 
194 	rc = metadata_printf(&str,
195 		"%20"PRIu64";\n};\n\n"
196 		"typealias integer {\n"
197 		"    size = 48; align = 1; signed = false;\n"
198 		"    map = clock.dpdk.value;\n"
199 		"} := uint48_clock_dpdk_t;\n\n", 0);
200 
201 	return meta_copy(meta, offset, str, rc);
202 }
203 
204 static int
205 meta_stream_emit(char **meta, int *offset)
206 {
207 	char *str = NULL;
208 	int rc;
209 
210 	rc = metadata_printf(&str,
211 		"stream {\n"
212 		"    packet.context := struct {\n"
213 		"         uint32_t cpu_id;\n"
214 		"         string_bounded_t name[32];\n"
215 		"    };\n"
216 		"    event.header := struct {\n"
217 		"          uint48_clock_dpdk_t timestamp;\n"
218 		"          uint16_t id;\n"
219 		"    } align(64);\n"
220 		"};\n\n");
221 	return meta_copy(meta, offset, str, rc);
222 }
223 
224 static int
225 meta_event_emit(char **meta, int *offset, struct trace_point *tp)
226 {
227 	char *str = NULL;
228 	int rc;
229 
230 	rc = metadata_printf(&str,
231 		"event {\n"
232 		"    id = %d;\n"
233 		"    name = \"%s\";\n"
234 		"    fields := struct {\n"
235 		"%s"
236 		"    };\n"
237 		"};\n\n", trace_id_get(tp->handle), tp->name,
238 		tp->ctf_field != NULL ? tp->ctf_field : "");
239 	return meta_copy(meta, offset, str, rc);
240 }
241 
242 int
243 trace_metadata_create(void)
244 {
245 	struct trace_point_head *tp_list = trace_list_head_get();
246 	struct trace *trace = trace_obj_get();
247 	struct trace_point *tp;
248 	int rc, offset = 0;
249 	char *meta = NULL;
250 
251 	rc = meta_data_type_emit(&meta, &offset);
252 	if (rc < 0)
253 		goto fail;
254 
255 	rc = meta_header_emit(&meta, &offset);
256 	if (rc < 0)
257 		goto fail;
258 
259 	rc = meta_env_emit(&meta, &offset);
260 	if (rc < 0)
261 		goto fail;
262 
263 	rc = meta_clock_pass1_emit(&meta, &offset);
264 	if (rc < 0)
265 		goto fail;
266 	trace->ctf_meta_offset_freq = offset;
267 
268 	rc = meta_clock_pass2_emit(&meta, &offset);
269 	if (rc < 0)
270 		goto fail;
271 	trace->ctf_meta_offset_freq_off_s = offset;
272 
273 	rc = meta_clock_pass3_emit(&meta, &offset);
274 	if (rc < 0)
275 		goto fail;
276 	trace->ctf_meta_offset_freq_off = offset;
277 
278 	rc = meta_clock_pass4_emit(&meta, &offset);
279 	if (rc < 0)
280 		goto fail;
281 
282 	rc = meta_stream_emit(&meta, &offset);
283 	if (rc < 0)
284 		goto fail;
285 
286 	STAILQ_FOREACH(tp, tp_list, next)
287 		if (meta_event_emit(&meta, &offset, tp) < 0)
288 			goto fail;
289 
290 	trace->ctf_meta = meta;
291 	return 0;
292 
293 fail:
294 	if (meta)
295 		free(meta);
296 	return -EBADF;
297 }
298 
299 void
300 trace_metadata_destroy(void)
301 {
302 	struct trace *trace = trace_obj_get();
303 
304 	if (trace->ctf_meta) {
305 		free(trace->ctf_meta);
306 		trace->ctf_meta = NULL;
307 	}
308 }
309 
310 static void
311 meta_fix_freq(struct trace *trace, char *meta)
312 {
313 	char *str;
314 	int rc;
315 
316 	str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq);
317 	rc = sprintf(str, "%20"PRIu64"", rte_get_timer_hz());
318 	str[rc] = ';';
319 }
320 
321 static void
322 meta_fix_freq_offset(struct trace *trace, char *meta)
323 {
324 	uint64_t uptime_tickes_floor, uptime_ticks, freq, uptime_sec;
325 	uint64_t offset, offset_s;
326 	char *str;
327 	int rc;
328 
329 	uptime_ticks = trace->uptime_ticks &
330 			((1ULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT) - 1);
331 	freq = rte_get_tsc_hz();
332 	uptime_tickes_floor = RTE_ALIGN_MUL_FLOOR(uptime_ticks, freq);
333 
334 	uptime_sec = uptime_tickes_floor / freq;
335 	offset_s = trace->epoch_sec - uptime_sec;
336 
337 	offset = uptime_ticks - uptime_tickes_floor;
338 	offset += trace->epoch_nsec * (freq / NSEC_PER_SEC);
339 
340 	str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off_s);
341 	rc = sprintf(str, "%20"PRIu64"", offset_s);
342 	str[rc] = ';';
343 	str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off);
344 	rc = sprintf(str, "%20"PRIu64"", offset);
345 	str[rc] = ';';
346 }
347 
348 static void
349 meta_fixup(struct trace *trace, char *meta)
350 {
351 	meta_fix_freq(trace, meta);
352 	meta_fix_freq_offset(trace, meta);
353 }
354 
355 int
356 rte_trace_metadata_dump(FILE *f)
357 {
358 	struct trace *trace = trace_obj_get();
359 	char *ctf_meta = trace->ctf_meta;
360 	int rc;
361 
362 	if (!rte_trace_is_enabled())
363 		return 0;
364 
365 	if (ctf_meta == NULL)
366 		return -EINVAL;
367 
368 	if (!__atomic_load_n(&trace->ctf_fixup_done, __ATOMIC_SEQ_CST) &&
369 				rte_get_timer_hz()) {
370 		meta_fixup(trace, ctf_meta);
371 		__atomic_store_n(&trace->ctf_fixup_done, 1, __ATOMIC_SEQ_CST);
372 	}
373 
374 	rc = fprintf(f, "%s", ctf_meta);
375 	return rc < 0 ? rc : 0;
376 }
377 
378 char *trace_metadata_fixup_field(const char *field)
379 {
380 	const char *ctf_reserved_words[] = {
381 		"align",
382 		"event",
383 	};
384 	unsigned int i;
385 	char *out;
386 	char *p;
387 
388 	/* reserved keywords */
389 	for (i = 0; i < RTE_DIM(ctf_reserved_words); i++) {
390 		if (strcmp(field, ctf_reserved_words[i]) != 0)
391 			continue;
392 		if (asprintf(&out, "_%s", ctf_reserved_words[i]) == -1)
393 			out = NULL;
394 		return out;
395 	}
396 
397 	/* nothing to replace, return early */
398 	if (strstr(field, ".") == NULL && strstr(field, "->") == NULL)
399 		return NULL;
400 
401 	out = strdup(field);
402 	if (out == NULL)
403 		return NULL;
404 	p = out;
405 	while ((p = strstr(p, ".")) != NULL) {
406 		p[0] = '_';
407 		p++;
408 	}
409 	p = out;
410 	while ((p = strstr(p, "->")) != NULL) {
411 		p[0] = '_';
412 		p++;
413 		memmove(p, p + 1, strlen(p));
414 	}
415 	return out;
416 }
417