Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2020 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <inttypes.h>
6 : : #include <stdlib.h>
7 : : #include <time.h>
8 : :
9 : : #include <rte_byteorder.h>
10 : : #include <rte_common.h>
11 : : #include <rte_time.h>
12 : : #include <rte_trace.h>
13 : : #include <rte_version.h>
14 : :
15 : : #include "eal_trace.h"
16 : :
17 : : __rte_format_printf(2, 0)
18 : : static int
19 : 96348 : metadata_printf(char **str, const char *fmt, ...)
20 : : {
21 : : va_list ap;
22 : : int rc;
23 : :
24 : 96348 : *str = NULL;
25 : 96348 : va_start(ap, fmt);
26 : : rc = vasprintf(str, fmt, ap);
27 : 96348 : va_end(ap);
28 : :
29 : 96348 : return rc;
30 : : }
31 : :
32 : : static int
33 : 96348 : meta_copy(char **meta, int *offset, char *str, int rc)
34 : : {
35 : 96348 : int count = *offset;
36 : 96348 : char *ptr = *meta;
37 : :
38 [ + - ]: 96348 : if (rc < 0)
39 : : return rc;
40 : :
41 : 96348 : ptr = realloc(ptr, count + rc + 1);
42 [ - + ]: 96348 : if (ptr == NULL)
43 : 0 : goto free_str;
44 : :
45 : 96348 : memcpy(RTE_PTR_ADD(ptr, count), str, rc);
46 : 96348 : ptr[count + rc] = '\0';
47 : : count += rc;
48 : 96348 : free(str);
49 : :
50 : 96348 : *meta = ptr;
51 : 96348 : *offset = count;
52 : :
53 : 96348 : return rc;
54 : :
55 : : free_str:
56 : 0 : free(str);
57 : 0 : return -ENOMEM;
58 : : }
59 : :
60 : : static int
61 : 186 : meta_data_type_emit(char **meta, int *offset)
62 : : {
63 : 186 : char *str = NULL;
64 : : int rc;
65 : :
66 : 186 : 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 : 186 : 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 : 186 : meta_header_emit(char **meta, int *offset)
116 : : {
117 : 186 : struct trace *trace = trace_obj_get();
118 : : char uustr[RTE_UUID_STRLEN];
119 : 186 : char *str = NULL;
120 : : int rc;
121 : :
122 : 186 : rte_uuid_unparse(trace->uuid, uustr, RTE_UUID_STRLEN);
123 : 186 : 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 : 186 : return meta_copy(meta, offset, str, rc);
135 : : }
136 : :
137 : : static int
138 : 186 : meta_env_emit(char **meta, int *offset)
139 : : {
140 : 186 : char *str = NULL;
141 : : int rc;
142 : :
143 : 186 : rc = metadata_printf(&str,
144 : : "env {\n"
145 : : " dpdk_version = \"%s\";\n"
146 : : " tracer_name = \"dpdk\";\n"
147 : : "};\n\n", rte_version());
148 : 186 : return meta_copy(meta, offset, str, rc);
149 : : }
150 : :
151 : : static int
152 : 186 : meta_clock_pass1_emit(char **meta, int *offset)
153 : : {
154 : 186 : char *str = NULL;
155 : : int rc;
156 : :
157 : 186 : rc = metadata_printf(&str,
158 : : "clock {\n"
159 : : " name = \"dpdk\";\n"
160 : : " freq = ");
161 : 186 : return meta_copy(meta, offset, str, rc);
162 : : }
163 : :
164 : : static int
165 : 186 : meta_clock_pass2_emit(char **meta, int *offset)
166 : : {
167 : 186 : char *str = NULL;
168 : : int rc;
169 : :
170 : 186 : rc = metadata_printf(&str,
171 : : "%20"PRIu64";\n"
172 : : " offset_s =", 0);
173 : 186 : return meta_copy(meta, offset, str, rc);
174 : : }
175 : :
176 : : static int
177 : 186 : meta_clock_pass3_emit(char **meta, int *offset)
178 : : {
179 : 186 : char *str = NULL;
180 : : int rc;
181 : :
182 : 186 : rc = metadata_printf(&str,
183 : : "%20"PRIu64";\n"
184 : : " offset =", 0);
185 : 186 : return meta_copy(meta, offset, str, rc);
186 : : }
187 : :
188 : : static int
189 : 186 : meta_clock_pass4_emit(char **meta, int *offset)
190 : : {
191 : 186 : char *str = NULL;
192 : : int rc;
193 : :
194 : 186 : 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 : 186 : return meta_copy(meta, offset, str, rc);
202 : : }
203 : :
204 : : static int
205 : 186 : meta_stream_emit(char **meta, int *offset)
206 : : {
207 : 186 : char *str = NULL;
208 : : int rc;
209 : :
210 : 186 : 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 : 186 : return meta_copy(meta, offset, str, rc);
222 : : }
223 : :
224 : : static int
225 : 94860 : meta_event_emit(char **meta, int *offset, struct trace_point *tp)
226 : : {
227 : 94860 : char *str = NULL;
228 : : int rc;
229 : :
230 : 189720 : rc = metadata_printf(&str,
231 : : "event {\n"
232 : : " id = %d;\n"
233 : : " name = \"%s\";\n"
234 : : " fields := struct {\n"
235 : : "%s"
236 : : " };\n"
237 : 94860 : "};\n\n", trace_id_get(tp->handle), tp->name,
238 [ + + ]: 94860 : tp->ctf_field != NULL ? tp->ctf_field : "");
239 : 94860 : return meta_copy(meta, offset, str, rc);
240 : : }
241 : :
242 : : int
243 : 186 : trace_metadata_create(void)
244 : : {
245 : 186 : struct trace_point_head *tp_list = trace_list_head_get();
246 : 186 : struct trace *trace = trace_obj_get();
247 : : struct trace_point *tp;
248 : 186 : int rc, offset = 0;
249 : 186 : char *meta = NULL;
250 : :
251 : 186 : rc = meta_data_type_emit(&meta, &offset);
252 [ - + ]: 186 : if (rc < 0)
253 : 0 : goto fail;
254 : :
255 : 186 : rc = meta_header_emit(&meta, &offset);
256 [ - + ]: 186 : if (rc < 0)
257 : 0 : goto fail;
258 : :
259 : 186 : rc = meta_env_emit(&meta, &offset);
260 [ - + ]: 186 : if (rc < 0)
261 : 0 : goto fail;
262 : :
263 : 186 : rc = meta_clock_pass1_emit(&meta, &offset);
264 [ - + ]: 186 : if (rc < 0)
265 : 0 : goto fail;
266 : 186 : trace->ctf_meta_offset_freq = offset;
267 : :
268 : 186 : rc = meta_clock_pass2_emit(&meta, &offset);
269 [ - + ]: 186 : if (rc < 0)
270 : 0 : goto fail;
271 : 186 : trace->ctf_meta_offset_freq_off_s = offset;
272 : :
273 : 186 : rc = meta_clock_pass3_emit(&meta, &offset);
274 [ - + ]: 186 : if (rc < 0)
275 : 0 : goto fail;
276 : 186 : trace->ctf_meta_offset_freq_off = offset;
277 : :
278 : 186 : rc = meta_clock_pass4_emit(&meta, &offset);
279 [ - + ]: 186 : if (rc < 0)
280 : 0 : goto fail;
281 : :
282 : 186 : rc = meta_stream_emit(&meta, &offset);
283 [ - + ]: 186 : if (rc < 0)
284 : 0 : goto fail;
285 : :
286 [ + + ]: 95046 : STAILQ_FOREACH(tp, tp_list, next)
287 [ - + ]: 94860 : if (meta_event_emit(&meta, &offset, tp) < 0)
288 : 0 : goto fail;
289 : :
290 : 186 : trace->ctf_meta = meta;
291 : 186 : return 0;
292 : :
293 : 0 : fail:
294 : 0 : free(meta);
295 : 0 : return -EBADF;
296 : : }
297 : :
298 : : void
299 : 238 : trace_metadata_destroy(void)
300 : : {
301 : 238 : struct trace *trace = trace_obj_get();
302 : :
303 [ + + ]: 238 : if (trace->ctf_meta) {
304 : 186 : free(trace->ctf_meta);
305 : 186 : trace->ctf_meta = NULL;
306 : : }
307 : 238 : }
308 : :
309 : : static void
310 : 2 : meta_fix_freq(struct trace *trace, char *meta)
311 : : {
312 : : char *str;
313 : : int rc;
314 : :
315 : 2 : str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq);
316 : : rc = sprintf(str, "%20"PRIu64"", rte_get_timer_hz());
317 : 2 : str[rc] = ';';
318 : 2 : }
319 : :
320 : : static void
321 : 2 : meta_fix_freq_offset(struct trace *trace, char *meta)
322 : : {
323 : : uint64_t uptime_tickes_floor, uptime_ticks, freq, uptime_sec;
324 : : uint64_t offset, offset_s;
325 : : char *str;
326 : : int rc;
327 : :
328 : 2 : uptime_ticks = trace->uptime_ticks &
329 : : ((1ULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT) - 1);
330 : 2 : freq = rte_get_tsc_hz();
331 : 2 : uptime_tickes_floor = RTE_ALIGN_MUL_FLOOR(uptime_ticks, freq);
332 : :
333 : 2 : uptime_sec = uptime_tickes_floor / freq;
334 : 2 : offset_s = trace->epoch_sec - uptime_sec;
335 : :
336 : : offset = uptime_ticks - uptime_tickes_floor;
337 : 2 : offset += trace->epoch_nsec * (freq / NSEC_PER_SEC);
338 : :
339 : 2 : str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off_s);
340 : : rc = sprintf(str, "%20"PRIu64"", offset_s);
341 : 2 : str[rc] = ';';
342 : 2 : str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off);
343 : : rc = sprintf(str, "%20"PRIu64"", offset);
344 : 2 : str[rc] = ';';
345 : 2 : }
346 : :
347 : : static void
348 : : meta_fixup(struct trace *trace, char *meta)
349 : : {
350 : 2 : meta_fix_freq(trace, meta);
351 : 2 : meta_fix_freq_offset(trace, meta);
352 : : }
353 : :
354 : : int
355 : 4 : rte_trace_metadata_dump(FILE *f)
356 : : {
357 : 4 : struct trace *trace = trace_obj_get();
358 : 4 : char *ctf_meta = trace->ctf_meta;
359 : : int rc;
360 : :
361 [ + - ]: 4 : if (ctf_meta == NULL)
362 : : return -EINVAL;
363 : :
364 [ + + + - ]: 6 : if (!rte_atomic_load_explicit(&trace->ctf_fixup_done, rte_memory_order_seq_cst) &&
365 : : rte_get_timer_hz()) {
366 : : meta_fixup(trace, ctf_meta);
367 : 2 : rte_atomic_store_explicit(&trace->ctf_fixup_done, 1, rte_memory_order_seq_cst);
368 : : }
369 : :
370 : : rc = fprintf(f, "%s", ctf_meta);
371 : 4 : return rc < 0 ? rc : 0;
372 : : }
373 : :
374 : 450058 : char *trace_metadata_fixup_field(const char *field)
375 : : {
376 : 450058 : const char *ctf_reserved_words[] = {
377 : : "align",
378 : : "event",
379 : : };
380 : : unsigned int i;
381 : : char *out;
382 : : char *p;
383 : :
384 : : /* reserved keywords */
385 [ + + ]: 1347318 : for (i = 0; i < RTE_DIM(ctf_reserved_words); i++) {
386 [ + + ]: 899164 : if (strcmp(field, ctf_reserved_words[i]) != 0)
387 : : continue;
388 [ - + ]: 1904 : if (asprintf(&out, "_%s", ctf_reserved_words[i]) == -1)
389 : 0 : out = NULL;
390 : 1904 : return out;
391 : : }
392 : :
393 : : /* nothing to replace, return early */
394 [ + + + + ]: 448154 : if (strstr(field, ".") == NULL && strstr(field, "->") == NULL)
395 : : return NULL;
396 : :
397 : 74018 : out = strdup(field);
398 [ + - ]: 74018 : if (out == NULL)
399 : : return NULL;
400 : : p = out;
401 [ + + ]: 83300 : while ((p = strstr(p, ".")) != NULL) {
402 : 9282 : p[0] = '_';
403 : 9282 : p++;
404 : : }
405 : 74018 : p = out;
406 [ + + ]: 147560 : while ((p = strstr(p, "->")) != NULL) {
407 : 73542 : p[0] = '_';
408 : 73542 : p++;
409 : 73542 : memmove(p, p + 1, strlen(p));
410 : : }
411 : 74018 : return out;
412 : : }
|