static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
static struct trace trace;
+struct trace *
+trace_obj_get(void)
+{
+ return &trace;
+}
+
+struct trace_point_head *
+trace_list_head_get(void)
+{
+ return &tp_list;
+}
+
+int
+eal_trace_init(void)
+{
+ /* One of the trace point registration failed */
+ if (trace.register_errno) {
+ rte_errno = trace.register_errno;
+ goto fail;
+ }
+
+ if (!rte_trace_is_enabled())
+ return 0;
+
+ rte_spinlock_init(&trace.lock);
+
+ /* Is duplicate trace name registered */
+ if (trace_has_duplicate_entry())
+ goto fail;
+
+ /* Generate UUID ver 4 with total size of events and number of
+ * events
+ */
+ trace_uuid_generate();
+
+ /* Create trace directory */
+ if (trace_mkdir())
+ goto fail;
+
+
+ rte_trace_mode_set(trace.mode);
+
+ return 0;
+
+fail:
+ trace_err("failed to initialize trace [%s]", rte_strerror(rte_errno));
+ return -rte_errno;
+}
+
+void
+eal_trace_fini(void)
+{
+ if (!rte_trace_is_enabled())
+ return;
+}
+
bool
rte_trace_is_enabled(void)
{
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include <fnmatch.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+
+#include "eal_filesystem.h"
+#include "eal_trace.h"
+
+static bool
+trace_entry_compare(const char *name)
+{
+ struct trace_point_head *tp_list = trace_list_head_get();
+ struct trace_point *tp;
+ int count = 0;
+
+ STAILQ_FOREACH(tp, tp_list, next) {
+ if (strncmp(tp->name, name, TRACE_POINT_NAME_SIZE) == 0)
+ count++;
+ if (count > 1) {
+ trace_err("found duplicate entry %s", name);
+ rte_errno = EEXIST;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+trace_has_duplicate_entry(void)
+{
+ struct trace_point_head *tp_list = trace_list_head_get();
+ struct trace_point *tp;
+
+ /* Is duplicate trace name registered */
+ STAILQ_FOREACH(tp, tp_list, next)
+ if (trace_entry_compare(tp->name))
+ return true;
+
+ return false;
+}
+
+void
+trace_uuid_generate(void)
+{
+ struct trace_point_head *tp_list = trace_list_head_get();
+ struct trace *trace = trace_obj_get();
+ struct trace_point *tp;
+ uint64_t sz_total = 0;
+
+ /* Go over the registered trace points to get total size of events */
+ STAILQ_FOREACH(tp, tp_list, next) {
+ const uint16_t sz = *tp->handle & __RTE_TRACE_FIELD_SIZE_MASK;
+ sz_total += sz;
+ }
+
+ rte_uuid_t uuid = RTE_UUID_INIT(sz_total, trace->nb_trace_points,
+ 0x4370, 0x8f50, 0x222ddd514176ULL);
+ rte_uuid_copy(trace->uuid, uuid);
+}
+
+static int
+trace_session_name_generate(char *trace_dir)
+{
+ struct tm *tm_result;
+ time_t tm;
+ int rc;
+
+ tm = time(NULL);
+ if ((int)tm == -1)
+ goto fail;
+
+ tm_result = localtime(&tm);
+ if (tm_result == NULL)
+ goto fail;
+
+ rc = rte_strscpy(trace_dir, eal_get_hugefile_prefix(),
+ TRACE_PREFIX_LEN);
+ if (rc == -E2BIG)
+ rc = TRACE_PREFIX_LEN;
+ trace_dir[rc++] = '-';
+
+ rc = strftime(trace_dir + rc, TRACE_DIR_STR_LEN - rc,
+ "%Y-%m-%d-%p-%I-%M-%S", tm_result);
+ if (rc == 0)
+ goto fail;
+
+ return rc;
+fail:
+ rte_errno = errno;
+ return -rte_errno;
+}
+
+static int
+trace_dir_default_path_get(char *dir_path)
+{
+ struct trace *trace = trace_obj_get();
+ uint32_t size = sizeof(trace->dir);
+ struct passwd *pwd;
+ char *home_dir;
+
+ /* First check for shell environment variable */
+ home_dir = getenv("HOME");
+ if (home_dir == NULL) {
+ /* Fallback to password file entry */
+ pwd = getpwuid(getuid());
+ if (pwd == NULL)
+ return -EINVAL;
+
+ home_dir = pwd->pw_dir;
+ }
+
+ /* Append dpdk-traces to directory */
+ if (snprintf(dir_path, size, "%s/dpdk-traces/", home_dir) < 0)
+ return -ENAMETOOLONG;
+
+ return 0;
+}
+
+int
+trace_mkdir(void)
+{
+ struct trace *trace = trace_obj_get();
+ char session[TRACE_DIR_STR_LEN];
+ char *dir_path;
+ int rc;
+
+ if (!trace->dir_offset) {
+ dir_path = calloc(1, sizeof(trace->dir));
+ if (dir_path == NULL) {
+ trace_err("fail to allocate memory");
+ return -ENOMEM;
+ }
+
+ rc = trace_dir_default_path_get(dir_path);
+ if (rc < 0) {
+ trace_err("fail to get default path");
+ free(dir_path);
+ return rc;
+ }
+
+ }
+
+ /* Create the path if it t exist, no "mkdir -p" available here */
+ rc = mkdir(trace->dir, 0700);
+ if (rc < 0 && errno != EEXIST) {
+ trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
+ rte_errno = errno;
+ return -rte_errno;
+ }
+
+ rc = trace_session_name_generate(session);
+ if (rc < 0)
+ return rc;
+
+ rc = mkdir(trace->dir, 0700);
+ if (rc < 0) {
+ trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
+ rte_errno = errno;
+ return -rte_errno;
+ }
+
+ RTE_LOG(INFO, EAL, "Trace dir: %s\n", trace->dir);
+ return 0;
+}
+
#ifndef __EAL_TRACE_H
#define __EAL_TRACE_H
+#include <rte_spinlock.h>
#include <rte_trace.h>
#include <rte_trace_point.h>
+#include <rte_uuid.h>
#define trace_err(fmt, args...) \
RTE_LOG(ERR, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args)
#define trace_crit(fmt, args...) \
RTE_LOG(CRIT, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args)
+#define TRACE_PREFIX_LEN 12
+#define TRACE_DIR_STR_LEN (sizeof("YYYY-mm-dd-AM-HH-MM-SS") + TRACE_PREFIX_LEN)
#define TRACE_CTF_FIELD_SIZE 384
#define TRACE_POINT_NAME_SIZE 64
};
struct trace {
+ char dir[PATH_MAX];
+ int dir_offset;
int register_errno;
bool status;
enum rte_trace_mode mode;
+ rte_uuid_t uuid;
+ uint32_t buff_len;
uint32_t nb_trace_points;
+ rte_spinlock_t lock;
};
/* Helper functions */
__RTE_TRACE_FIELD_ID_SHIFT;
}
+/* Trace object functions */
+struct trace *trace_obj_get(void);
+
/* Trace point list functions */
STAILQ_HEAD(trace_point_head, trace_point);
+struct trace_point_head *trace_list_head_get(void);
+
+/* Util functions */
+bool trace_has_duplicate_entry(void);
+void trace_uuid_generate(void);
+int trace_mkdir(void);
+
+/* EAL interface */
+int eal_trace_init(void);
+void eal_trace_fini(void);
#endif /* __EAL_TRACE_H */