Skip to contentSkip to conversation

eal: add option to put timestamp on console output

PATCH In review Stephen Hemminger 12 participants 486 messages Aug 14, 2020 – Nov 8, 2024 Arm/Amlogic Meson SoC support Page 3 of 5

lore
Share & tools
lore
#225 lore raw

PATCH v19 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.43.0
#226 lore raw

PATCH v19 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.43.0
#227 lore raw

PATCH v19 4/15 windows: common wrapper for vasprintf and asprintf

In reply to Stephen Hemminger

Replace the windows version of asprintf() that was only usable in eal. With a more generic one that supports both vasprintf() and asprintf(). This also eliminates duplicate code.

Fixes 8f4de2dba9b9 ("bus/pci: fill bus specific information")
Fixes 9ec521006db0 ("eal/windows: hide asprintf shim")
---
 drivers/bus/pci/pci_common.c          | 32 ------------------
 lib/eal/common/eal_private.h          | 10 ------
 lib/eal/windows/eal.c                 | 28 ----------------
 lib/eal/windows/include/rte_os_shim.h | 48 +++++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 70 deletions(-)
drivers/bus/pci/pci_common.c +0 -32
index 889a48d2af..80691c75a3 100644
@@ -45,38 +45,6 @@ const char *rte_pci_get_sysfs_path(void)
 	return path;
 }
 
-#ifdef RTE_EXEC_ENV_WINDOWS
-#define asprintf pci_asprintf
-
-static int
-__rte_format_printf(2, 3)
-pci_asprintf(char **buffer, const char *format, ...)
-{
-	int size, ret;
-	va_list arg;
-
-	va_start(arg, format);
-	size = vsnprintf(NULL, 0, format, arg);
-	va_end(arg);
-	if (size < 0)
-		return -1;
-	size++;
-
-	*buffer = malloc(size);
-	if (*buffer == NULL)
-		return -1;
-
-	va_start(arg, format);
-	ret = vsnprintf(*buffer, size, format, arg);
-	va_end(arg);
-	if (ret != size - 1) {
-		free(*buffer);
-		return -1;
-	}
-	return ret;
-}
-#endif /* RTE_EXEC_ENV_WINDOWS */
-
 static struct rte_devargs *
 pci_devargs_lookup(const struct rte_pci_addr *pci_addr)
 {
lib/eal/common/eal_private.h +0 -10
index 71523cfdb8..da8d77a134 100644
@@ -737,16 +737,6 @@ void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset);
  */
 void __rte_thread_uninit(void);
 
-/**
- * asprintf(3) replacement for Windows.
- */
-#ifdef RTE_EXEC_ENV_WINDOWS
-__rte_format_printf(2, 3)
-int eal_asprintf(char **buffer, const char *format, ...);
-
-#define asprintf(buffer, format, ...) \
-		eal_asprintf(buffer, format, ##__VA_ARGS__)
-#endif
 
 #define EAL_LOG(level, ...) \
 	RTE_LOG_LINE(level, EAL, "" __VA_ARGS__)
lib/eal/windows/eal.c +0 -28
index 52f0e7462d..8ca00c0f95 100644
@@ -503,34 +503,6 @@ rte_eal_init(int argc, char **argv)
 	return fctret;
 }
 
-/* Don't use MinGW asprintf() to have identical code with all toolchains. */
-int
-eal_asprintf(char **buffer, const char *format, ...)
-{
-	int size, ret;
-	va_list arg;
-
-	va_start(arg, format);
-	size = vsnprintf(NULL, 0, format, arg);
-	va_end(arg);
-	if (size < 0)
-		return -1;
-	size++;
-
-	*buffer = malloc(size);
-	if (*buffer == NULL)
-		return -1;
-
-	va_start(arg, format);
-	ret = vsnprintf(*buffer, size, format, arg);
-	va_end(arg);
-	if (ret != size - 1) {
-		free(*buffer);
-		return -1;
-	}
-	return ret;
-}
-
 int
 rte_vfio_container_dma_map(__rte_unused int container_fd,
 			__rte_unused uint64_t vaddr,
lib/eal/windows/include/rte_os_shim.h +48 -0

58 lines not on this page · raw message

Signature · 1 line
2.43.0
#228 lore raw

PATCH v19 5/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 46 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 --------------------------
 lib/eal/linux/eal.c                 | 39 ------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 47 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +46 -0
index e541f07939..5435399b85 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
@@ -2173,6 +2218,7 @@ rte_vect_set_max_simd_bitwidth(uint16_t bitwidth)
 	return 0;
 }
 
+
 void
 eal_common_usage(void)
 {
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index fd422f1f62..bffeb1f34e 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 8ca00c0f95..44e20643f2 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.43.0
#229 lore raw

PATCH v19 6/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index 9825bcea0b..17b56f38aa 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index bffeb1f34e..23dc26b124 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.43.0
#230 lore raw

PATCH v19 7/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +6 -5
index 3e77995896..ad2be63cbb 100644
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.43.0
#231 lore raw

PATCH v19 8/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index 5435399b85..661b2db211 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1882,7 +1835,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 17b56f38aa..6552f9c138 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 23dc26b124..3d0c34063e 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1106,8 +1106,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index 44e20643f2..14e498a643 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 0648f8831a..9c6c49bf06 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#232 lore raw

PATCH v19 9/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index 6552f9c138..55ff27a4da 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -565,9 +574,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 3d0c34063e..b9a0fb1742 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -952,9 +961,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1106,13 +1112,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 14e498a643..e59aba954e 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.43.0
#233 lore raw

PATCH v19 10/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 6cb4b06757..36e3185a10 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 661b2db211..9ab512e8a1 100644
@@ -2212,9 +2212,6 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
-#ifndef RTE_EXEC_ENV_WINDOWS
-	       "  --"OPT_SYSLOG"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 9c6c49bf06..32b9680c31 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#234 lore raw

PATCH v19 11/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 14 +++++++++++++-
 lib/log/log_private.h | 11 +++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +13 -1
index 3fe86ddcd7..71b00528d0 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -28,16 +29,19 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = log_print,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +78,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -470,7 +475,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, level, format, ap);
 	fflush(f);
 	return ret;
 }
@@ -499,6 +504,13 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+int
+log_print(FILE *f, uint32_t level __rte_unused,  const char *format, va_list ap)
+{
+	return vfprintf(f, format, ap);
+}
+
 /*
  * Called by rte_eal_init
  */
lib/log/log_private.h new file +11 -0
new file mode 100644
index 0000000000..afd833c3bd
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+
+__rte_format_printf(3, 0)
+int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.43.0
#235 lore raw

PATCH v19 12/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |  10 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |   7 +
 lib/log/log_timestamp.c             | 204 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 309 insertions(+), 10 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index 36e3185a10..e54f6e8b7f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index 9ab512e8a1..5173835c2c 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1843,7 +1845,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1851,7 +1853,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2216,6 +2225,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 55ff27a4da..662a829ce8 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index b9a0fb1742..8cbea480e0 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index e59aba954e..b251dc3e1b 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +7 -3
