1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell International Ltd.
10 #include <rte_common.h>
11 #include <rte_errno.h>
12 #include <rte_string_fns.h>
14 #include "eal_filesystem.h"
15 #include "eal_trace.h"
18 trace_mode_to_string(enum rte_trace_mode mode)
21 case RTE_TRACE_MODE_OVERWRITE: return "overwrite";
22 case RTE_TRACE_MODE_DISCARD: return "discard";
23 default: return "unknown";
28 trace_area_to_string(enum trace_area_e area)
31 case TRACE_AREA_HEAP: return "heap";
32 case TRACE_AREA_HUGEPAGE: return "hugepage";
33 default: return "unknown";
38 trace_entry_compare(const char *name)
40 struct trace_point_head *tp_list = trace_list_head_get();
41 struct trace_point *tp;
44 STAILQ_FOREACH(tp, tp_list, next) {
45 if (strncmp(tp->name, name, TRACE_POINT_NAME_SIZE) == 0)
48 trace_err("found duplicate entry %s", name);
57 trace_has_duplicate_entry(void)
59 struct trace_point_head *tp_list = trace_list_head_get();
60 struct trace_point *tp;
62 /* Is duplicate trace name registered */
63 STAILQ_FOREACH(tp, tp_list, next)
64 if (trace_entry_compare(tp->name))
71 trace_uuid_generate(void)
73 struct trace_point_head *tp_list = trace_list_head_get();
74 struct trace *trace = trace_obj_get();
75 struct trace_point *tp;
76 uint64_t sz_total = 0;
78 /* Go over the registered trace points to get total size of events */
79 STAILQ_FOREACH(tp, tp_list, next) {
80 const uint16_t sz = *tp->handle & __RTE_TRACE_FIELD_SIZE_MASK;
84 rte_uuid_t uuid = RTE_UUID_INIT(sz_total, trace->nb_trace_points,
85 0x4370, 0x8f50, 0x222ddd514176ULL);
86 rte_uuid_copy(trace->uuid, uuid);
90 trace_session_name_generate(char *trace_dir)
100 tm_result = localtime(&tm);
101 if (tm_result == NULL)
104 rc = rte_strscpy(trace_dir, eal_get_hugefile_prefix(),
107 rc = TRACE_PREFIX_LEN;
108 trace_dir[rc++] = '-';
110 rc = strftime(trace_dir + rc, TRACE_DIR_STR_LEN - rc,
111 "%Y-%m-%d-%p-%I-%M-%S", tm_result);
122 trace_dir_update(const char *str)
124 struct trace *trace = trace_obj_get();
127 remaining = sizeof(trace->dir) - trace->dir_offset;
128 rc = rte_strscpy(&trace->dir[0] + trace->dir_offset, str, remaining);
132 trace->dir_offset += rc;
138 eal_trace_args_save(const char *val)
140 struct trace *trace = trace_obj_get();
144 nb_args = trace->args.nb_args;
146 if (nb_args >= TRACE_MAX_ARGS) {
147 trace_err("ignoring trace %s as limit exceeds", val);
151 trace_args = calloc(1, (strlen(val) + 1));
152 if (trace_args == NULL) {
153 trace_err("fail to allocate memory for %s", val);
157 memcpy(trace_args, val, strlen(val));
158 trace->args.args[nb_args++] = trace_args;
159 trace->args.nb_args = nb_args;
164 eal_trace_args_free(void)
166 struct trace *trace = trace_obj_get();
169 for (i = 0; i < trace->args.nb_args; i++) {
170 if (trace->args.args[i]) {
171 free((void *)trace->args.args[i]);
172 trace->args.args[i] = NULL;
178 trace_args_apply(const char *arg)
186 if (rte_trace_regexp(str, true) < 0) {
187 trace_err("cannot enable trace for %s", str);
197 eal_trace_bufsz_args_save(char const *val)
199 struct trace *trace = trace_obj_get();
203 trace_err("no optarg is passed");
207 bufsz = rte_str_to_size(val);
209 trace_err("buffer size cannot be zero");
213 trace->buff_len = bufsz;
218 trace_bufsz_args_apply(void)
220 struct trace *trace = trace_obj_get();
222 if (trace->buff_len == 0)
223 trace->buff_len = 1024 * 1024; /* 1MB */
227 eal_trace_mode_args_save(const char *val)
229 struct trace *trace = trace_obj_get();
230 size_t len = strlen(val);
235 trace_err("no optarg is passed");
240 trace_err("value is not provided with option");
244 pattern = (char *)calloc(1, len + 2);
245 if (pattern == NULL) {
246 trace_err("fail to allocate memory");
250 sprintf(pattern, "%s*", val);
252 if (fnmatch(pattern, "overwrite", 0) == 0)
253 tmp = RTE_TRACE_MODE_OVERWRITE;
254 else if (fnmatch(pattern, "discard", 0) == 0)
255 tmp = RTE_TRACE_MODE_DISCARD;
267 eal_trace_dir_args_save(char const *val)
269 struct trace *trace = trace_obj_get();
270 uint32_t size = sizeof(trace->dir);
271 char *dir_path = NULL;
275 trace_err("no optarg is passed");
279 if (strlen(val) >= size) {
280 trace_err("input string is too big");
281 return -ENAMETOOLONG;
284 dir_path = (char *)calloc(1, size);
285 if (dir_path == NULL) {
286 trace_err("fail to allocate memory");
290 sprintf(dir_path, "%s/", val);
291 rc = trace_dir_update(dir_path);
298 trace_epoch_time_save(void)
300 struct trace *trace = trace_obj_get();
301 struct timespec epoch = { 0, 0 };
302 uint64_t avg, start, end;
304 start = rte_get_tsc_cycles();
305 if (clock_gettime(CLOCK_REALTIME, &epoch) < 0) {
306 trace_err("failed to get the epoch time");
309 end = rte_get_tsc_cycles();
310 avg = (start + end) >> 1;
312 trace->epoch_sec = (uint64_t) epoch.tv_sec;
313 trace->epoch_nsec = (uint64_t) epoch.tv_nsec;
314 trace->uptime_ticks = avg;
320 trace_dir_default_path_get(char *dir_path)
322 struct trace *trace = trace_obj_get();
323 uint32_t size = sizeof(trace->dir);
327 /* First check for shell environment variable */
328 home_dir = getenv("HOME");
329 if (home_dir == NULL) {
330 /* Fallback to password file entry */
331 pwd = getpwuid(getuid());
335 home_dir = pwd->pw_dir;
338 /* Append dpdk-traces to directory */
339 if (snprintf(dir_path, size, "%s/dpdk-traces/", home_dir) < 0)
340 return -ENAMETOOLONG;
348 struct trace *trace = trace_obj_get();
349 char session[TRACE_DIR_STR_LEN];
353 if (!trace->dir_offset) {
354 dir_path = calloc(1, sizeof(trace->dir));
355 if (dir_path == NULL) {
356 trace_err("fail to allocate memory");
360 rc = trace_dir_default_path_get(dir_path);
362 trace_err("fail to get default path");
367 rc = trace_dir_update(dir_path);
373 /* Create the path if it t exist, no "mkdir -p" available here */
374 rc = mkdir(trace->dir, 0700);
375 if (rc < 0 && errno != EEXIST) {
376 trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
381 rc = trace_session_name_generate(session);
384 rc = trace_dir_update(session);
388 rc = mkdir(trace->dir, 0700);
390 trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
395 RTE_LOG(INFO, EAL, "Trace dir: %s\n", trace->dir);
400 trace_meta_save(struct trace *trace)
402 char file_name[PATH_MAX];
406 rc = snprintf(file_name, PATH_MAX, "%s/metadata", trace->dir);
410 f = fopen(file_name, "w");
414 rc = rte_trace_metadata_dump(f);
424 trace_file_sz(struct __rte_trace_header *hdr)
426 return sizeof(struct __rte_trace_stream_header) + hdr->offset;
430 trace_mem_save(struct trace *trace, struct __rte_trace_header *hdr,
433 char file_name[PATH_MAX];
437 rc = snprintf(file_name, PATH_MAX, "%s/channel0_%d", trace->dir, cnt);
441 f = fopen(file_name, "w");
445 rc = fwrite(&hdr->stream_header, trace_file_sz(hdr), 1, f);
446 rc = (rc == 1) ? 0 : -EACCES;
457 struct trace *trace = trace_obj_get();
458 struct __rte_trace_header *header;
462 if (trace->nb_trace_mem_list == 0)
465 rc = trace_meta_save(trace);
469 rte_spinlock_lock(&trace->lock);
470 for (count = 0; count < trace->nb_trace_mem_list; count++) {
471 header = trace->lcore_meta[count].mem;
472 rc = trace_mem_save(trace, header, count);
476 rte_spinlock_unlock(&trace->lock);