99a2dd955f
There is no reason for the DPDK libraries to all have 'librte_' prefix on the directory names. This prefix makes the directory names longer and also makes it awkward to add features referring to individual libraries in the build - should the lib names be specified with or without the prefix. Therefore, we can just remove the library prefix and use the library's unique name as the directory name, i.e. 'eal' rather than 'librte_eal' Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
417 lines
8.4 KiB
C
417 lines
8.4 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(C) 2020 Marvell International Ltd.
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include <time.h>
|
|
|
|
#include <rte_byteorder.h>
|
|
#include <rte_common.h>
|
|
#include <rte_time.h>
|
|
#include <rte_trace.h>
|
|
#include <rte_version.h>
|
|
|
|
#include "eal_trace.h"
|
|
|
|
__rte_format_printf(2, 0)
|
|
static int
|
|
metadata_printf(char **str, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
int rc;
|
|
|
|
*str = NULL;
|
|
va_start(ap, fmt);
|
|
rc = vasprintf(str, fmt, ap);
|
|
va_end(ap);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int
|
|
meta_copy(char **meta, int *offset, char *str, int rc)
|
|
{
|
|
int count = *offset;
|
|
char *ptr = *meta;
|
|
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
ptr = realloc(ptr, count + rc + 1);
|
|
if (ptr == NULL)
|
|
goto free_str;
|
|
|
|
memcpy(RTE_PTR_ADD(ptr, count), str, rc);
|
|
ptr[count + rc] = '\0';
|
|
count += rc;
|
|
free(str);
|
|
|
|
*meta = ptr;
|
|
*offset = count;
|
|
|
|
return rc;
|
|
|
|
free_str:
|
|
if (str)
|
|
free(str);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static int
|
|
meta_data_type_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"/* CTF 1.8 */\n"
|
|
"typealias integer {size = 8; base = x;}:= uint8_t;\n"
|
|
"typealias integer {size = 16; base = x;} := uint16_t;\n"
|
|
"typealias integer {size = 32; base = x;} := uint32_t;\n"
|
|
"typealias integer {size = 64; base = x;} := uint64_t;\n"
|
|
"typealias integer {size = 8; signed = true;} := int8_t;\n"
|
|
"typealias integer {size = 16; signed = true;} := int16_t;\n"
|
|
"typealias integer {size = 32; signed = true;} := int32_t;\n"
|
|
"typealias integer {size = 64; signed = true;} := int64_t;\n"
|
|
#ifdef RTE_ARCH_64
|
|
"typealias integer {size = 64; base = x;} := uintptr_t;\n"
|
|
#else
|
|
"typealias integer {size = 32; base = x;} := uintptr_t;\n"
|
|
#endif
|
|
#ifdef RTE_ARCH_64
|
|
"typealias integer {size = 64; base = x;} := long;\n"
|
|
#else
|
|
"typealias integer {size = 32; base = x;} := long;\n"
|
|
#endif
|
|
"typealias integer {size = 8; signed = false; encoding = ASCII; } := string_bounded_t;\n\n"
|
|
#ifdef RTE_ARCH_64
|
|
"typealias integer {size = 64; base = x;} := size_t;\n"
|
|
#else
|
|
"typealias integer {size = 32; base = x;} := size_t;\n"
|
|
#endif
|
|
"typealias floating_point {\n"
|
|
" exp_dig = 8;\n"
|
|
" mant_dig = 24;\n"
|
|
"} := float;\n\n"
|
|
"typealias floating_point {\n"
|
|
" exp_dig = 11;\n"
|
|
" mant_dig = 53;\n"
|
|
"} := double;\n\n");
|
|
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
is_be(void)
|
|
{
|
|
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
|
return 1;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
meta_header_emit(char **meta, int *offset)
|
|
{
|
|
struct trace *trace = trace_obj_get();
|
|
char uustr[RTE_UUID_STRLEN];
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rte_uuid_unparse(trace->uuid, uustr, RTE_UUID_STRLEN);
|
|
rc = metadata_printf(&str,
|
|
"trace {\n"
|
|
" major = 1;\n"
|
|
" minor = 8;\n"
|
|
" uuid = \"%s\";\n"
|
|
" byte_order = %s;\n"
|
|
" packet.header := struct {\n"
|
|
" uint32_t magic;\n"
|
|
" uint8_t uuid[16];\n"
|
|
" };\n"
|
|
"};\n\n", uustr, is_be() ? "be" : "le");
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_env_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"env {\n"
|
|
" dpdk_version = \"%s\";\n"
|
|
" tracer_name = \"dpdk\";\n"
|
|
"};\n\n", rte_version());
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_clock_pass1_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"clock {\n"
|
|
" name = \"dpdk\";\n"
|
|
" freq = ");
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_clock_pass2_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"%20"PRIu64";\n"
|
|
" offset_s =", 0);
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_clock_pass3_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"%20"PRIu64";\n"
|
|
" offset =", 0);
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_clock_pass4_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"%20"PRIu64";\n};\n\n"
|
|
"typealias integer {\n"
|
|
" size = 48; align = 1; signed = false;\n"
|
|
" map = clock.dpdk.value;\n"
|
|
"} := uint48_clock_dpdk_t;\n\n", 0);
|
|
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_stream_emit(char **meta, int *offset)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"stream {\n"
|
|
" packet.context := struct {\n"
|
|
" uint32_t cpu_id;\n"
|
|
" string_bounded_t name[32];\n"
|
|
" };\n"
|
|
" event.header := struct {\n"
|
|
" uint48_clock_dpdk_t timestamp;\n"
|
|
" uint16_t id;\n"
|
|
" } align(64);\n"
|
|
"};\n\n");
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
static int
|
|
meta_event_emit(char **meta, int *offset, struct trace_point *tp)
|
|
{
|
|
char *str = NULL;
|
|
int rc;
|
|
|
|
rc = metadata_printf(&str,
|
|
"event {\n"
|
|
" id = %d;\n"
|
|
" name = \"%s\";\n"
|
|
" fields := struct {\n"
|
|
"%s"
|
|
" };\n"
|
|
"};\n\n", trace_id_get(tp->handle), tp->name,
|
|
tp->ctf_field != NULL ? tp->ctf_field : "");
|
|
return meta_copy(meta, offset, str, rc);
|
|
}
|
|
|
|
int
|
|
trace_metadata_create(void)
|
|
{
|
|
struct trace_point_head *tp_list = trace_list_head_get();
|
|
struct trace *trace = trace_obj_get();
|
|
struct trace_point *tp;
|
|
int rc, offset = 0;
|
|
char *meta = NULL;
|
|
|
|
rc = meta_data_type_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
|
|
rc = meta_header_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
|
|
rc = meta_env_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
|
|
rc = meta_clock_pass1_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
trace->ctf_meta_offset_freq = offset;
|
|
|
|
rc = meta_clock_pass2_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
trace->ctf_meta_offset_freq_off_s = offset;
|
|
|
|
rc = meta_clock_pass3_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
trace->ctf_meta_offset_freq_off = offset;
|
|
|
|
rc = meta_clock_pass4_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
|
|
rc = meta_stream_emit(&meta, &offset);
|
|
if (rc < 0)
|
|
goto fail;
|
|
|
|
STAILQ_FOREACH(tp, tp_list, next)
|
|
if (meta_event_emit(&meta, &offset, tp) < 0)
|
|
goto fail;
|
|
|
|
trace->ctf_meta = meta;
|
|
return 0;
|
|
|
|
fail:
|
|
if (meta)
|
|
free(meta);
|
|
return -EBADF;
|
|
}
|
|
|
|
void
|
|
trace_metadata_destroy(void)
|
|
{
|
|
struct trace *trace = trace_obj_get();
|
|
|
|
if (trace->ctf_meta) {
|
|
free(trace->ctf_meta);
|
|
trace->ctf_meta = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_fix_freq(struct trace *trace, char *meta)
|
|
{
|
|
char *str;
|
|
int rc;
|
|
|
|
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq);
|
|
rc = sprintf(str, "%20"PRIu64"", rte_get_timer_hz());
|
|
str[rc] = ';';
|
|
}
|
|
|
|
static void
|
|
meta_fix_freq_offset(struct trace *trace, char *meta)
|
|
{
|
|
uint64_t uptime_tickes_floor, uptime_ticks, freq, uptime_sec;
|
|
uint64_t offset, offset_s;
|
|
char *str;
|
|
int rc;
|
|
|
|
uptime_ticks = trace->uptime_ticks &
|
|
((1ULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT) - 1);
|
|
freq = rte_get_tsc_hz();
|
|
uptime_tickes_floor = RTE_ALIGN_MUL_FLOOR(uptime_ticks, freq);
|
|
|
|
uptime_sec = uptime_tickes_floor / freq;
|
|
offset_s = trace->epoch_sec - uptime_sec;
|
|
|
|
offset = uptime_ticks - uptime_tickes_floor;
|
|
offset += trace->epoch_nsec * (freq / NSEC_PER_SEC);
|
|
|
|
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off_s);
|
|
rc = sprintf(str, "%20"PRIu64"", offset_s);
|
|
str[rc] = ';';
|
|
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off);
|
|
rc = sprintf(str, "%20"PRIu64"", offset);
|
|
str[rc] = ';';
|
|
}
|
|
|
|
static void
|
|
meta_fixup(struct trace *trace, char *meta)
|
|
{
|
|
meta_fix_freq(trace, meta);
|
|
meta_fix_freq_offset(trace, meta);
|
|
}
|
|
|
|
int
|
|
rte_trace_metadata_dump(FILE *f)
|
|
{
|
|
struct trace *trace = trace_obj_get();
|
|
char *ctf_meta = trace->ctf_meta;
|
|
int rc;
|
|
|
|
if (!rte_trace_is_enabled())
|
|
return 0;
|
|
|
|
if (ctf_meta == NULL)
|
|
return -EINVAL;
|
|
|
|
if (!__atomic_load_n(&trace->ctf_fixup_done, __ATOMIC_SEQ_CST) &&
|
|
rte_get_timer_hz()) {
|
|
meta_fixup(trace, ctf_meta);
|
|
__atomic_store_n(&trace->ctf_fixup_done, 1, __ATOMIC_SEQ_CST);
|
|
}
|
|
|
|
rc = fprintf(f, "%s", ctf_meta);
|
|
return rc < 0 ? rc : 0;
|
|
}
|
|
|
|
char *trace_metadata_fixup_field(const char *field)
|
|
{
|
|
const char *ctf_reserved_words[] = {
|
|
"align",
|
|
"event",
|
|
};
|
|
unsigned int i;
|
|
char *out;
|
|
char *p;
|
|
|
|
/* reserved keywords */
|
|
for (i = 0; i < RTE_DIM(ctf_reserved_words); i++) {
|
|
if (strcmp(field, ctf_reserved_words[i]) != 0)
|
|
continue;
|
|
if (asprintf(&out, "_%s", ctf_reserved_words[i]) == -1)
|
|
out = NULL;
|
|
return out;
|
|
}
|
|
|
|
/* nothing to replace, return early */
|
|
if (strstr(field, ".") == NULL && strstr(field, "->") == NULL)
|
|
return NULL;
|
|
|
|
out = strdup(field);
|
|
if (out == NULL)
|
|
return NULL;
|
|
p = out;
|
|
while ((p = strstr(p, ".")) != NULL) {
|
|
p[0] = '_';
|
|
p++;
|
|
}
|
|
p = out;
|
|
while ((p = strstr(p, "->")) != NULL) {
|
|
p[0] = '_';
|
|
p++;
|
|
memmove(p, p + 1, strlen(p));
|
|
}
|
|
return out;
|
|
}
|