index 71b00528d0..3c15f2a560 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -29,13 +29,13 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
-
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 	log_print_t print_func;
+
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
@@ -359,7 +359,6 @@ static const struct logtype logtype_strings[] = {
 RTE_INIT_PRIO(log_init, LOG)
 {
 	uint32_t i;
-
 	rte_log_set_global_level(RTE_LOG_DEBUG);
 
 	rte_logs.dynamic_types = calloc(RTE_LOGTYPE_FIRST_EXT_ID,
@@ -517,6 +516,11 @@ log_print(FILE *f, uint32_t level __rte_unused,  const char *format, va_list ap)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = log_print;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +7 -0
index afd833c3bd..070baee8dd 100644
@@ -8,4 +8,11 @@ typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap)
 __rte_format_printf(3, 0)
 int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
 
+bool log_timestamp_enabled(void);
+
+ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
+
+__rte_format_printf(3, 0)
+int log_print_with_timestamp(FILE *f, uint32_t level, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +204 -0

204 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 32b9680c31..14d6681a5f 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#236 lore raw

PATCH v19 13/15 log: add optional support of syslog

In reply to Stephen Hemminger

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 17 ++++
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 25 +++---
 lib/log/log_private.h                         |  4 +
 lib/log/log_stubs.c                           | 28 ++++++
 lib/log/log_syslog.c                          | 89 +++++++++++++++++++
 lib/log/meson.build                           |  6 ++
 9 files changed, 165 insertions(+), 41 deletions(-)
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index e54f6e8b7f..08f4866461 100644
@@ -987,9 +987,10 @@ test_misc_flags(void)
 	/* With empty --syslog */
 	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
 	/* With invalid --syslog */
-	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
 	const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
 			no_shconf, nosh_prefix, no_huge};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -108,30 +108,3 @@ Memory-related options
 *   ``--match-allocations``
 
     Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-*   ``--syslog <syslog facility>``
-
-    Set syslog facility. Valid syslog facilities are::
-
-        auth
-        cron
-        daemon
-        ftp
-        kern
-        lpr
-        mail
-        news
-        syslog
-        user
-        uucp
-        local0
-        local1
-        local2
-        local3
-        local4
-        local5
-        local6
-        local7
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
 
 	/path/to/app --log-timestamp=iso
 
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+    Redirect all log output to syslog.
+
+*auto*
+    Use console if it is a terminal, and use syslog if is not.
+
+*both*
+    Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +4 -1
index 5173835c2c..9ca7db04aa 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
@@ -2221,6 +2221,9 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +14 -11
index 3c15f2a560..ddb8400d73 100644
@@ -12,18 +12,19 @@
 #include <regex.h>
 #include <fnmatch.h>
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
-#include "log_internal.h"
-#include "log_private.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+#include "log_private.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
@@ -496,13 +497,6 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 	return ret;
 }
 
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
-	return -1;
-}
-
 /* default log print function */
 int
 log_print(FILE *f, uint32_t level __rte_unused,  const char *format, va_list ap)
@@ -514,8 +508,17 @@ log_print(FILE *f, uint32_t level __rte_unused,  const char *format, va_list ap)
  * Called by rte_eal_init
  */
 void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
+	RTE_SET_USED(id);
+#else
+	bool is_terminal = isatty(STDERR_FILENO);
+
+	if (log_syslog_enabled(is_terminal))
+		log_syslog_open(id, is_terminal);
+	else
+#endif
 	if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
lib/log/log_private.h +4 -0
index 070baee8dd..0e7d10ffca 100644
@@ -15,4 +15,8 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 __rte_format_printf(3, 0)
 int log_print_with_timestamp(FILE *f, uint32_t level, const char *format, va_list ap);
 
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c new file +28 -0
new file mode 100644
index 0000000000..cb34217af8
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <regex.h>
+#include <fnmatch.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <rte_os_shim.h>
+
+#include <rte_log.h>
+#include <rte_per_lcore.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+/* Stubs for Windows */
+int
+eal_log_syslog(const char *str __rte_unused)
+{
+	return -1;
+}
lib/log/log_syslog.c new file +89 -0

89 lines not on this page · raw message

lib/log/meson.build +6 -0
index 04235f6ee5..37507299e7 100644
@@ -7,4 +7,10 @@ sources = files(
         'log_timestamp.c',
 )
 
+if is_windows
+	sources += files('log_stubs.c')
+else
+	sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
Signature · 1 line
2.43.0
#237 lore raw

PATCH v19 14/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   5 +
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 216 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |   4 +
 lib/log/log_stubs.c                 |   6 +
 lib/log/meson.build                 |   5 +
 lib/log/version.map                 |   1 +
 10 files changed, 267 insertions(+)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +11 -0
index 9ca7db04aa..9a82118184 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1843,6 +1845,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
+
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
 #endif
 
 	case OPT_LOG_LEVEL_NUM:
@@ -2223,6 +2233,7 @@ eal_common_usage(void)
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +5 -0
index ddb8400d73..d97bde984e 100644
@@ -515,6 +515,11 @@ eal_log_init(const char *id)
 #else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+#ifdef RTE_EXEC_ENV_LINUX
+	if (log_journal_enabled(id))
+		rte_logs.print_func = journal_print;
+	else
+#endif
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +216 -0

216 lines not on this page · raw message

