From: Jerin Jacob <jer...@marvell.com> Define eal_trace_init() and eal_trace_fini() EAL interface functions that rte_eal_init() and rte_eal_cleanup() function can be use to initialize and finalize the trace subsystem. eal_trace_init() function will add the following functionality if trace is enabled through EAL command line param.
- Test for trace registration failure. - Test for duplicate trace name registration - Generate UUID ver 4. - Create a trace directory Signed-off-by: Jerin Jacob <jer...@marvell.com> Signed-off-by: Sunil Kumar Kori <sk...@marvell.com> --- lib/librte_eal/common/eal_common_trace.c | 54 ++++++ .../common/eal_common_trace_utils.c | 173 ++++++++++++++++++ lib/librte_eal/common/eal_trace.h | 22 +++ lib/librte_eal/common/meson.build | 1 + lib/librte_eal/freebsd/Makefile | 1 + lib/librte_eal/linux/Makefile | 1 + 6 files changed, 252 insertions(+) create mode 100644 lib/librte_eal/common/eal_common_trace_utils.c diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c index 1ca702f68..557054c65 100644 --- a/lib/librte_eal/common/eal_common_trace.c +++ b/lib/librte_eal/common/eal_common_trace.c @@ -22,6 +22,60 @@ static RTE_DEFINE_PER_LCORE(int, ctf_count); 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 registration failed */ + if (trace.register_errno) { + rte_errno = trace.register_errno; + goto fail; + } + + if (rte_trace_is_enabled() == false) + 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() == false) + return; +} + bool rte_trace_is_enabled(void) { diff --git a/lib/librte_eal/common/eal_common_trace_utils.c b/lib/librte_eal/common/eal_common_trace_utils.c new file mode 100644 index 000000000..d2ab8f845 --- /dev/null +++ b/lib/librte_eal/common/eal_common_trace_utils.c @@ -0,0 +1,173 @@ +/* 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; +} + diff --git a/lib/librte_eal/common/eal_trace.h b/lib/librte_eal/common/eal_trace.h index ebf7914ff..deb57dd4c 100644 --- a/lib/librte_eal/common/eal_trace.h +++ b/lib/librte_eal/common/eal_trace.h @@ -5,8 +5,10 @@ #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",\ @@ -16,6 +18,8 @@ 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 @@ -27,10 +31,15 @@ struct trace_point { }; 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 */ @@ -41,7 +50,20 @@ trace_id_get(rte_trace_point_t *trace) __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 */ diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build index 429e89f99..3dc320327 100644 --- a/lib/librte_eal/common/meson.build +++ b/lib/librte_eal/common/meson.build @@ -43,6 +43,7 @@ sources += files( 'eal_common_thread.c', 'eal_common_timer.c', 'eal_common_trace.c', + 'eal_common_trace_utils.c', 'eal_common_uuid.c', 'hotplug_mp.c', 'malloc_elem.c', diff --git a/lib/librte_eal/freebsd/Makefile b/lib/librte_eal/freebsd/Makefile index 500afc578..ae59c8c19 100644 --- a/lib/librte_eal/freebsd/Makefile +++ b/lib/librte_eal/freebsd/Makefile @@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_proc.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_uuid.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_trace.c +SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_trace_utils.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += hotplug_mp.c SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += malloc_elem.c diff --git a/lib/librte_eal/linux/Makefile b/lib/librte_eal/linux/Makefile index 2ced2085b..7992500a9 100644 --- a/lib/librte_eal/linux/Makefile +++ b/lib/librte_eal/linux/Makefile @@ -67,6 +67,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_proc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_uuid.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_trace.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_trace_utils.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += hotplug_mp.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += malloc_elem.c -- 2.25.1