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 2 of 5

lore
Share & tools
lore
#129 lore raw

PATCH v13 6/11 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_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 +
 9 files changed, 68 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_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
#130 lore raw

PATCH v13 7/11 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
#131 lore raw

PATCH v13 8/11 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#132 lore raw

PATCH v13 9/11 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#133 lore raw

PATCH v13 10/11 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#134 lore raw

PATCH v13 11/11 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           |   2 +-
 lib/log/log.c                                 | 101 ++++++++++++++++--
 5 files changed, 114 insertions(+), 38 deletions(-)
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 +1 -1
index 5173835c2c..16884c5aa3 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    },
lib/log/log.c +93 -8

148 lines not on this page · raw message

Signature · 1 line
2.43.0
#135 lore raw

v14 cover Logging unification and improvments

In reply to Stephen Hemminger

Improvements and unification of logging library (for 24.07 release). 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.

I find color helpful because 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...
Will add a release note in next release (after this is merged)

v14 - fix Windows build, by having common asprintf shim
fix asprintf memory leaks
add log stream when using journal

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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             |  57 ++
 drivers/bus/pci/pci_common.c                  |  32 -
 lib/eal/common/eal_common_debug.c             |  10 +-
 lib/eal/common/eal_common_options.c           | 117 ++--
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 +-
 lib/eal/linux/eal.c                           |  68 +-
 lib/eal/windows/eal.c                         |  77 +--
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  56 ++
 lib/log/log.c                                 | 633 +++++++++++++++++-
 lib/log/log_freebsd.c                         |   5 +-
 lib/log/log_internal.h                        |  25 +-
 lib/log/log_linux.c                           |  61 --
 lib/log/log_windows.c                         |  18 -
 lib/log/meson.build                           |   5 +-
 lib/log/version.map                           |   4 +-
 22 files changed, 942 insertions(+), 428 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#136 lore raw

PATCH v14 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 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
#137 lore raw

PATCH v14 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
#138 lore raw

PATCH v14 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
#139 lore raw

PATCH v14 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 | 46 +++++++++++++++++++++++++++
 4 files changed, 46 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 +46 -0

56 lines not on this page · raw message

Signature · 1 line
2.43.0
#140 lore raw

PATCH v14 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
#141 lore raw

PATCH v14 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
#142 lore raw

PATCH v14 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 | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +5 -5
index 3e77995896..71bb5a7d34 100644
@@ -34,17 +34,17 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char *msg = NULL;
 
 	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);
+	if (vasprintf(&msg, format, ap) > 0)
+		rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
 	va_end(ap);
 
 	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
#143 lore raw

PATCH v14 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_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 +
 9 files changed, 68 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_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
#144 lore raw

PATCH v14 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
#145 lore raw

PATCH v14 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#146 lore raw

PATCH v14 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#147 lore raw

PATCH v14 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#148 lore raw

PATCH v14 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                                 | 101 ++++++++++++++++--
 5 files changed, 117 insertions(+), 38 deletions(-)
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 +93 -8

148 lines not on this page · raw message

Signature · 1 line
2.43.0
#149 lore raw

PATCH v14 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/

---
 lib/log/log.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 160 insertions(+), 2 deletions(-)
lib/log/log.c +160 -2
index d8974c66db..8e2319b3f0 100644
@@ -17,6 +17,10 @@
 #include <rte_os_shim.h>
 #else
 #include <syslog.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #endif
 
 #include <rte_log.h>
@@ -56,6 +60,7 @@ static struct rte_logs {
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 #ifndef RTE_EXEC_ENV_WINDOWS
 	enum eal_log_syslog syslog_opt;
+	int journal_fd;
 #endif
 	log_print_t print_func;
 
@@ -758,6 +763,146 @@ static cookie_io_functions_t syslog_log_func = {
 	.write = syslog_log_write,
 	.close = syslog_log_close,
 };
+
+/*
+ * send message using journal protocol to journald
+ */
+static int
+journal_send(uint32_t level, const char *buf, size_t len)
+{
+	struct iovec iov[3];
+	char msg[] = "MESSAGE=";
+	char prio[32];
+	int ret;
+
+	iov[0].iov_base = msg;
+	iov[0].iov_len = strlen(msg);
+
+	iov[1].iov_base = (char *)(uintptr_t)buf;
+	iov[1].iov_len = len;
+
+	/* priority value between 0 ("emerg") and 7 ("debug") */
+	iov[2].iov_base = prio;
+	iov[2].iov_len = snprintf(prio, sizeof(prio),
+				  "PRIORITY=%i\n", level - 1);
+
+	ret = writev(rte_logs.journal_fd, iov, 3);
+	return ret;
+}
+
+__rte_format_printf(3, 0)
+static int
+journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap)
+{
+	char *buf = NULL;
+	int ret, len;
+
+	len = vasprintf(&buf, format, ap);
+	if (len == 0)
+		return 0;
+
+	/* check that message ends with newline, if not add one */
+	if (buf[len - 1] != '\n') {
+		char *clone = malloc(len + 1);
+		if (clone == NULL) {
+			free(buf);
+			return 0;
+		}
+
+		memcpy(clone, buf, len);
+		clone[len++] = '\n';
+		free(buf);
+		buf = clone;
+	}
+
+	ret = journal_send(level, buf, len);
+	free(buf);
+	return ret;
+}
+
+/* wrapper for log stream to put messages into journal */
+static ssize_t
+journal_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	return journal_send(rte_log_cur_msg_loglevel(), buf, size);
+}
+
+static cookie_io_functions_t journal_log_func = {
+	.write = journal_log_write,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ *
+ */
+static bool
+using_journal(void)
+{
+	char *jenv, *endp = NULL;
+	struct stat st;
+	unsigned long dev, ino;
+
+	jenv = getenv("JOURNAL_STREAM");
+	if (jenv == NULL)
+		return false;
+
+	if (fstat(STDERR_FILENO, &st) < 0)
+		return false;
+
+	/* systemd sets colon-separated list of device and inode number */
+	dev = strtoul(jenv, &endp, 10);
+	if (endp == NULL || *endp != ':')
+		return false;	/* missing colon */
+
+	ino = strtoul(endp + 1, NULL, 10);
+
+	return dev == st.st_dev && ino == st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+static int
+open_journal(const char *id)
+{
+	char *syslog_id = NULL;
+	struct sockaddr_un sun = {
+		.sun_family = AF_UNIX,
+		.sun_path = "/run/systemd/journal/socket",
+	};
+	ssize_t len;
+	int s;
+
+	s = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0)
+		return -1;
+
+	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
+		goto error;
+
+	/* Send syslog identifier as first message */
+	len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id);
+	if (len == 0)
+		goto error;
+
+	if (write(s, syslog_id, len) != len)
+		goto error;
+
+	free(syslog_id);
+
+	/* redirect other log messages to journal */
+	FILE *log_stream = fopencookie(NULL, "w", journal_log_func);
+	if (log_stream != NULL)
+		default_log_stream = log_stream;
+
+	return s;
+
+error:
+	free(syslog_id);
+	close(s);
+	return -1;
+}
 #endif
 
 