lib/log/log_private.h +4 -0
index 0e7d10ffca..988579fc08 100644
@@ -18,5 +18,9 @@ int log_print_with_timestamp(FILE *f, uint32_t level, const char *format, va_lis
 bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 
+bool log_journal_enabled(const char *id);
+
+__rte_format_printf(3, 0)
+int journal_print(FILE *f, uint32_t level, const char *format, va_list ap);
 
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c +6 -0
index cb34217af8..803a6e9f6b 100644
@@ -26,3 +26,9 @@ eal_log_syslog(const char *str __rte_unused)
 {
 	return -1;
 }
+
+int
+eal_log_journal(const char *str __rte_unused)
+{
+	return -1;
+}
lib/log/meson.build +5 -0
index 37507299e7..5b9be7f6f1 100644
@@ -7,10 +7,15 @@ sources = files(
         'log_timestamp.c',
 )
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 if is_windows
 	sources += files('log_stubs.c')
 else
 	sources += files('log_syslog.c')
 endif
 
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 14d6681a5f..7af97ece43 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal;
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.43.0
#238 lore raw

PATCH v19 15/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  16 ++-
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  24 +++--
 lib/log/log_color.c                 | 160 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   2 +-
 lib/log/version.map                 |   1 +
 10 files changed, 247 insertions(+), 10 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 08f4866461..c6c05e2e1d 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -1
index 476dedb097..f46720fe34 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
@@ -115,7 +130,6 @@ There are three possible settings for this option:
 *always*
     Always try to direct messages to journal socket.
 
-
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +11 -0
index 9a82118184..70fdf3f5a1 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1872,6 +1874,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2240,6 +2250,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +18 -6
index d97bde984e..a2254b461b 100644
@@ -510,10 +510,14 @@ log_print(FILE *f, uint32_t level __rte_unused,  const char *format, va_list ap)
 void
 eal_log_init(const char *id)
 {
+	bool is_terminal;
+
 #ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
+
+	is_terminal = _isatty(_fileno(stderr));
 #else
-	bool is_terminal = isatty(STDERR_FILENO);
+	is_terminal = isatty(STDERR_FILENO);
 
 #ifdef RTE_EXEC_ENV_LINUX
 	if (log_journal_enabled(id))
@@ -523,11 +527,19 @@ eal_log_init(const char *id)
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
-#endif
-	if (log_timestamp_enabled())
-		rte_logs.print_func = log_print_with_timestamp;
-	else
-		rte_logs.print_func = log_print;
+#endif /* RTE_EXEC_ENV_WINDOWS */
+
+	if (log_color_enabled(is_terminal)) {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = color_print;
+	} else {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = log_print_with_timestamp;
+		else
+			rte_logs.print_func = log_print;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +160 -0

160 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index 988579fc08..bb93584f29 100644
@@ -23,4 +23,12 @@ bool log_journal_enabled(const char *id);
 __rte_format_printf(3, 0)
 int journal_print(FILE *f, uint32_t level, const char *format, va_list ap);
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(3, 0)
+int color_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
+__rte_format_printf(3, 0)
+int color_print_with_timestamp(FILE *f, uint32_t level, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -1
index 5b9be7f6f1..3467cb5e9d 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
@@ -17,5 +18,4 @@ else
 	sources += files('log_syslog.c')
 endif
 
-
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 7af97ece43..eb3200dcde 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal;
 	eal_log_level2str;
Signature · 1 line
2.43.0
#239 lore raw

v20 cover Logging unification and improvements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog.

Add myself as maintainer for log because by now have added more than previous authors.

v20 - avoid use vasprintf if possible, because it requires
extra patch for Windows, and increases risk of missed message if malloc pool is corrupted.
- fix build on FreeBSD.

Stephen Hemminger (14):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 +++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 ---
 doc/guides/prog_guide/log_lib.rst             |  71 ++++++
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 137 +++++++-----
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  80 ++++---
 lib/log/log_color.c                           | 148 ++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 200 +++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  34 +++
 lib/log/log_stubs.c                           |  37 +++
 lib/log/log_syslog.c                          |  88 ++++++++
 lib/log/log_timestamp.c                       | 210 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  14 +-
 lib/log/version.map                           |   5 +-
 26 files changed, 1097 insertions(+), 378 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#240 lore raw

PATCH v20 1/14 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index 7abb3aee49..54c28a601d 100644
@@ -180,6 +180,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.43.0
#241 lore raw

PATCH v20 2/14 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.43.0
#242 lore raw

PATCH v20 3/14 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.43.0
#243 lore raw

PATCH v20 4/14 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 46 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 --------------------------
 lib/eal/linux/eal.c                 | 39 ------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 47 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +46 -0
index e541f07939..5435399b85 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
@@ -2173,6 +2218,7 @@ rte_vect_set_max_simd_bitwidth(uint16_t bitwidth)
 	return 0;
 }
 
+
 void
 eal_common_usage(void)
 {
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index fd422f1f62..bffeb1f34e 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 52f0e7462d..85171b2768 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.43.0
#244 lore raw

PATCH v20 5/14 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index 9825bcea0b..17b56f38aa 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index bffeb1f34e..23dc26b124 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.43.0
#245 lore raw

PATCH v20 6/14 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +6 -5
index 3e77995896..ad2be63cbb 100644
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.43.0
#246 lore raw

PATCH v20 7/14 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index 5435399b85..661b2db211 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1882,7 +1835,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 17b56f38aa..6552f9c138 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 23dc26b124..3d0c34063e 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1106,8 +1106,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index 85171b2768..2519a30017 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 0648f8831a..9c6c49bf06 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#247 lore raw

PATCH v20 8/14 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index 6552f9c138..55ff27a4da 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -565,9 +574,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 3d0c34063e..b9a0fb1742 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -952,9 +961,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1106,13 +1112,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 2519a30017..74b3ece30c 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.43.0
#248 lore raw

PATCH v20 9/14 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 6cb4b06757..36e3185a10 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 661b2db211..9ab512e8a1 100644
@@ -2212,9 +2212,6 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
-#ifndef RTE_EXEC_ENV_WINDOWS
-	       "  --"OPT_SYSLOG"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 9c6c49bf06..32b9680c31 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#249 lore raw

PATCH v20 10/14 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 7 ++++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +6 -1
index 3fe86ddcd7..979b20c3ef 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -28,16 +29,19 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +78,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +475,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.43.0
#250 lore raw

PATCH v20 11/14 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |  10 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 210 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 319 insertions(+), 10 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index 36e3185a10..e54f6e8b7f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index 9ab512e8a1..5173835c2c 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1843,7 +1845,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1851,7 +1853,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2216,6 +2225,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 55ff27a4da..662a829ce8 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index b9a0fb1742..8cbea480e0 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index 74b3ece30c..4283c920c8 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +7 -3
index 979b20c3ef..71db4894fa 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -29,13 +29,13 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
-
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 	log_print_t print_func;
+
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
@@ -359,7 +359,6 @@ static const struct logtype logtype_strings[] = {
 RTE_INIT_PRIO(log_init, LOG)
 {
 	uint32_t i;
-
 	rte_log_set_global_level(RTE_LOG_DEBUG);
 
 	rte_logs.dynamic_types = calloc(RTE_LOGTYPE_FIRST_EXT_ID,
@@ -510,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
+
+__rte_format_printf(2, 0)
+int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +210 -0

210 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 32b9680c31..14d6681a5f 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#251 lore raw

PATCH v20 12/14 log: add optional support of syslog

In reply to Stephen Hemminger

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 17 ++++
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 25 +++---
 lib/log/log_private.h                         |  4 +
 lib/log/log_stubs.c                           | 28 ++++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  6 ++
 9 files changed, 164 insertions(+), 41 deletions(-)
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index e54f6e8b7f..08f4866461 100644
@@ -987,9 +987,10 @@ test_misc_flags(void)
 	/* With empty --syslog */
 	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
 	/* With invalid --syslog */
-	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
 	const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
 			no_shconf, nosh_prefix, no_huge};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -108,30 +108,3 @@ Memory-related options
 *   ``--match-allocations``
 
     Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-*   ``--syslog <syslog facility>``
-
-    Set syslog facility. Valid syslog facilities are::
-
-        auth
-        cron
-        daemon
-        ftp
-        kern
-        lpr
-        mail
-        news
-        syslog
-        user
-        uucp
-        local0
-        local1
-        local2
-        local3
-        local4
-        local5
-        local6
-        local7
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
 
 	/path/to/app --log-timestamp=iso
 
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+    Redirect all log output to syslog.
+
+*auto*
+    Use console if it is a terminal, and use syslog if is not.
+
+*both*
+    Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +4 -1
index 5173835c2c..9ca7db04aa 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
@@ -2221,6 +2221,9 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +14 -11
index 71db4894fa..4430b251a1 100644
@@ -12,18 +12,19 @@
 #include <regex.h>
 #include <fnmatch.h>
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
-#include "log_internal.h"
-#include "log_private.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+#include "log_private.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
@@ -496,19 +497,21 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 	return ret;
 }
 
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
-	return -1;
-}
-
 /*
  * Called by rte_eal_init
  */
 void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
+	RTE_SET_USED(id);
+#else
+	bool is_terminal = isatty(STDERR_FILENO);
+
+	if (log_syslog_enabled(is_terminal))
+		log_syslog_open(id, is_terminal);
+	else
+#endif
 	if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
lib/log/log_private.h +4 -0
index 67cfe72fc6..c4eb533529 100644
@@ -17,4 +17,8 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 __rte_format_printf(2, 0)
 int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c new file +28 -0
new file mode 100644
index 0000000000..cb34217af8
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <regex.h>
+#include <fnmatch.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <rte_os_shim.h>
+
+#include <rte_log.h>
+#include <rte_per_lcore.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+/* Stubs for Windows */
+int
+eal_log_syslog(const char *str __rte_unused)
+{
+	return -1;
+}
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +6 -0
index 04235f6ee5..37507299e7 100644
@@ -7,4 +7,10 @@ sources = files(
         'log_timestamp.c',
 )
 
+if is_windows
+	sources += files('log_stubs.c')
+else
+	sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
Signature · 1 line
2.43.0
#252 lore raw

PATCH v20 13/14 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   5 +
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |   2 +
 lib/log/log_stubs.c                 |  11 +-
 lib/log/meson.build                 |  10 +-
 lib/log/version.map                 |   1 +
 10 files changed, 255 insertions(+), 4 deletions(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +11 -0
index 9ca7db04aa..9a82118184 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1843,6 +1845,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
+
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
 #endif
 
 	case OPT_LOG_LEVEL_NUM:
@@ -2223,6 +2233,7 @@ eal_common_usage(void)
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +5 -0
index 4430b251a1..13d68402d9 100644
@@ -508,6 +508,11 @@ eal_log_init(const char *id)
 #else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+#ifdef RTE_EXEC_ENV_LINUX
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else
+#endif
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +2 -0
index c4eb533529..91976ab313 100644
@@ -20,5 +20,7 @@ int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
 
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c +10 -1
index cb34217af8..6b2099f57b 100644
@@ -20,9 +20,18 @@
 #include "log_internal.h"
 #include "log_private.h"
 
-/* Stubs for Windows */
+#ifdef RTE_EXEC_ENV_WINDOWS
 int
 eal_log_syslog(const char *str __rte_unused)
 {
 	return -1;
 }
+#endif
+
+#ifndef RTE_EXEC_ENV_LINUX
+int
+eal_log_journal(const char *str __rte_unused)
+{
+	return -1;
+}
+#endif
lib/log/meson.build +7 -3
index 37507299e7..0a80027326 100644
@@ -7,10 +7,14 @@ sources = files(
         'log_timestamp.c',
 )
 
-if is_windows
-	sources += files('log_stubs.c')
-else
+if not is_windows
 	sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+else
+	sources += files('log_stubs.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 14d6681a5f..7af97ece43 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal;
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.43.0
#253 lore raw

Re: [PATCH v20 13/14] log: add support for systemd journal

Quoted 11 lines · Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

Quoted 13 lines
---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   5 +
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |   2 +
 lib/log/log_stubs.c                 |  11 +-
 lib/log/meson.build                 |  10 +-
 lib/log/version.map                 |   1 +
 10 files changed, 255 insertions(+), 4 deletions(-)
 create mode 100644 lib/log/log_journal.c

This is very nice work, I like it a lot!

Quoted 23 lines
lib/log/log_journal.c new file +23 -0
+/*
+ * send structured message using journal protocol
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ */
+static int
+journal_send(const char *buf, size_t len)
+{
+       struct iovec iov[4];
+       unsigned int n = 0;
+       int priority = rte_log_cur_msg_loglevel() - 1;
+       char msg[] = "MESSAGE=";
+       char newline = '\n';
+       char pbuf[16];  /* "PRIORITY=N\n" */
+
+       iov[n].iov_base = msg;
+       iov[n++].iov_len = strlen(msg);
+
+       iov[n].iov_base = (char *)(uintptr_t)buf;
+       iov[n++].iov_len = len;
+
+       /* if message doesn't end with newline, one will be applied. */
+       if (buf[len - 1] != '\n') {
+               iov[n].iov_base = &newline;

lib/log/log_journal.c line 75

Quoted 10 lines
lib/log/log_journal.c new file +10 -0
+               iov[n++].iov_len = 1;
+       }
+
+       /* priority value between 0 ("emerg") and 7 ("debug") */
+       iov[n].iov_base = pbuf;
+       iov[n++].iov_len = snprintf(pbuf, sizeof(pbuf),
+                                   "PRIORITY=%d\n", priority);
+
+       return writev(log_journal_fd, iov, n);
+}

Doesn't need to be implemented immediately, but the nicest thing about talking directly to the journal is the ability to send lots of arbitrary and useful metadata together with a message, so would be nice if the logging function took an optional string vector that is appended, or some other such mechanism.

A very useful example is creating a UUID and then setting MESSAGE_ID=uuid when logging particularly important messages that are useful to filter by this type - for example, when an interface state changes to up/down. That way, one can do 'journalctl MESSAGE_ID=abc..' and get all messages about interface state changes. A project can also ship a catalog file that adds additional context to each ID, that is automatically parsed and displayed to users.

#254 lore raw

PATCH v20 14/14 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  16 ++-
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  24 +++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 235 insertions(+), 9 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 08f4866461..c6c05e2e1d 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -1
index 476dedb097..f46720fe34 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
@@ -115,7 +130,6 @@ There are three possible settings for this option:
 *always*
     Always try to direct messages to journal socket.
 
-
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +11 -0
index 9a82118184..70fdf3f5a1 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1872,6 +1874,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2240,6 +2250,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +18 -6
index 13d68402d9..856c0a0a29 100644
@@ -503,10 +503,14 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 void
 eal_log_init(const char *id)
 {
+	bool is_terminal;
+
 #ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
+
+	is_terminal = _isatty(_fileno(stderr));
 #else
-	bool is_terminal = isatty(STDERR_FILENO);
+	is_terminal = isatty(STDERR_FILENO);
 
 #ifdef RTE_EXEC_ENV_LINUX
 	if (log_journal_enabled())
@@ -516,11 +520,19 @@ eal_log_init(const char *id)
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
-#endif
-	if (log_timestamp_enabled())
-		rte_logs.print_func = log_print_with_timestamp;
-	else
-		rte_logs.print_func = vfprintf;
+#endif /* RTE_EXEC_ENV_WINDOWS */
+
+	if (log_color_enabled(is_terminal)) {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = color_print;
+	} else {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = log_print_with_timestamp;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index 91976ab313..5952bfb453 100644
@@ -23,4 +23,12 @@ void log_syslog_open(const char *id, bool is_terminal);
 bool log_journal_enabled(void);
 void log_journal_open(const char *id);
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 0a80027326..4041feed13 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 7af97ece43..eb3200dcde 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal;
 	eal_log_level2str;
Signature · 1 line
2.43.0
#255 lore raw

v21 cover Log library unification ane enhancements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v21 - rebase and clean up a couple of blank lines that snuck in

Stephen Hemminger (14):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 +++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 ---
 doc/guides/prog_guide/log_lib.rst             |  72 ++++++
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 136 +++++++-----
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  80 ++++---
 lib/log/log_color.c                           | 148 ++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 200 +++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  34 +++
 lib/log/log_stubs.c                           |  37 +++
 lib/log/log_syslog.c                          |  88 ++++++++
 lib/log/log_timestamp.c                       | 210 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  14 +-
 lib/log/version.map                           |   5 +-
 26 files changed, 1097 insertions(+), 378 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#256 lore raw

PATCH v21 1/14 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c9adff9846..92e502c64b 100644
@@ -181,6 +181,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.43.0
#258 lore raw

PATCH v21 2/14 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.43.0
#259 lore raw

Re: [PATCH v21 02/14] windows: make getopt functions have const properties

Quoted 5 lines · On Mon, 3 Jun 2024 17:44:50 -0700 Stephen Hemminger…

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

Quoted 7 lines

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

Ignore checkpatch complaints about this file.

It is better for the code to not change from the original FreeBSD.

#260 lore raw

PATCH v21 3/14 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.43.0
#261 lore raw

PATCH v21 4/14 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 45 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 ---------------------------
 lib/eal/linux/eal.c                 | 39 -------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 46 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +45 -0
index e541f07939..cb3c52c67a 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index fd422f1f62..bffeb1f34e 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 52f0e7462d..85171b2768 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.43.0
#262 lore raw

PATCH v21 5/14 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index 9825bcea0b..17b56f38aa 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index bffeb1f34e..23dc26b124 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.43.0
#263 lore raw

PATCH v21 6/14 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +6 -5
index 3e77995896..ad2be63cbb 100644
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.43.0
#264 lore raw

PATCH v21 7/14 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index cb3c52c67a..02e0f6fe55 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1882,7 +1835,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 17b56f38aa..6552f9c138 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 23dc26b124..3d0c34063e 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1106,8 +1106,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index 85171b2768..2519a30017 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 0648f8831a..9c6c49bf06 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#265 lore raw

PATCH v21 8/14 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index 6552f9c138..55ff27a4da 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -565,9 +574,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 3d0c34063e..b9a0fb1742 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -952,9 +961,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1106,13 +1112,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 2519a30017..74b3ece30c 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.43.0
#266 lore raw

PATCH v21 9/14 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 6cb4b06757..36e3185a10 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 02e0f6fe55..89e0465f04 100644
@@ -2211,9 +2211,6 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
-#ifndef RTE_EXEC_ENV_WINDOWS
-	       "  --"OPT_SYSLOG"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 9c6c49bf06..32b9680c31 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#267 lore raw

Re: [PATCH v21 09/14] log: drop syslog support, and make code common

Quoted 5 lines · On Mon, 3 Jun 2024 17:44:57 -0700 Stephen Hemminger…

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

Ignore checkpatch complaints on this patch.
It is better for the test code in test_eal_flags.c to match the existing style, rather than being different because checkpatch wants it to be static.

#268 lore raw

PATCH v21 10/14 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 7 ++++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +6 -1
index 3fe86ddcd7..979b20c3ef 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -28,16 +29,19 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +78,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +475,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.43.0
#269 lore raw

PATCH v21 11/14 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |  10 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 210 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 319 insertions(+), 10 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index 36e3185a10..e54f6e8b7f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index 89e0465f04..b6c648dcf3 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1843,7 +1845,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1851,7 +1853,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2215,6 +2224,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 55ff27a4da..662a829ce8 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index b9a0fb1742..8cbea480e0 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index 74b3ece30c..4283c920c8 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +7 -3
index 979b20c3ef..71db4894fa 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -29,13 +29,13 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
-
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 	log_print_t print_func;
+
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
@@ -359,7 +359,6 @@ static const struct logtype logtype_strings[] = {
 RTE_INIT_PRIO(log_init, LOG)
 {
 	uint32_t i;
-
 	rte_log_set_global_level(RTE_LOG_DEBUG);
 
 	rte_logs.dynamic_types = calloc(RTE_LOGTYPE_FIRST_EXT_ID,
@@ -510,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
+
+__rte_format_printf(2, 0)
+int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +210 -0

210 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 32b9680c31..14d6681a5f 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.43.0
#270 lore raw

Re: [PATCH v21 11/14] log: add timestamp option

Quoted 20 lines · On Mon, 3 Jun 2024 17:44:59 -0700 Stephen Hemminger…

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
Quoted 1 line

Ignore bogus checkpatch warning from this patch. Checkpatch thinks that #include <stdio.h> is a spelling error!

#271 lore raw

PATCH v21 12/14 log: add optional support of syslog

In reply to Stephen Hemminger

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 17 ++++
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 25 +++---
 lib/log/log_private.h                         |  4 +
 lib/log/log_stubs.c                           | 28 ++++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  6 ++
 9 files changed, 164 insertions(+), 41 deletions(-)
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index e54f6e8b7f..08f4866461 100644
@@ -987,9 +987,10 @@ test_misc_flags(void)
 	/* With empty --syslog */
 	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
 	/* With invalid --syslog */
-	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
 	const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
 			no_shconf, nosh_prefix, no_huge};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -108,30 +108,3 @@ Memory-related options
 *   ``--match-allocations``
 
     Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-*   ``--syslog <syslog facility>``
-
-    Set syslog facility. Valid syslog facilities are::
-
-        auth
-        cron
-        daemon
-        ftp
-        kern
-        lpr
-        mail
-        news
-        syslog
-        user
-        uucp
-        local0
-        local1
-        local2
-        local3
-        local4
-        local5
-        local6
-        local7
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
 
 	/path/to/app --log-timestamp=iso
 
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+    Redirect all log output to syslog.
+
+*auto*
+    Use console if it is a terminal, and use syslog if is not.
+
+*both*
+    Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +4 -1
index b6c648dcf3..59454bb473 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
@@ -2220,6 +2220,9 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +14 -11
index 71db4894fa..4430b251a1 100644
@@ -12,18 +12,19 @@
 #include <regex.h>
 #include <fnmatch.h>
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
-#include "log_internal.h"
-#include "log_private.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+#include "log_private.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
@@ -496,19 +497,21 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 	return ret;
 }
 
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
-	return -1;
-}
-
 /*
  * Called by rte_eal_init
  */
 void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
+	RTE_SET_USED(id);
+#else
+	bool is_terminal = isatty(STDERR_FILENO);
+
+	if (log_syslog_enabled(is_terminal))
+		log_syslog_open(id, is_terminal);
+	else
+#endif
 	if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
lib/log/log_private.h +4 -0
index 67cfe72fc6..c4eb533529 100644
@@ -17,4 +17,8 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 __rte_format_printf(2, 0)
 int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c new file +28 -0
new file mode 100644
index 0000000000..cb34217af8
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <regex.h>
+#include <fnmatch.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <rte_os_shim.h>
+
+#include <rte_log.h>
+#include <rte_per_lcore.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+/* Stubs for Windows */
+int
+eal_log_syslog(const char *str __rte_unused)
+{
+	return -1;
+}
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +6 -0
index 04235f6ee5..37507299e7 100644
@@ -7,4 +7,10 @@ sources = files(
         'log_timestamp.c',
 )
 
+if is_windows
+	sources += files('log_stubs.c')
+else
+	sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
Signature · 1 line
2.43.0
#272 lore raw

Re: [PATCH v21 12/14] log: add optional support of syslog

Quoted 6 lines · On Mon, 3 Jun 2024 17:45:00 -0700 Stephen Hemminger…

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---

Ignore checkpatch complaints.
1. The tests should use the same style as other tests.

2. Checkpatch can't figure out code indent correctly with #ifdefs.

3. Checkpatch thinks stdio.h is spelling error.

#273 lore raw

PATCH v21 13/14 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   5 +
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |   2 +
 lib/log/log_stubs.c                 |  11 +-
 lib/log/meson.build                 |  10 +-
 lib/log/version.map                 |   1 +
 10 files changed, 255 insertions(+), 4 deletions(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +11 -0
index 59454bb473..42cdc4a1da 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1843,6 +1845,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
+
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
 #endif
 
 	case OPT_LOG_LEVEL_NUM:
@@ -2222,6 +2232,7 @@ eal_common_usage(void)
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +5 -0
index 4430b251a1..13d68402d9 100644
@@ -508,6 +508,11 @@ eal_log_init(const char *id)
 #else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+#ifdef RTE_EXEC_ENV_LINUX
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else
+#endif
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +2 -0
index c4eb533529..91976ab313 100644
@@ -20,5 +20,7 @@ int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
 
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c +10 -1
index cb34217af8..6b2099f57b 100644
@@ -20,9 +20,18 @@
 #include "log_internal.h"
 #include "log_private.h"
 
-/* Stubs for Windows */
+#ifdef RTE_EXEC_ENV_WINDOWS
 int
 eal_log_syslog(const char *str __rte_unused)
 {
 	return -1;
 }
+#endif
+
+#ifndef RTE_EXEC_ENV_LINUX
+int
+eal_log_journal(const char *str __rte_unused)
+{
+	return -1;
+}
+#endif
lib/log/meson.build +7 -3
index 37507299e7..0a80027326 100644
@@ -7,10 +7,14 @@ sources = files(
         'log_timestamp.c',
 )
 
-if is_windows
-	sources += files('log_stubs.c')
-else
+if not is_windows
 	sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+else
+	sources += files('log_stubs.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 14d6681a5f..7af97ece43 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal;
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.43.0
#274 lore raw

Re: [PATCH v21 13/14] log: add support for systemd journal

Quoted 10 lines · On Mon, 3 Jun 2024 17:45:01 -0700 Stephen Hemminger…

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

Same kind of bogus checkpatch warnings:
- stdio.h is not a spelling error
- the indent is correct, just that checkpatch can't handle #ifdef's

#275 lore raw

PATCH v21 14/14 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  15 +++
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  24 +++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 235 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 08f4866461..c6c05e2e1d 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 476dedb097..647c3fc28a 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 42cdc4a1da..b68b10e120 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1872,6 +1874,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2239,6 +2249,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +18 -6
index 13d68402d9..856c0a0a29 100644
@@ -503,10 +503,14 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 void
 eal_log_init(const char *id)
 {
+	bool is_terminal;
+
 #ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
+
+	is_terminal = _isatty(_fileno(stderr));
 #else
-	bool is_terminal = isatty(STDERR_FILENO);
+	is_terminal = isatty(STDERR_FILENO);
 
 #ifdef RTE_EXEC_ENV_LINUX
 	if (log_journal_enabled())
@@ -516,11 +520,19 @@ eal_log_init(const char *id)
 	if (log_syslog_enabled(is_terminal))
 		log_syslog_open(id, is_terminal);
 	else
-#endif
-	if (log_timestamp_enabled())
-		rte_logs.print_func = log_print_with_timestamp;
-	else
-		rte_logs.print_func = vfprintf;
+#endif /* RTE_EXEC_ENV_WINDOWS */
+
+	if (log_color_enabled(is_terminal)) {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = color_print;
+	} else {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = log_print_with_timestamp;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index 91976ab313..5952bfb453 100644
@@ -23,4 +23,12 @@ void log_syslog_open(const char *id, bool is_terminal);
 bool log_journal_enabled(void);
 void log_journal_open(const char *id);
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 0a80027326..4041feed13 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 7af97ece43..eb3200dcde 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal;
 	eal_log_level2str;
Signature · 1 line
2.43.0
#276 lore raw

Re: [PATCH v21 14/14] log: colorize log output

Quoted 6 lines · On Mon, 3 Jun 2024 17:45:02 -0700 Stephen Hemminger…

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

Yet another valid patch that checkpatch complains about:
1. indent is correct, but it can't see #ifdefs
2. stdio is not a spelling error
3. it doesn't understand that FILE is a type, so it thinks it sees a multiply operator

#277 lore raw

v22 cover Logging improvements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v22 - rebase, rearrange some code to stifle some checkpatch complaints
and add release notes

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 +++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 ---
 doc/guides/prog_guide/log_lib.rst             |  72 ++++++
 doc/guides/rel_notes/release_24_11.rst        |  14 ++
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 136 +++++++-----
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  83 ++++---
 lib/log/log_color.c                           | 148 ++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 200 +++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  33 +++
 lib/log/log_stubs.c                           |  37 +++
 lib/log/log_syslog.c                          |  88 ++++++++
 lib/log/log_timestamp.c                       | 210 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  13 +-
 lib/log/version.map                           |   5 +-
 27 files changed, 1113 insertions(+), 377 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#278 lore raw

PATCH v22 1/15 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c5a703b5c0..ecf6f955cc 100644
@@ -185,6 +185,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#279 lore raw

PATCH v22 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#280 lore raw

PATCH v22 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.45.2
#281 lore raw

PATCH v22 4/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 45 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 ---------------------------
 lib/eal/linux/eal.c                 | 39 -------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 46 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +45 -0
index f1a5e329a5..b0ceeef632 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index d742cc98e2..0ded386472 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#282 lore raw

PATCH v22 5/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 0ded386472..7c26393d00 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.45.2
#283 lore raw

PATCH v22 6/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +6 -5
index 3e77995896..ad2be63cbb 100644
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#284 lore raw

PATCH v22 7/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index b0ceeef632..641c63998f 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1882,7 +1835,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 7c26393d00..5aedd348d1 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1113,8 +1113,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index a77e590a72..69a8fc8d80 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#285 lore raw

PATCH v22 8/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 5aedd348d1..fab633976d 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -959,9 +968,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1113,13 +1119,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 69a8fc8d80..c9648b7da7 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
#286 lore raw

PATCH v22 9/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 71d8dba731..a5c0c67357 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 641c63998f..2ca2a7a0c4 100644
@@ -2211,9 +2211,6 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
-#ifndef RTE_EXEC_ENV_WINDOWS
-	       "  --"OPT_SYSLOG"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 879567ba15..a0341196d4 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#287 lore raw

PATCH v22 10/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 6 +++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +5 -1
index 3fe86ddcd7..48543ee941 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -33,11 +34,13 @@ static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +77,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +474,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.45.2
#288 lore raw

PATCH v22 11/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   7 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 210 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 318 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index a5c0c67357..40dd288d5f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index 2ca2a7a0c4..27627fe5e4 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1843,7 +1845,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1851,7 +1853,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2215,6 +2224,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index fab633976d..ceaa1f9487 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index c9648b7da7..0fda2abb97 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +6 -1
index 48543ee941..6ab856272c 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -509,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
+
+__rte_format_printf(2, 0)
+int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +210 -0

210 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index a0341196d4..155f8b3bbe 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#289 lore raw

PATCH v22 12/15 log: add optional support of syslog

In reply to Stephen Hemminger

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 17 ++++
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 28 +++---
 lib/log/log_private.h                         |  3 +
 lib/log/log_stubs.c                           | 28 ++++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  6 ++
 9 files changed, 166 insertions(+), 41 deletions(-)
 create mode 100644 lib/log/log_stubs.c
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index 40dd288d5f..06295030b2 100644
@@ -987,9 +987,10 @@ test_misc_flags(void)
 	/* With empty --syslog */
 	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
 	/* With invalid --syslog */
-	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
 	const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
 			no_shconf, nosh_prefix, no_huge};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -108,30 +108,3 @@ Memory-related options
 *   ``--match-allocations``
 
     Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-*   ``--syslog <syslog facility>``
-
-    Set syslog facility. Valid syslog facilities are::
-
-        auth
-        cron
-        daemon
-        ftp
-        kern
-        lpr
-        mail
-        news
-        syslog
-        user
-        uucp
-        local0
-        local1
-        local2
-        local3
-        local4
-        local5
-        local6
-        local7
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
 
 	/path/to/app --log-timestamp=iso
 
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+    Redirect all log output to syslog.
+
+*auto*
+    Use console if it is a terminal, and use syslog if is not.
+
+*both*
+    Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +4 -1
index 27627fe5e4..8d5a83d871 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
@@ -2220,6 +2220,9 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -11
index 6ab856272c..4374cc81ff 100644
@@ -12,18 +12,19 @@
 #include <regex.h>
 #include <fnmatch.h>
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
-#include "log_internal.h"
-#include "log_private.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+#include "log_private.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
@@ -496,28 +497,33 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 	return ret;
 }
 
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
-	return -1;
-}
-
 /*
  * Called by rte_eal_init
  */
 void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
+	RTE_SET_USED(id);
+#else
+	bool is_terminal = isatty(STDERR_FILENO);
+
+	if (log_syslog_enabled(is_terminal)) {
+		log_syslog_open(id, is_terminal);
+		goto notice;
+	}
+#endif
 	if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
 		rte_logs.print_func = vfprintf;
 
+notice:
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
 #endif
+	return; /* needed for goto target */
 }
 
 /*
lib/log/log_private.h +3 -0
index 67cfe72fc6..e9a7a8829a 100644
@@ -17,4 +17,7 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 __rte_format_printf(2, 0)
 int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c new file +28 -0
new file mode 100644
index 0000000000..cb34217af8
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <regex.h>
+#include <fnmatch.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <rte_os_shim.h>
+
+#include <rte_log.h>
+#include <rte_per_lcore.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+/* Stubs for Windows */
+int
+eal_log_syslog(const char *str __rte_unused)
+{
+	return -1;
+}
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +6 -0
index 04235f6ee5..a4ceed491d 100644
@@ -7,4 +7,10 @@ sources = files(
         'log_timestamp.c',
 )
 
+if is_windows
+    sources += files('log_stubs.c')
+else
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
Signature · 1 line
2.45.2
#290 lore raw

PATCH v22 13/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   6 +
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |   2 +
 lib/log/log_stubs.c                 |  11 +-
 lib/log/meson.build                 |   3 +
 lib/log/version.map                 |   1 +
 10 files changed, 252 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +11 -0
index 8d5a83d871..59b9cdf5ff 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1843,6 +1845,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
+
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
 #endif
 
 	case OPT_LOG_LEVEL_NUM:
@@ -2222,6 +2232,7 @@ eal_common_usage(void)
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +6 -0
index 4374cc81ff..180011ae67 100644
@@ -508,6 +508,12 @@ eal_log_init(const char *id)
 #else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+#ifdef RTE_EXEC_ENV_LINUX
+	if (log_journal_enabled()) {
+		log_journal_open(id);
+		goto notice;
+	}
+#endif
 	if (log_syslog_enabled(is_terminal)) {
 		log_syslog_open(id, is_terminal);
 		goto notice;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +2 -0
index e9a7a8829a..cb7bb32f2c 100644
@@ -19,5 +19,7 @@ int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 
 bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
 
 #endif /* LOG_PRIVATE_H */
lib/log/log_stubs.c +10 -1
index cb34217af8..6b2099f57b 100644
@@ -20,9 +20,18 @@
 #include "log_internal.h"
 #include "log_private.h"
 
-/* Stubs for Windows */
+#ifdef RTE_EXEC_ENV_WINDOWS
 int
 eal_log_syslog(const char *str __rte_unused)
 {
 	return -1;
 }
+#endif
+
+#ifndef RTE_EXEC_ENV_LINUX
+int
+eal_log_journal(const char *str __rte_unused)
+{
+	return -1;
+}
+#endif
lib/log/meson.build +3 -0
index a4ceed491d..873c17238e 100644
@@ -11,6 +11,9 @@ if is_windows
     sources += files('log_stubs.c')
 else
     sources += files('log_syslog.c')
+if is_linux
+    sources += files('log_journal.c')
+endif
 endif
 
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 155f8b3bbe..b00657b98d 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal;
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#291 lore raw

PATCH v22 14/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  15 +++
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  25 +++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 236 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 06295030b2..6ee56ec97a 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 476dedb097..647c3fc28a 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 59b9cdf5ff..db9a18188a 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1872,6 +1874,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2239,6 +2249,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +19 -6
index 180011ae67..adccf2762b 100644
@@ -503,10 +503,14 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 void
 eal_log_init(const char *id)
 {
+	bool is_terminal;
+
 #ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
+
+	is_terminal = _isatty(_fileno(stderr));
 #else
-	bool is_terminal = isatty(STDERR_FILENO);
+	is_terminal = isatty(STDERR_FILENO);
 
 #ifdef RTE_EXEC_ENV_LINUX
 	if (log_journal_enabled()) {
@@ -518,11 +522,20 @@ eal_log_init(const char *id)
 		log_syslog_open(id, is_terminal);
 		goto notice;
 	}
-#endif
-	if (log_timestamp_enabled())
-		rte_logs.print_func = log_print_with_timestamp;
-	else
-		rte_logs.print_func = vfprintf;
+
+#endif /* RTE_EXEC_ENV_WINDOWS */
+
+	if (log_color_enabled(is_terminal)) {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = color_print;
+	} else {
+		if (log_timestamp_enabled())
+			rte_logs.print_func = log_print_with_timestamp;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 notice:
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index cb7bb32f2c..382ad0e892 100644
@@ -22,4 +22,12 @@ void log_syslog_open(const char *id, bool is_terminal);
 bool log_journal_enabled(void);
 void log_journal_open(const char *id);
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 873c17238e..8fa5a5a47c 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index b00657b98d..2611d3a22a 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal;
 	eal_log_level2str;
Signature · 1 line
2.45.2
#292 lore raw

PATCH v22 15/15 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
doc/guides/rel_notes/release_24_11.rst +14 -0
index 0ff70d9057..4ed483b06f 100644
@@ -55,6 +55,20 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Enhancements to logging library.**
+
+  * Log is initialized earlier in startup so all messages go through the log library.
+
+  * Log messages can be timestamped which is useful for debugging startup timing.
+
+  * The log now supports color in the log if going to a terminal device
+    similar to dmesg. The default format shows timestamp in green, subsystem
+    in yellow, and the message is bold, boldface or normal depending on severity.
+
+  * If DPDK is being used by a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
+  * On FreeBSD the log library uses syslog the same as Linux.
 
 Removed Items
 -------------
Signature · 1 line
2.45.2
#294 lore raw

v23 cover Logging improvements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v23 - simplify and fix Windows and FreeBSD builds; fix #ifdefs.
Change from defining stubs to using inline functions in log_private.h.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 +++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 ---
 doc/guides/prog_guide/log_lib.rst             |  72 ++++++
 doc/guides/rel_notes/release_24_11.rst        |  15 ++
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 140 +++++++-----
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  71 +++---
 lib/log/log_color.c                           | 148 ++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 200 +++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  61 +++++
 lib/log/log_syslog.c                          |  88 ++++++++
 lib/log/log_timestamp.c                       | 210 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 26 files changed, 1096 insertions(+), 377 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#295 lore raw

PATCH v23 1/15 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c5a703b5c0..ecf6f955cc 100644
@@ -185,6 +185,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
Acked-by on v23 1/15
#296 lore raw

Re: [PATCH v23 01/15] maintainers: add for log library

Quoted 22 lines · Stephen Hemminger

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c5a703b5c0..ecf6f955cc 100644
@@ -185,6 +185,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
#297 lore raw

PATCH v23 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
Acked-by on v23 2/15
#298 lore raw

Re: [PATCH v23 02/15] windows: make getopt functions have const properties

Quoted 13 lines · Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

#299 lore raw

PATCH v23 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.45.2
#300 lore raw

Re: [PATCH v23 03/15] windows: add os shim for localtime_r

Quoted 15 lines · Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +0 -0
index eda8113662..e9741a9df2 100644

lib/eal/windows/include/rte_os_shim.h rte_clock_gettime(clockid_t clock_id, struct timespec *tp) · line 114

Quoted 5 lines
lib/eal/windows/include/rte_os_shim.h +2 -0
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)

buf always means char *, but this function return struct tm *, suggest:
struct tm *localtime_r(const time_t *timep, struct tm *result)

Quoted 9 lines
lib/eal/windows/include/rte_os_shim.h +8 -0
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)
+
 #endif /* _RTE_OS_SHIM_ */
#301 lore raw

Re: [PATCH v23 03/15] windows: add os shim for localtime_r

Quoted 15 lines · On Wed, 18 Sep 2024 15:09:25 +0800 fengchengwen <[email protected]> wrote:

lib/eal/windows/include/rte_os_shim.h rte_clock_gettime(clockid_t clock_id, struct timespec *tp) · line 114

Quoted 10 lines
lib/eal/windows/include/rte_os_shim.h +2 -0
index eda8113662..e9741a9df2 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timer, struct tm *buf)  

buf always means char *, but this function return struct tm *, suggest:
struct tm *localtime_r(const time_t *timep, struct tm *result)

Quoted 7 lines

lib/eal/windows/include/rte_os_shim.h rte_clock_gettime(clockid_t clock_id, struct timespec *tp) · line 121

Quoted 7 lines
lib/eal/windows/include/rte_os_shim.h +7 -0
+{
+	if (localtime_s(buf, timer) == 0)
+		return buf;
+	else
+		return NULL;
+}
+#define localtime_r(timer, buf) rte_localtime_r(timer, buf)

This is a windows wrapper around the GNU extension localtime_r() so the signature needs to be the same, will change the name of the args to match man page.

struct tm *localtime_r(const time_t *restrict timep,

                           struct tm *restrict result);
#302 lore raw

PATCH v23 4/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 45 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 ---------------------------
 lib/eal/linux/eal.c                 | 39 -------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 46 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +45 -0
index f1a5e329a5..b0ceeef632 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index d742cc98e2..0ded386472 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#303 lore raw

Re: [PATCH v23 04/15] eal: make eal_log_level_parse common

Quoted 41 lines · Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 45 +++++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 ---------------------------
 lib/eal/linux/eal.c                 | 39 -------------------------
 lib/eal/windows/eal.c               | 35 ----------------------
 5 files changed, 46 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +19 -0
index f1a5e329a5..b0ceeef632 100644
@@ -1640,6 +1640,51 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,

lib/eal/common/eal_common_options.c eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out) · line 1671

Quoted 10 lines
lib/eal/common/eal_common_options.c +10 -0
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;

no need goto, could use break

Quoted 16 lines
lib/eal/common/eal_common_options.c +16 -0
+		default:
+			continue;
+		}
+	}
+out:
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+

...

#304 lore raw

Re: [PATCH v23 04/15] eal: make eal_log_level_parse common

Quoted 23 lines · On Wed, 18 Sep 2024 15:18:04 +0800 fengchengwen <[email protected]> wrote:
Quoted 23 lines
lib/eal/common/eal_common_options.c +23 -0
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
Quoted 8 lines

lib/eal/common/eal_common_options.c eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out) · line 1671

Quoted 6 lines
lib/eal/common/eal_common_options.c +6 -0
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		case '?':
+			/* getopt is not happy, stop right now */
+			goto out;  

no need goto, could use break

This function is only used to pre-scan options, it should just ignore anything it doesn't care about. Can remove the ? case and default part.

#305 lore raw

PATCH v23 5/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 0ded386472..7c26393d00 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.45.2
Acked-by on v23 5/15
#306 lore raw

Re: [PATCH v23 05/15] eal: do not duplicate rte_init_alert() messages

Quoted 40 lines · Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 0ded386472..7c26393d00 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
#307 lore raw

PATCH v23 6/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +6 -5
index 3e77995896..ad2be63cbb 100644
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#308 lore raw

Re: [PATCH v23 06/15] eal: change rte_exit() output to match rte_log()

Quoted 23 lines · Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +0 -0
index 3e77995896..ad2be63cbb 100644

lib/eal/common/eal_common_debug.c void · line 37

Quoted 4 lines
lib/eal/common/eal_common_debug.c +1 -0
@@ -34,17 +34,18 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char msg[256];

the length maybe too short.

lib/eal/common/eal_common_debug.c void · line 43

Quoted 9 lines
lib/eal/common/eal_common_debug.c +2 -3
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
-	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	vsnprintf(msg, sizeof(msg), format, ap);

should handle the vsnprintf return negative value.

Quoted 10 lines
lib/eal/common/eal_common_debug.c +3 -2
 	va_end(ap);
 
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
+
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
#309 lore raw

PATCH v23 7/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index b0ceeef632..641c63998f 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1882,7 +1835,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 7c26393d00..5aedd348d1 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1113,8 +1113,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index a77e590a72..69a8fc8d80 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#311 lore raw

PATCH v23 8/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 5aedd348d1..fab633976d 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -959,9 +968,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1113,13 +1119,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 69a8fc8d80..c9648b7da7 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
Acked-by on v23 8/15
#312 lore raw

Re: [PATCH v23 08/15] eal: initialize log before everything else

Quoted 12 lines · Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

#313 lore raw

PATCH v23 9/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 71d8dba731..a5c0c67357 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 641c63998f..2ca2a7a0c4 100644
@@ -2211,9 +2211,6 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
-#ifndef RTE_EXEC_ENV_WINDOWS
-	       "  --"OPT_SYSLOG"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 879567ba15..a0341196d4 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#314 lore raw

PATCH v23 10/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 6 +++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +5 -1
index 3fe86ddcd7..48543ee941 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -33,11 +34,13 @@ static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +77,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +474,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.45.2
#316 lore raw

PATCH v23 11/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   7 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 210 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 318 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index a5c0c67357..40dd288d5f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index 2ca2a7a0c4..27627fe5e4 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1843,7 +1845,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1851,7 +1853,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2215,6 +2224,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index fab633976d..ceaa1f9487 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index c9648b7da7..0fda2abb97 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +6 -1
index 48543ee941..6ab856272c 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -509,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
+
+__rte_format_printf(2, 0)
+int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +210 -0

210 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index a0341196d4..155f8b3bbe 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#317 lore raw

Re: [PATCH v23 11/15] log: add timestamp option

Quoted 20 lines · Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected

...

lib/log/log_timestamp.c line 27

Quoted 8 lines
lib/log/log_timestamp.c new file +8 -0
+
+static enum {
+	LOG_TIMESTAMP_NONE = 0,
+	LOG_TIMESTAMP_TIME,	/* time since start */
+	LOG_TIMESTAMP_DELTA,	/* time since last message */
+	LOG_TIMESTAMP_RELTIME,  /* relative time since last message */
+	LOG_TIMESTAMP_CTIME,	/* Unix standard time format */
+	LOG_TIMESTAMP_ISO,	/* ISO8601 time format */

Some of the impl should consider multiple-thread safety.

And for multiple-process, how about the secondary-processes align the main-process.

#318 lore raw

Re: [PATCH v23 11/15] log: add timestamp option

Quoted 13 lines · On Wed, 18 Sep 2024 15:37:49 +0800 fengchengwen <[email protected]> wrote:

...

lib/log/log_timestamp.c line 27

Quoted 8 lines
lib/log/log_timestamp.c new file +8 -0
+
+static enum {
+	LOG_TIMESTAMP_NONE = 0,
+	LOG_TIMESTAMP_TIME,	/* time since start */
+	LOG_TIMESTAMP_DELTA,	/* time since last message */
+	LOG_TIMESTAMP_RELTIME,  /* relative time since last message */
+	LOG_TIMESTAMP_CTIME,	/* Unix standard time format */
+	LOG_TIMESTAMP_ISO,	/* ISO8601 time format */  

Some of the impl should consider multiple-thread safety.

Quoted 1 line

And for multiple-process, how about the secondary-processes align the main-process.

As much as possible, they are thread safe, that is why locatime_r is used. Of course if multiple threads are printing it is possible that time stamps could be out of order. I.e CPU A got timestamp and is formatting message, and CPU B got timestamp is formatting message. The formatting might take longer for A.

#319 lore raw

Re: [PATCH v23 11/15] log: add timestamp option

Quoted 16 lines · Stephen Hemminger
Quoted 13 lines · On Wed, 18 Sep 2024 15:37:49 +0800 fengchengwen <[email protected]> wrote:

...

lib/log/log_timestamp.c line 27

Quoted 8 lines
lib/log/log_timestamp.c new file +8 -0
+
+static enum {
+	LOG_TIMESTAMP_NONE = 0,
+	LOG_TIMESTAMP_TIME,	/* time since start */
+	LOG_TIMESTAMP_DELTA,	/* time since last message */
+	LOG_TIMESTAMP_RELTIME,  /* relative time since last message */
+	LOG_TIMESTAMP_CTIME,	/* Unix standard time format */
+	LOG_TIMESTAMP_ISO,	/* ISO8601 time format */  

Some of the impl should consider multiple-thread safety.

Quoted 7 lines
Quoted 1 line

And for multiple-process, how about the secondary-processes align the main-process.

As much as possible, they are thread safe, that is why locatime_r is used. Of course if multiple threads are printing it is possible that time stamps could be out of order. I.e CPU A got timestamp and is formatting message, and CPU B got timestamp is formatting message. The formatting might take longer for A.

Yes, the localtime_r is thread safe, but like delta, multi thread will both read and update global variable log_time.previous with any sync, this may lead problem. static struct {
struct timespec started; /* when log was initialized */
struct timespec previous; /* when last msg was printed */
} log_time;

e.g.
1, the previous tv_sec = 1000, tv_nsec = 90000;
2, thread A invoke log, and current tv_sec = 2000, tv_nsec = 10000; it will update the previous
3, thread B also invoke log, and current tv_sec = 2000, tv_nsec = 10001, but it read previous is tv_sec = 2000, tv_nsec = 90000
and the delta will invalid.

#320 lore raw

PATCH v23 12/15 log: add optional support of syslog

In reply to Stephen Hemminger

Log to syslog only if option is specified. And if syslog is used then normally only log to syslog, don't duplicate output. Also enables syslog support on FreeBSD.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 17 ++++
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 28 +++---
 lib/log/log_private.h                         | 17 ++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  4 +
 lib/log/version.map                           |  2 +-
 9 files changed, 150 insertions(+), 43 deletions(-)
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index 40dd288d5f..06295030b2 100644
@@ -987,9 +987,10 @@ test_misc_flags(void)
 	/* With empty --syslog */
 	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
 	/* With invalid --syslog */
-	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
 	const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
 			no_shconf, nosh_prefix, no_huge};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -108,30 +108,3 @@ Memory-related options
 *   ``--match-allocations``
 
     Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-*   ``--syslog <syslog facility>``
-
-    Set syslog facility. Valid syslog facilities are::
-
-        auth
-        cron
-        daemon
-        ftp
-        kern
-        lpr
-        mail
-        news
-        syslog
-        user
-        uucp
-        local0
-        local1
-        local2
-        local3
-        local4
-        local5
-        local6
-        local7
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
 
 	/path/to/app --log-timestamp=iso
 
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+    Redirect all log output to syslog.
+
+*auto*
+    Use console if it is a terminal, and use syslog if is not.
+
+*both*
+    Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +4 -1
index 27627fe5e4..8d5a83d871 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
@@ -2220,6 +2220,9 @@ eal_common_usage(void)
 	       "                      (can be used multiple times)\n"
 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+	       "  --"OPT_SYSLOG"[=<when>]   Enable use of syslog\n"
+#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +16 -12
index 6ab856272c..f748551bc0 100644
@@ -12,18 +12,19 @@
 #include <regex.h>
 #include <fnmatch.h>
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
-#include "log_internal.h"
-#include "log_private.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+#include "log_private.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
@@ -496,20 +497,23 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 	return ret;
 }
 
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
-	return -1;
-}
-
 /*
  * Called by rte_eal_init
  */
 void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
 {
-	if (log_timestamp_enabled())
+	bool is_terminal;
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+	is_terminal = _isatty(_fileno(stderr));
+#else
+	is_terminal = isatty(STDERR_FILENO);
+#endif
+
+	if (log_syslog_enabled(is_terminal))
+		log_syslog_open(id, is_terminal);
+	else if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
 		rte_logs.print_func = vfprintf;
lib/log/log_private.h +17 -0
index 67cfe72fc6..532a481340 100644
@@ -17,4 +17,21 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 __rte_format_printf(2, 0)
 int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
 
+#ifdef RTE_EXEC_ENV_WINDOWS
+static inline bool
+log_syslog_enabled(bool is_tty __rte_unused)
+{
+	return false;
+}
+
+static inline void
+log_syslog_open(const char *id __rte_unused, bool is_terminal __rte_unused)
+{
+}
+#else
+
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+#endif
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +4 -0
index 04235f6ee5..4ac232786e 100644
@@ -7,4 +7,8 @@ sources = files(
         'log_timestamp.c',
 )
 
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -1
index 155f8b3bbe..8be6907840 100644
@@ -29,7 +29,7 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_syslog;
+	eal_log_syslog; # WINDOWS_NO_EXPORT
 	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2