[v7,05/32] eal/trace: add internal trace init and fini interface

Message ID 20200422190349.3768487-6-jerinj@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: David Marchand
Headers
Series DPDK Trace support |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Jerin Jacob April 22, 2020, 7:03 p.m. UTC
From: Jerin Jacob <jerinj@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 <jerinj@marvell.com>
Signed-off-by: Sunil Kumar Kori <skori@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
  

Patch

diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index 4090f909f..e270808d2 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())
+		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