@@ -765,11 +910,24 @@ static cookie_io_functions_t syslog_log_func = {
 static void
 log_output_selection(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
-
-#ifndef RTE_EXEC_ENV_WINDOWS
+#else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+	/* If stderr is redirected to systemd journal then upgrade */
+	if (using_journal()) {
+		int jfd = open_journal(id);
+
+		if (jfd < 0) {
+			RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s",
+				     strerror(errno));
+		} else {
+			rte_logs.print_func = journal_print;
+			return;
+		}
+	}
+
 	if (!(rte_logs.syslog_opt == EAL_LOG_SYSLOG_NONE ||
 	      (rte_logs.syslog_opt == EAL_LOG_SYSLOG_AUTO && is_terminal))) {
 		int flags = LOG_NDELAY | LOG_PID;
Signature · 1 line
2.43.0
#150 lore raw

PATCH v14 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 |   2 +
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       | 163 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   5 +
 lib/log/version.map                 |   1 +
 7 files changed, 208 insertions(+), 5 deletions(-)
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 abaedc7212..40727ebaae 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
 ~~~~~~~~~~~~~
 
@@ -101,7 +116,6 @@ option. There are three possible settings for this option:
 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 +2 -0
index 9ca7db04aa..709605e722 100644
@@ -75,6 +75,7 @@ eal_long_options[] = {
 	{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_LOG_COLOR,		1, NULL, OPT_LOG_COLOR_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   },
@@ -2229,6 +2230,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 +2 -0
index e24c9eca53..5a63c1dd3a 100644
@@ -37,6 +37,8 @@ enum {
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/log/log.c +159 -4

207 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 7c7d44eed2..525e1397fd 100644
@@ -47,5 +47,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/version.map +1 -0
index 14d6681a5f..7fa79b20ff 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_level2str;
 	eal_log_save_pattern;
Signature · 1 line
2.43.0
#151 lore raw

v15 cover Logging unification and improvements

In reply to Stephen Hemminger

Improvements and unification of logging library (for 24.07 release). 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.

I find color helpful because 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...
Will add a release note in next release (after this is merged)

v15 - fix log test cases
avoid use of malloc (ie vasprintf) in log path because malloc pool maybe corrupted.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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             |  57 ++
 drivers/bus/pci/pci_common.c                  |  32 -
 lib/eal/common/eal_common_debug.c             |  10 +-
 lib/eal/common/eal_common_options.c           | 126 ++--
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 +-
 lib/eal/linux/eal.c                           |  68 +-
 lib/eal/windows/eal.c                         |  77 +--
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  56 ++
 lib/log/log.c                                 | 646 +++++++++++++++++-
 lib/log/log_freebsd.c                         |   5 +-
 lib/log/log_internal.h                        |  25 +-
 lib/log/log_linux.c                           |  61 --
 lib/log/log_windows.c                         |  18 -
 lib/log/meson.build                           |   5 +-
 lib/log/version.map                           |   4 +-
 22 files changed, 964 insertions(+), 428 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#152 lore raw

PATCH v15 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 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
#153 lore raw

PATCH v15 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
#154 lore raw

PATCH v15 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
#155 lore raw

PATCH v15 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 | 46 +++++++++++++++++++++++++++
 4 files changed, 46 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 +46 -0

56 lines not on this page · raw message

Signature · 1 line
2.43.0
#156 lore raw

PATCH v15 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
#157 lore raw

PATCH v15 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
#158 lore raw

PATCH v15 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 | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
lib/eal/common/eal_common_debug.c +5 -5
index 3e77995896..71bb5a7d34 100644
@@ -34,17 +34,17 @@ void
 rte_exit(int exit_code, const char *format, ...)
 {
 	va_list ap;
+	char *msg = NULL;
 
 	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);
+	if (vasprintf(&msg, format, ap) > 0)
+		rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "EAL: Cause - %s", msg);
 	va_end(ap);
 
 	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
#159 lore raw

PATCH v15 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_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 +
 9 files changed, 68 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_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
#160 lore raw

PATCH v15 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
#161 lore raw

PATCH v15 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#162 lore raw

PATCH v15 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#163 lore raw

PATCH v15 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#164 lore raw

PATCH v15 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                                 | 121 ++++++++++++++++--
 5 files changed, 137 insertions(+), 38 deletions(-)
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 +113 -8

168 lines not on this page · raw message

Signature · 1 line
2.43.0
#165 lore raw

PATCH v15 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/

---
 lib/log/log.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 2 deletions(-)
lib/log/log.c +152 -2
index ec0d55273e..650d294120 100644
@@ -17,6 +17,10 @@
 #include <rte_os_shim.h>
 #else
 #include <syslog.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #endif
 
 #include <rte_log.h>
@@ -56,6 +60,7 @@ static struct rte_logs {
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 #ifndef RTE_EXEC_ENV_WINDOWS
 	enum eal_log_syslog syslog_opt;
+	int journal_fd;
 #endif
 	log_print_t print_func;
 
@@ -775,6 +780,138 @@ static cookie_io_functions_t syslog_log_func = {
 	.close = syslog_log_close,
 };
 
+/*
+ * send message using journal protocol to journald
+ */
+static int
+journal_send(uint32_t level, const char *buf, size_t len)
+{
+	struct iovec iov[3];
+	char msg[] = "MESSAGE=";
+	char prio[32];
+	int ret;
+
+	iov[0].iov_base = msg;
+	iov[0].iov_len = strlen(msg);
+
+	iov[1].iov_base = (char *)(uintptr_t)buf;
+	iov[1].iov_len = len;
+
+	/* priority value between 0 ("emerg") and 7 ("debug") */
+	iov[2].iov_base = prio;
+	iov[2].iov_len = snprintf(prio, sizeof(prio),
+				  "PRIORITY=%i\n", level - 1);
+
+	ret = writev(rte_logs.journal_fd, iov, 3);
+	return ret;
+}
+
+__rte_format_printf(3, 0)
+static int
+journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap)
+{
+	char buf[BUFSIZ];
+	size_t len;
+
+	len = vsnprintf(buf, sizeof(buf), format, ap);
+	if (len == 0)
+		return 0;
+
+	/* check for truncation */
+	if (len >= sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	/* check that message ends with newline, if not add one */
+	if (buf[len - 1] != '\n')
+		buf[len++] = '\n';
+
+	return journal_send(level, buf, len);
+}
+
+/* wrapper for log stream to put messages into journal */
+static ssize_t
+journal_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	return journal_send(rte_log_cur_msg_loglevel(), buf, size);
+}
+
+static cookie_io_functions_t journal_log_func = {
+	.write = journal_log_write,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ *
+ */
+static bool
+is_journal(int fd)
+{
+	char *jenv, *endp = NULL;
+	struct stat st;
+	unsigned long dev, ino;
+
+	jenv = getenv("JOURNAL_STREAM");
+	if (jenv == NULL)
+		return false;
+
+	if (fstat(fd, &st) < 0)
+		return false;
+
+	/* systemd sets colon-separated list of device and inode number */
+	dev = strtoul(jenv, &endp, 10);
+	if (endp == NULL || *endp != ':')
+		return false;	/* missing colon */
+
+	ino = strtoul(endp + 1, NULL, 10);
+
+	return dev == st.st_dev && ino == st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+static int
+open_journal(const char *id)
+{
+	char *syslog_id = NULL;
+	struct sockaddr_un sun = {
+		.sun_family = AF_UNIX,
+		.sun_path = "/run/systemd/journal/socket",
+	};
+	ssize_t len;
+	int s;
+
+	s = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0)
+		return -1;
+
+	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
+		goto error;
+
+	/* Send syslog identifier as first message */
+	len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id);
+	if (len == 0)
+		goto error;
+
+	if (write(s, syslog_id, len) != len)
+		goto error;
+
+	free(syslog_id);
+
+	/* redirect other log messages to journal */
+	FILE *log_stream = fopencookie(NULL, "w", journal_log_func);
+	if (log_stream != NULL)
+		default_log_stream = log_stream;
+
+	return s;
+
+error:
+	free(syslog_id);
+	close(s);
+	return -1;
+}
+
 static void
 log_open_syslog(const char *id, bool is_terminal)
 {
@@ -797,11 +934,24 @@ log_open_syslog(const char *id, bool is_terminal)
 static void
 log_output_selection(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
-
-#ifndef RTE_EXEC_ENV_WINDOWS
+#else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+	/* If stderr is redirected to systemd journal then upgrade */
+	if (!is_terminal && is_journal(STDERR_FILENO)) {
+		int jfd = open_journal(id);
+
+		if (jfd < 0) {
+			RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s",
+				     strerror(errno));
+		} else {
+			rte_logs.print_func = journal_print;
+			return;
+		}
+	}
+
 	if (using_syslog(is_terminal)) {
 		log_open_syslog(id, is_terminal);
 		return;
Signature · 1 line
2.43.0
#166 lore raw

PATCH v15 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        |   2 +
 lib/log/log.c                       | 164 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   5 +
 lib/log/version.map                 |   1 +
 7 files changed, 218 insertions(+), 5 deletions(-)
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 abaedc7212..40727ebaae 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
 ~~~~~~~~~~~~~
 
@@ -101,7 +116,6 @@ option. There are three possible settings for this option:
 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 +11 -0
index 9ca7db04aa..5e7ab29ae3 100644
@@ -75,6 +75,7 @@ eal_long_options[] = {
 	{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_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_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   },
@@ -1618,6 +1619,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1862,6 +1864,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) {
@@ -2229,6 +2239,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 +2 -0
index e24c9eca53..5a63c1dd3a 100644
@@ -37,6 +37,8 @@ enum {
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/log/log.c +160 -4

207 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 7c7d44eed2..525e1397fd 100644
@@ -47,5 +47,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/version.map +1 -0
index 14d6681a5f..7fa79b20ff 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_level2str;
 	eal_log_save_pattern;
Signature · 1 line
2.43.0
#167 lore raw

v16 cover Logging unification and improvements

In reply to Stephen Hemminger

Improvements and unification of logging library (for 24.07 release). 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.

I find color helpful because 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...
Will add a release note in next release (after this is merged)

v16 - add printf attribute to Windows shim
add missing va_end in color_fprintf
avoid allocation in rte_exit

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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             |  57 ++
 drivers/bus/pci/pci_common.c                  |  32 -
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 126 ++--
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 +-
 lib/eal/linux/eal.c                           |  68 +-
 lib/eal/windows/eal.c                         |  77 +--
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  58 ++
 lib/log/log.c                                 | 647 +++++++++++++++++-
 lib/log/log_freebsd.c                         |   5 +-
 lib/log/log_internal.h                        |  25 +-
 lib/log/log_linux.c                           |  61 --
 lib/log/log_windows.c                         |  18 -
 lib/log/meson.build                           |   5 +-
 lib/log/version.map                           |   4 +-
 22 files changed, 968 insertions(+), 428 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#168 lore raw

PATCH v16 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 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
#170 lore raw

PATCH v16 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
#171 lore raw

PATCH v16 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
Acked-by on v16 3/15
#172 lore raw

Re: [PATCH v16 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
@@ -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)

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

Quoted 10 lines
lib/eal/windows/include/rte_os_shim.h +9 -0
 
+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)

hm, i'm always a bit concerned about expressing platform standard names from dpdk api surface. i think we should just expose and use rte_localtime_r() and not present localtime_r.

can be treated as a suggestion.

#173 lore raw

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

Quoted 31 lines · On Wed, 27 Mar 2024 09:56:59 -0700 Tyler Retzlaff…
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
@@ -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)

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

Quoted 10 lines
lib/eal/windows/include/rte_os_shim.h +9 -0
 
+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)  

hm, i'm always a bit concerned about expressing platform standard names from dpdk api surface. i think we should just expose and use rte_localtime_r() and not present localtime_r.

Quoted 4 lines

can be treated as a suggestion.

I was just copying what clock_gettime was doing. But yes, should really do global update to rte_localtime()

#174 lore raw

PATCH v16 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
Acked-by on v16 4/15
#175 lore raw

Re: [PATCH v16 04/15] windows: common wrapper for vasprintf and asprintf

Quoted 9 lines · 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")

---

#176 lore raw

PATCH v16 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
#178 lore raw

PATCH v16 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
#180 lore raw

PATCH v16 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
Acked-by on v16 7/15
#181 lore raw

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

Quoted 7 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
Quoted 6 lines

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cause - Cannot init EAL: Permission denied

---

this version too

#182 lore raw

PATCH v16 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_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 +
 9 files changed, 68 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_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
#183 lore raw

PATCH v16 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
Acked-by on v16 9/15
#184 lore raw

Re: [PATCH v16 09/15] eal: initialize log before everything else

Quoted 11 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.

---

#185 lore raw

PATCH v16 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#186 lore raw

PATCH v16 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#187 lore raw

PATCH v16 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#188 lore raw

PATCH v16 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                                 | 121 ++++++++++++++++--
 5 files changed, 137 insertions(+), 38 deletions(-)
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 +113 -8

168 lines not on this page · raw message

Signature · 1 line
2.43.0
#189 lore raw

PATCH v16 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/

---
 lib/log/log.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 2 deletions(-)
lib/log/log.c +152 -2
index ec0d55273e..650d294120 100644
@@ -17,6 +17,10 @@
 #include <rte_os_shim.h>
 #else
 #include <syslog.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #endif
 
 #include <rte_log.h>
@@ -56,6 +60,7 @@ static struct rte_logs {
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 #ifndef RTE_EXEC_ENV_WINDOWS
 	enum eal_log_syslog syslog_opt;
+	int journal_fd;
 #endif
 	log_print_t print_func;
 
@@ -775,6 +780,138 @@ static cookie_io_functions_t syslog_log_func = {
 	.close = syslog_log_close,
 };
 
+/*
+ * send message using journal protocol to journald
+ */
+static int
+journal_send(uint32_t level, const char *buf, size_t len)
+{
+	struct iovec iov[3];
+	char msg[] = "MESSAGE=";
+	char prio[32];
+	int ret;
+
+	iov[0].iov_base = msg;
+	iov[0].iov_len = strlen(msg);
+
+	iov[1].iov_base = (char *)(uintptr_t)buf;
+	iov[1].iov_len = len;
+
+	/* priority value between 0 ("emerg") and 7 ("debug") */
+	iov[2].iov_base = prio;
+	iov[2].iov_len = snprintf(prio, sizeof(prio),
+				  "PRIORITY=%i\n", level - 1);
+
+	ret = writev(rte_logs.journal_fd, iov, 3);
+	return ret;
+}
+
+__rte_format_printf(3, 0)
+static int
+journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap)
+{
+	char buf[BUFSIZ];
+	size_t len;
+
+	len = vsnprintf(buf, sizeof(buf), format, ap);
+	if (len == 0)
+		return 0;
+
+	/* check for truncation */
+	if (len >= sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	/* check that message ends with newline, if not add one */
+	if (buf[len - 1] != '\n')
+		buf[len++] = '\n';
+
+	return journal_send(level, buf, len);
+}
+
+/* wrapper for log stream to put messages into journal */
+static ssize_t
+journal_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	return journal_send(rte_log_cur_msg_loglevel(), buf, size);
+}
+
+static cookie_io_functions_t journal_log_func = {
+	.write = journal_log_write,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ *
+ */
+static bool
+is_journal(int fd)
+{
+	char *jenv, *endp = NULL;
+	struct stat st;
+	unsigned long dev, ino;
+
+	jenv = getenv("JOURNAL_STREAM");
+	if (jenv == NULL)
+		return false;
+
+	if (fstat(fd, &st) < 0)
+		return false;
+
+	/* systemd sets colon-separated list of device and inode number */
+	dev = strtoul(jenv, &endp, 10);
+	if (endp == NULL || *endp != ':')
+		return false;	/* missing colon */
+
+	ino = strtoul(endp + 1, NULL, 10);
+
+	return dev == st.st_dev && ino == st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+static int
+open_journal(const char *id)
+{
+	char *syslog_id = NULL;
+	struct sockaddr_un sun = {
+		.sun_family = AF_UNIX,
+		.sun_path = "/run/systemd/journal/socket",
+	};
+	ssize_t len;
+	int s;
+
+	s = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0)
+		return -1;
+
+	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
+		goto error;
+
+	/* Send syslog identifier as first message */
+	len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id);
+	if (len == 0)
+		goto error;
+
+	if (write(s, syslog_id, len) != len)
+		goto error;
+
+	free(syslog_id);
+
+	/* redirect other log messages to journal */
+	FILE *log_stream = fopencookie(NULL, "w", journal_log_func);
+	if (log_stream != NULL)
+		default_log_stream = log_stream;
+
+	return s;
+
+error:
+	free(syslog_id);
+	close(s);
+	return -1;
+}
+
 static void
 log_open_syslog(const char *id, bool is_terminal)
 {
@@ -797,11 +934,24 @@ log_open_syslog(const char *id, bool is_terminal)
 static void
 log_output_selection(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
-
-#ifndef RTE_EXEC_ENV_WINDOWS
+#else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+	/* If stderr is redirected to systemd journal then upgrade */
+	if (!is_terminal && is_journal(STDERR_FILENO)) {
+		int jfd = open_journal(id);
+
+		if (jfd < 0) {
+			RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s",
+				     strerror(errno));
+		} else {
+			rte_logs.print_func = journal_print;
+			return;
+		}
+	}
+
 	if (using_syslog(is_terminal)) {
 		log_open_syslog(id, is_terminal);
 		return;
Signature · 1 line
2.43.0
#190 lore raw

PATCH v16 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        |   2 +
 lib/log/log.c                       | 165 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   5 +
 lib/log/version.map                 |   1 +
 7 files changed, 219 insertions(+), 5 deletions(-)
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 abaedc7212..40727ebaae 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
 ~~~~~~~~~~~~~
 
@@ -101,7 +116,6 @@ option. There are three possible settings for this option:
 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 +11 -0
index 9ca7db04aa..5e7ab29ae3 100644
@@ -75,6 +75,7 @@ eal_long_options[] = {
 	{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_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_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   },
@@ -1618,6 +1619,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1862,6 +1864,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) {
@@ -2229,6 +2239,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 +2 -0
index e24c9eca53..5a63c1dd3a 100644
@@ -37,6 +37,8 @@ enum {
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/log/log.c +161 -4

208 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 7c7d44eed2..525e1397fd 100644
@@ -47,5 +47,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/version.map +1 -0
index 14d6681a5f..7fa79b20ff 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_level2str;
 	eal_log_save_pattern;
Signature · 1 line
2.43.0
#191 lore raw

v17 cover Logging unification and improvements

In reply to Stephen Hemminger

Improvements and unification of logging library (for 24.07 release). 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.

I find color helpful because 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...
Will add a release note in next release (after this is merged)

v17 - fix isatty incompatability on Windows

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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             |  57 ++
 drivers/bus/pci/pci_common.c                  |  32 -
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 126 ++--
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 +-
 lib/eal/linux/eal.c                           |  68 +-
 lib/eal/windows/eal.c                         |  77 +--
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  58 ++
 lib/log/log.c                                 | 651 +++++++++++++++++-
 lib/log/log_freebsd.c                         |   5 +-
 lib/log/log_internal.h                        |  25 +-
 lib/log/log_linux.c                           |  61 --
 lib/log/log_windows.c                         |  18 -
 lib/log/meson.build                           |   5 +-
 lib/log/version.map                           |   4 +-
 22 files changed, 972 insertions(+), 428 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#192 lore raw

PATCH v17 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 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
#193 lore raw

PATCH v17 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
#194 lore raw

PATCH v17 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
#195 lore raw

PATCH v17 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
#196 lore raw

PATCH v17 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
#197 lore raw

PATCH v17 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
#198 lore raw

PATCH v17 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
#199 lore raw

PATCH v17 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_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 +
 9 files changed, 68 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_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
#200 lore raw

PATCH v17 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
#201 lore raw

PATCH v17 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#202 lore raw

PATCH v17 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#203 lore raw

PATCH v17 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#204 lore raw

PATCH v17 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                                 | 121 ++++++++++++++++--
 5 files changed, 137 insertions(+), 38 deletions(-)
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 +113 -8

168 lines not on this page · raw message

Signature · 1 line
2.43.0
#205 lore raw

PATCH v17 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/

---
 lib/log/log.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 2 deletions(-)
lib/log/log.c +152 -2
index ec0d55273e..650d294120 100644
@@ -17,6 +17,10 @@
 #include <rte_os_shim.h>
 #else
 #include <syslog.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #endif
 
 #include <rte_log.h>
@@ -56,6 +60,7 @@ static struct rte_logs {
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 #ifndef RTE_EXEC_ENV_WINDOWS
 	enum eal_log_syslog syslog_opt;
+	int journal_fd;
 #endif
 	log_print_t print_func;
 
@@ -775,6 +780,138 @@ static cookie_io_functions_t syslog_log_func = {
 	.close = syslog_log_close,
 };
 
+/*
+ * send message using journal protocol to journald
+ */
+static int
+journal_send(uint32_t level, const char *buf, size_t len)
+{
+	struct iovec iov[3];
+	char msg[] = "MESSAGE=";
+	char prio[32];
+	int ret;
+
+	iov[0].iov_base = msg;
+	iov[0].iov_len = strlen(msg);
+
+	iov[1].iov_base = (char *)(uintptr_t)buf;
+	iov[1].iov_len = len;
+
+	/* priority value between 0 ("emerg") and 7 ("debug") */
+	iov[2].iov_base = prio;
+	iov[2].iov_len = snprintf(prio, sizeof(prio),
+				  "PRIORITY=%i\n", level - 1);
+
+	ret = writev(rte_logs.journal_fd, iov, 3);
+	return ret;
+}
+
+__rte_format_printf(3, 0)
+static int
+journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap)
+{
+	char buf[BUFSIZ];
+	size_t len;
+
+	len = vsnprintf(buf, sizeof(buf), format, ap);
+	if (len == 0)
+		return 0;
+
+	/* check for truncation */
+	if (len >= sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	/* check that message ends with newline, if not add one */
+	if (buf[len - 1] != '\n')
+		buf[len++] = '\n';
+
+	return journal_send(level, buf, len);
+}
+
+/* wrapper for log stream to put messages into journal */
+static ssize_t
+journal_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	return journal_send(rte_log_cur_msg_loglevel(), buf, size);
+}
+
+static cookie_io_functions_t journal_log_func = {
+	.write = journal_log_write,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ *
+ */
+static bool
+is_journal(int fd)
+{
+	char *jenv, *endp = NULL;
+	struct stat st;
+	unsigned long dev, ino;
+
+	jenv = getenv("JOURNAL_STREAM");
+	if (jenv == NULL)
+		return false;
+
+	if (fstat(fd, &st) < 0)
+		return false;
+
+	/* systemd sets colon-separated list of device and inode number */
+	dev = strtoul(jenv, &endp, 10);
+	if (endp == NULL || *endp != ':')
+		return false;	/* missing colon */
+
+	ino = strtoul(endp + 1, NULL, 10);
+
+	return dev == st.st_dev && ino == st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+static int
+open_journal(const char *id)
+{
+	char *syslog_id = NULL;
+	struct sockaddr_un sun = {
+		.sun_family = AF_UNIX,
+		.sun_path = "/run/systemd/journal/socket",
+	};
+	ssize_t len;
+	int s;
+
+	s = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0)
+		return -1;
+
+	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
+		goto error;
+
+	/* Send syslog identifier as first message */
+	len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id);
+	if (len == 0)
+		goto error;
+
+	if (write(s, syslog_id, len) != len)
+		goto error;
+
+	free(syslog_id);
+
+	/* redirect other log messages to journal */
+	FILE *log_stream = fopencookie(NULL, "w", journal_log_func);
+	if (log_stream != NULL)
+		default_log_stream = log_stream;
+
+	return s;
+
+error:
+	free(syslog_id);
+	close(s);
+	return -1;
+}
+
 static void
 log_open_syslog(const char *id, bool is_terminal)
 {
@@ -797,11 +934,24 @@ log_open_syslog(const char *id, bool is_terminal)
 static void
 log_output_selection(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
-
-#ifndef RTE_EXEC_ENV_WINDOWS
+#else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+	/* If stderr is redirected to systemd journal then upgrade */
+	if (!is_terminal && is_journal(STDERR_FILENO)) {
+		int jfd = open_journal(id);
+
+		if (jfd < 0) {
+			RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s",
+				     strerror(errno));
+		} else {
+			rte_logs.print_func = journal_print;
+			return;
+		}
+	}
+
 	if (using_syslog(is_terminal)) {
 		log_open_syslog(id, is_terminal);
 		return;
Signature · 1 line
2.43.0
#206 lore raw

PATCH v17 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        |   2 +
 lib/log/log.c                       | 167 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   5 +
 lib/log/version.map                 |   1 +
 7 files changed, 222 insertions(+), 4 deletions(-)
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 abaedc7212..40727ebaae 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
 ~~~~~~~~~~~~~
 
@@ -101,7 +116,6 @@ option. There are three possible settings for this option:
 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 +11 -0
index 9ca7db04aa..5e7ab29ae3 100644
@@ -75,6 +75,7 @@ eal_long_options[] = {
 	{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_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_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   },
@@ -1618,6 +1619,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1862,6 +1864,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) {
@@ -2229,6 +2239,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 +2 -0
index e24c9eca53..5a63c1dd3a 100644
@@ -37,6 +37,8 @@ enum {
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/log/log.c +164 -3

210 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 7c7d44eed2..525e1397fd 100644
@@ -47,5 +47,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/version.map +1 -0
index 14d6681a5f..7fa79b20ff 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_level2str;
 	eal_log_save_pattern;
Signature · 1 line
2.43.0
#207 lore raw

v18 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.

I find color helpful because 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...

v18 - handle more Windows MSVC incompatabilities.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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             |  57 ++
 drivers/bus/pci/pci_common.c                  |  32 -
 lib/eal/common/eal_common_debug.c             |  11 +-
 lib/eal/common/eal_common_options.c           | 126 ++--
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 +-
 lib/eal/linux/eal.c                           |  68 +-
 lib/eal/windows/eal.c                         |  77 +--
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  58 ++
 lib/log/log.c                                 | 652 +++++++++++++++++-
 lib/log/log_freebsd.c                         |   5 +-
 lib/log/log_internal.h                        |  25 +-
 lib/log/log_linux.c                           |  61 --
 lib/log/log_windows.c                         |  18 -
 lib/log/meson.build                           |   5 +-
 lib/log/version.map                           |   4 +-
 22 files changed, 973 insertions(+), 428 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.43.0
#208 lore raw

PATCH v18 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 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
#209 lore raw

PATCH v18 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
#210 lore raw

PATCH v18 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
#211 lore raw

PATCH v18 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
#212 lore raw

PATCH v18 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
#213 lore raw

PATCH v18 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
#214 lore raw

PATCH v18 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
#215 lore raw

PATCH v18 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_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 +
 9 files changed, 68 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_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
#216 lore raw

PATCH v18 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
#217 lore raw

PATCH v18 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                       |  29 +++++---
 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 -
 8 files changed, 26 insertions(+), 153 deletions(-)
 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 +20 -9
index 255f757d94..f597da2e39 100644
@@ -70,12 +70,13 @@ struct log_cur_msg {
  /* per core log */
 static RTE_DEFINE_PER_LCORE(struct log_cur_msg, log_cur_msg);
 
-/* default logs */
-
 /* Change the stream that will be used by logging system */
 int
 rte_openlog_stream(FILE *f)
 {
+	if (rte_logs.file != NULL)
+		fclose(rte_logs.file);
+
 	rte_logs.file = f;
 	return 0;
 }
@@ -505,13 +506,20 @@ 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 environment-specific initialization functions.
+ * Called by rte_eal_init
  */
 void
-eal_log_set_default(FILE *default_log)
+eal_log_init(const char *id __rte_unused)
 {
-	default_log_stream = default_log;
+	default_log_stream = stderr;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +533,11 @@ eal_log_set_default(FILE *default_log)
 void
 rte_eal_log_cleanup(void)
 {
-	if (default_log_stream) {
-		fclose(default_log_stream);
-		default_log_stream = NULL;
-	}
+	FILE *log_stream = rte_log_get_stream();
+
+	/* don't close stderr on the application */
+	if (log_stream != stderr)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
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
#218 lore raw

PATCH v18 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
lib/log/log.c +16 -1
index f597da2e39..acd4c320b6 100644
@@ -26,16 +26,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+typedef int (*log_print_t)(FILE *f, uint32_t level, const char *fmt, va_list ap);
+static int log_print(FILE *f, uint32_t level, const char *format, va_list ap);
+
 /** 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 {
@@ -78,6 +83,7 @@ rte_openlog_stream(FILE *f)
 		fclose(rte_logs.file);
 
 	rte_logs.file = f;
+	rte_logs.print_func = log_print;
 	return 0;
 }
 
@@ -484,7 +490,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;
 }
@@ -513,6 +519,15 @@ eal_log_syslog(const char *mode __rte_unused)
 	return -1;
 }
 
+/* default log print function */
+__rte_format_printf(3, 0)
+static 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
  */
Signature · 1 line
2.43.0
#219 lore raw

PATCH v18 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                       | 183 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   9 ++
 lib/log/version.map                 |   1 +
 10 files changed, 268 insertions(+), 7 deletions(-)
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 +182 -1

231 lines not on this page · raw message

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/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
#220 lore raw

PATCH v18 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                                 | 121 ++++++++++++++++--
 5 files changed, 137 insertions(+), 38 deletions(-)
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 +113 -8

168 lines not on this page · raw message

Signature · 1 line
2.43.0
#221 lore raw

PATCH v18 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/

---
 lib/log/log.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 2 deletions(-)
lib/log/log.c +152 -2
index ec0d55273e..650d294120 100644
@@ -17,6 +17,10 @@
 #include <rte_os_shim.h>
 #else
 #include <syslog.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #endif
 
 #include <rte_log.h>
@@ -56,6 +60,7 @@ static struct rte_logs {
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
 #ifndef RTE_EXEC_ENV_WINDOWS
 	enum eal_log_syslog syslog_opt;
+	int journal_fd;
 #endif
 	log_print_t print_func;
 
@@ -775,6 +780,138 @@ static cookie_io_functions_t syslog_log_func = {
 	.close = syslog_log_close,
 };
 
+/*
+ * send message using journal protocol to journald
+ */
+static int
+journal_send(uint32_t level, const char *buf, size_t len)
+{
+	struct iovec iov[3];
+	char msg[] = "MESSAGE=";
+	char prio[32];
+	int ret;
+
+	iov[0].iov_base = msg;
+	iov[0].iov_len = strlen(msg);
+
+	iov[1].iov_base = (char *)(uintptr_t)buf;
+	iov[1].iov_len = len;
+
+	/* priority value between 0 ("emerg") and 7 ("debug") */
+	iov[2].iov_base = prio;
+	iov[2].iov_len = snprintf(prio, sizeof(prio),
+				  "PRIORITY=%i\n", level - 1);
+
+	ret = writev(rte_logs.journal_fd, iov, 3);
+	return ret;
+}
+
+__rte_format_printf(3, 0)
+static int
+journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap)
+{
+	char buf[BUFSIZ];
+	size_t len;
+
+	len = vsnprintf(buf, sizeof(buf), format, ap);
+	if (len == 0)
+		return 0;
+
+	/* check for truncation */
+	if (len >= sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	/* check that message ends with newline, if not add one */
+	if (buf[len - 1] != '\n')
+		buf[len++] = '\n';
+
+	return journal_send(level, buf, len);
+}
+
+/* wrapper for log stream to put messages into journal */
+static ssize_t
+journal_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	return journal_send(rte_log_cur_msg_loglevel(), buf, size);
+}
+
+static cookie_io_functions_t journal_log_func = {
+	.write = journal_log_write,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/
+ *
+ */
+static bool
+is_journal(int fd)
+{
+	char *jenv, *endp = NULL;
+	struct stat st;
+	unsigned long dev, ino;
+
+	jenv = getenv("JOURNAL_STREAM");
+	if (jenv == NULL)
+		return false;
+
+	if (fstat(fd, &st) < 0)
+		return false;
+
+	/* systemd sets colon-separated list of device and inode number */
+	dev = strtoul(jenv, &endp, 10);
+	if (endp == NULL || *endp != ':')
+		return false;	/* missing colon */
+
+	ino = strtoul(endp + 1, NULL, 10);
+
+	return dev == st.st_dev && ino == st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+static int
+open_journal(const char *id)
+{
+	char *syslog_id = NULL;
+	struct sockaddr_un sun = {
+		.sun_family = AF_UNIX,
+		.sun_path = "/run/systemd/journal/socket",
+	};
+	ssize_t len;
+	int s;
+
+	s = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0)
+		return -1;
+
+	if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
+		goto error;
+
+	/* Send syslog identifier as first message */
+	len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id);
+	if (len == 0)
+		goto error;
+
+	if (write(s, syslog_id, len) != len)
+		goto error;
+
+	free(syslog_id);
+
+	/* redirect other log messages to journal */
+	FILE *log_stream = fopencookie(NULL, "w", journal_log_func);
+	if (log_stream != NULL)
+		default_log_stream = log_stream;
+
+	return s;
+
+error:
+	free(syslog_id);
+	close(s);
+	return -1;
+}
+
 static void
 log_open_syslog(const char *id, bool is_terminal)
 {
@@ -797,11 +934,24 @@ log_open_syslog(const char *id, bool is_terminal)
 static void
 log_output_selection(const char *id)
 {
+#ifdef RTE_EXEC_ENV_WINDOWS
 	RTE_SET_USED(id);
-
-#ifndef RTE_EXEC_ENV_WINDOWS
+#else
 	bool is_terminal = isatty(STDERR_FILENO);
 
+	/* If stderr is redirected to systemd journal then upgrade */
+	if (!is_terminal && is_journal(STDERR_FILENO)) {
+		int jfd = open_journal(id);
+
+		if (jfd < 0) {
+			RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s",
+				     strerror(errno));
+		} else {
+			rte_logs.print_func = journal_print;
+			return;
+		}
+	}
+
 	if (using_syslog(is_terminal)) {
 		log_open_syslog(id, is_terminal);
 		return;
Signature · 1 line
2.43.0
#222 lore raw

PATCH v18 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        |   2 +
 lib/log/log.c                       | 168 +++++++++++++++++++++++++++-
 lib/log/log_internal.h              |   5 +
 lib/log/version.map                 |   1 +
 7 files changed, 223 insertions(+), 4 deletions(-)
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 abaedc7212..40727ebaae 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
 ~~~~~~~~~~~~~
 
@@ -101,7 +116,6 @@ option. There are three possible settings for this option:
 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 +11 -0
index 9ca7db04aa..5e7ab29ae3 100644
@@ -75,6 +75,7 @@ eal_long_options[] = {
 	{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_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_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   },
@@ -1618,6 +1619,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1862,6 +1864,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) {
@@ -2229,6 +2239,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 +2 -0
index e24c9eca53..5a63c1dd3a 100644
@@ -37,6 +37,8 @@ enum {
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/log/log.c +165 -3

211 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 7c7d44eed2..525e1397fd 100644
@@ -47,5 +47,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/version.map +1 -0
index 14d6681a5f..7fa79b20ff 100644
@@ -25,6 +25,7 @@ DPDK_24 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_level2str;
 	eal_log_save_pattern;
Signature · 1 line
2.43.0
#223 lore raw

v19 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...

v19 - split log outputs into seperate files, which makes
it more OO and cleaner.
- make journal log configurable (mostly for testing)

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
windows: common wrapper for vasprintf and asprintf
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 ++++++
 drivers/bus/pci/pci_common.c                  |  32 ---
 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/common/eal_private.h                  |  10 -
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  77 +------
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  58 +++++
 lib/log/log.c                                 |  87 ++++---
 lib/log/log_color.c                           | 160 +++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 216 ++++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  34 +++
 lib/log/log_stubs.c                           |  34 +++
 lib/log/log_syslog.c                          |  89 ++++++++
 lib/log/log_timestamp.c                       | 204 +++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  14 +-
 lib/log/version.map                           |   5 +-
 28 files changed, 1172 insertions(+), 448 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
#224 lore raw

PATCH v19 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 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