[v32,06/12] log: rework syslog handling

Message ID 20241108085710.2943741-7-david.marchand@redhat.com (mailing list archive)
State Accepted, archived
Delegated to: David Marchand
Headers
Series Log library enhancements |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

David Marchand Nov. 8, 2024, 8:57 a.m. UTC
From: Stephen Hemminger <stephen@networkplumber.org>

Refactor how syslog is handled, make it common to Linux and FreeBSD
The syslog facility property is better handled in lib/log
rather than in eal.
This also adds syslog support to FreeBSD.

Log to syslog only if option is specified.
If no --syslog is given then use only standard error.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Chengwen Feng <fengchengwen@huawei.com>
---
 app/test/test_eal_flags.c                     |  16 +--
 .../freebsd_gsg/freebsd_eal_parameters.rst    |  27 +++++
 .../prog_guide/env_abstraction_layer.rst      |   6 +-
 doc/guides/prog_guide/log_lib.rst             |   6 +-
 doc/guides/rel_notes/release_24_11.rst        |   6 +
 lib/eal/common/eal_common_options.c           |  57 +--------
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/freebsd/eal.c                         |   1 -
 lib/eal/linux/eal.c                           |   8 +-
 lib/eal/windows/eal.c                         |   2 +-
 lib/log/log.c                                 |  43 ++++---
 lib/log/log_freebsd.c                         |  12 --
 lib/log/log_internal.h                        |  11 +-
 lib/log/log_linux.c                           |  61 ----------
 lib/log/log_private.h                         |  27 +++++
 lib/log/log_syslog.c                          | 108 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 ---
 lib/log/meson.build                           |   6 +-
 lib/log/version.map                           |   2 +-
 19 files changed, 220 insertions(+), 198 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 delete mode 100644 lib/log/log_windows.c
  

Patch

diff --git a/app/test/test_eal_flags.c b/app/test/test_eal_flags.c
index 71d8dba731..9fcf0d56e6 100644
--- a/app/test/test_eal_flags.c
+++ b/app/test/test_eal_flags.c
@@ -985,12 +985,12 @@  test_misc_flags(void)
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog=user"};
+	/* With empty --syslog (now defaults) */
 	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* 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};
@@ -1080,15 +1080,15 @@  test_misc_flags(void)
 #endif
 
 	if (launch_proc(argv3) != 0) {
-		printf("Error - process did not run ok with --syslog flag\n");
+		printf("Error - process did not run ok with --syslog=user 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 run ok with --syslog flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
-		printf("Error - process run ok with invalid --syslog flag\n");
+		printf("Error - process run ok with --syslog=invalid flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv7) != 0) {
diff --git a/doc/guides/freebsd_gsg/freebsd_eal_parameters.rst b/doc/guides/freebsd_gsg/freebsd_eal_parameters.rst
index fba467a2ce..9270d9fa3b 100644
--- a/doc/guides/freebsd_gsg/freebsd_eal_parameters.rst
+++ b/doc/guides/freebsd_gsg/freebsd_eal_parameters.rst
@@ -18,3 +18,30 @@  FreeBSD-specific EAL parameters
 -------------------------------
 
 There are currently no FreeBSD-specific EAL command-line parameters available.
+
+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
diff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst
index 272aeeb4ba..04214a05b2 100644
--- a/doc/guides/prog_guide/env_abstraction_layer.rst
+++ b/doc/guides/prog_guide/env_abstraction_layer.rst
@@ -884,9 +884,9 @@  Signal Safety
   Other functions are not signal safe because they use one or more
   library routines that are not themselves signal safe.
   For example, calling ``rte_panic()`` is not safe in a signal handler
-  because it uses ``rte_log()`` and ``rte_log()`` calls the
-  ``syslog()`` library function which is in the list of
-  signal safe functions in
+  because it uses ``rte_log()`` and ``rte_log()`` may call ``vfprintf()`` or
+  ``syslog()`` library functions which are not in the list of
+  signal safe functions
   `Signal-Safety manual page <https://man7.org/linux/man-pages/man7/signal-safety.7.html>`_.
 
   The set of functions that are expected to be async-signal-safe in DPDK
diff --git a/doc/guides/prog_guide/log_lib.rst b/doc/guides/prog_guide/log_lib.rst
index ff9d1b54a2..9cee75b88c 100644
--- a/doc/guides/prog_guide/log_lib.rst
+++ b/doc/guides/prog_guide/log_lib.rst
@@ -5,9 +5,9 @@  Log Library
 ===========
 
 The DPDK Log library provides the logging functionality for other DPDK libraries and drivers.
-By default, in a Linux application, logs are sent to syslog and also to the console.
-On FreeBSD and Windows applications, logs are sent only to the console.
-However, the log function can be overridden by the user to use a different logging mechanism.
+By default, logs are sent only to standard error output of the process.
+The syslog EAL option can be used to redirect to the stystem logger on Linux and FreeBSD.
+In addition, the log can be redirected to a different stdio file stream.
 
 Log Levels
 ----------
diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst
index d93343fd52..f27d283fab 100644
--- a/doc/guides/rel_notes/release_24_11.rst
+++ b/doc/guides/rel_notes/release_24_11.rst
@@ -114,6 +114,12 @@  New Features
   (and vice versa); freeing the same pointer twice in the same routine;
   freeing an object that was not created by allocation; etc.
 
+* **Updated logging library**
+
+  * The syslog option has changed.
+    By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified.
+    Syslog is also supported on FreeBSD (but not on Windows).
+
 * **Updated Marvell cnxk mempool driver.**
 
   * Added mempool driver support for CN20K SoC.
diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index ab6cf8bebf..9f4feb2611 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -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>
@@ -93,7 +90,9 @@  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           },
+#ifndef RTE_EXEC_ENV_WINDOWS
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
+#endif
 	{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    },
@@ -349,10 +348,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 +1292,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)
 {
@@ -1645,6 +1599,7 @@  eal_option_is_log(int opt)
 {
 	switch (opt) {
 	case OPT_LOG_LEVEL_NUM:
+	case OPT_SYSLOG_NUM:
 		return true;
 	default:
 		return false;
@@ -1887,7 +1842,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;
@@ -2264,7 +2219,7 @@  eal_common_usage(void)
 	       "  --"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"
+	       "  --"OPT_SYSLOG"[=<facility>] Enable use of syslog (and optionally set facility)\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index 167ec501fa..f53ab8b4aa 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -84,7 +84,6 @@  struct internal_config {
 	/**< true if storing all pages within single files (per-page-size,
 	 * per-node) non-legacy mode only.
 	 */
-	volatile int syslog_facility;	  /**< facility passed to openlog() */
 	/** default interrupt mode for VFIO */
 	volatile enum rte_intr_mode vfio_intr_mode;
 	/** the shared VF token for VFIO-PCI bound PF and VFs devices */
diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c
index c84983ac3f..e7fd4f141e 100644
--- a/lib/eal/freebsd/eal.c
+++ b/lib/eal/freebsd/eal.c
@@ -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>
diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
index 3915cdb838..c321ea87f3 100644
--- a/lib/eal/linux/eal.c
+++ b/lib/eal/linux/eal.c
@@ -1104,13 +1104,7 @@  rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
+	eal_log_init(program_invocation_short_name);
 
 #ifdef VFIO_PRESENT
 	if (rte_vfio_enable("vfio")) {
diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c
index a3eb15ce00..b948c52670 100644
--- a/lib/eal/windows/eal.c
+++ b/lib/eal/windows/eal.c
@@ -251,7 +251,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);
 
 	/* parse log options as early as possible */
 	eal_parse_log_options(argc, argv);
diff --git a/lib/log/log.c b/lib/log/log.c
index 255f757d94..a5cae1f950 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -2,6 +2,7 @@ 
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,10 +13,12 @@ 
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -55,9 +58,6 @@  TAILQ_HEAD(rte_eal_opt_loglevel_list, rte_eal_opt_loglevel);
 static struct rte_eal_opt_loglevel_list opt_loglevel_list =
 	TAILQ_HEAD_INITIALIZER(opt_loglevel_list);
 
-/* Stream to use for logging if rte_logs.file is NULL */
-static FILE *default_log_stream;
-
 /**
  * This global structure stores some information about the message
  * that is currently being processed by one lcore
@@ -70,8 +70,6 @@  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)
@@ -85,17 +83,7 @@  rte_log_get_stream(void)
 {
 	FILE *f = rte_logs.file;
 
-	if (f == NULL) {
-		/*
-		 * Grab the current value of stderr here, rather than
-		 * just initializing default_log_stream to stderr. This
-		 * ensures that we will always use the current value
-		 * of stderr, even if the application closes and
-		 * reopens it.
-		 */
-		return default_log_stream != NULL ? default_log_stream : stderr;
-	}
-	return f;
+	return (f == NULL) ? stderr : f;
 }
 
 /* Set global log level */
@@ -506,12 +494,18 @@  rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 }
 
 /*
- * 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)
 {
-	default_log_stream = default_log;
+	FILE *logf = NULL;
+
+	if (log_syslog_enabled())
+		logf = log_syslog_open(id);
+
+	if (logf)
+		rte_openlog_stream(logf);
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
@@ -525,8 +519,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_logs.file;
+
+	/* don't close stderr on the application */
+	if (log_stream != NULL)
+		fclose(log_stream);
+
+	rte_logs.file = NULL;
 }
diff --git a/lib/log/log_freebsd.c b/lib/log/log_freebsd.c
deleted file mode 100644
index 698d3c5423..0000000000
--- a/lib/log/log_freebsd.c
+++ /dev/null
@@ -1,12 +0,0 @@ 
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
-{
-	return 0;
-}
diff --git a/lib/log/log_internal.h b/lib/log/log_internal.h
index 451629f1c1..3c46328e7b 100644
--- a/lib/log/log_internal.h
+++ b/lib/log/log_internal.h
@@ -14,13 +14,7 @@ 
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
-
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
+void eal_log_init(const char *id);
 
 /*
  * Save a log option for later.
@@ -30,6 +24,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.
  */
diff --git a/lib/log/log_linux.c b/lib/log/log_linux.c
deleted file mode 100644
index 2dfb0c974b..0000000000
--- a/lib/log/log_linux.c
+++ /dev/null
@@ -1,61 +0,0 @@ 
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <syslog.h>
-
-#include <rte_log.h>
-
-#include "log_internal.h"
-
-/*
- * default log function
- */
-static ssize_t
-console_log_write(__rte_unused void *c, const char *buf, size_t size)
-{
-	ssize_t ret;
-
-	/* write on stderr */
-	ret = fwrite(buf, 1, size, stderr);
-	fflush(stderr);
-
-	/* Syslog error levels are from 0 to 7, so subtract 1 to convert */
-	syslog(rte_log_cur_msg_loglevel() - 1, "%.*s", (int)size, buf);
-
-	return ret;
-}
-
-static int
-console_log_close(__rte_unused void *c)
-{
-	closelog();
-	return 0;
-}
-
-static cookie_io_functions_t console_log_func = {
-	.write = console_log_write,
-	.close = console_log_close,
-};
-
-/*
- * set the log to default function, called during eal init process,
- * once memzones are available.
- */
-int
-eal_log_init(const char *id, int facility)
-{
-	FILE *log_stream;
-
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
-	openlog(id, LOG_NDELAY | LOG_PID, facility);
-
-	eal_log_set_default(log_stream);
-
-	return 0;
-}
diff --git a/lib/log/log_private.h b/lib/log/log_private.h
new file mode 100644
index 0000000000..d5a8bf271a
--- /dev/null
+++ b/lib/log/log_private.h
@@ -0,0 +1,27 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+static inline bool
+log_syslog_enabled(void)
+{
+	return false;
+}
+static inline FILE *
+log_syslog_open(const char *id __rte_unused)
+{
+	return NULL;
+}
+#else
+bool log_syslog_enabled(void);
+FILE *log_syslog_open(const char *id);
+#endif
+
+#endif /* LOG_PRIVATE_H */
diff --git a/lib/log/log_syslog.c b/lib/log/log_syslog.c
new file mode 100644
index 0000000000..6b34831bf3
--- /dev/null
+++ b/lib/log/log_syslog.c
@@ -0,0 +1,108 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <syslog.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+static int log_facility;
+
+/*
+ * Usable list of facilities
+ * Skip kern, mark, and security
+ */
+static const struct {
+	const char *name;
+	int value;
+} facilitys[] = {
+	{ "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 },
+};
+
+int
+eal_log_syslog(const char *name)
+{
+	unsigned int i;
+
+	if (name == NULL) {
+		log_facility = LOG_DAEMON;
+		return 0;
+	}
+
+	for (i = 0; i < RTE_DIM(facilitys); i++) {
+		if (!strcmp(name, facilitys[i].name)) {
+			log_facility = facilitys[i].value;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+/* syslog is enabled if facility is set */
+bool
+log_syslog_enabled(void)
+{
+	return log_facility != 0; /* LOG_KERN is 0 */
+}
+
+/*
+ * default log function
+ */
+static ssize_t
+log_syslog_write(__rte_unused void *c, const char *buf, size_t size)
+{
+	/* Syslog error levels are from 0 to 7, so subtract 1 to convert */
+	syslog(rte_log_cur_msg_loglevel() - 1, "%.*s", (int)size, buf);
+
+	return size;
+}
+
+static int
+log_syslog_close(__rte_unused void *c)
+{
+	closelog();
+	return 0;
+}
+
+static cookie_io_functions_t log_syslog_func = {
+	.write = log_syslog_write,
+	.close = log_syslog_close,
+};
+
+
+FILE *
+log_syslog_open(const char *id)
+{
+	int option = LOG_CONS | LOG_NDELAY | LOG_PID | LOG_PERROR;
+
+	openlog(id, option, log_facility);
+
+	/* redirect other log messages to syslog as well */
+	return fopencookie(NULL, "w", log_syslog_func);
+}
diff --git a/lib/log/log_windows.c b/lib/log/log_windows.c
deleted file mode 100644
index a6a0889550..0000000000
--- a/lib/log/log_windows.c
+++ /dev/null
@@ -1,18 +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"
-
-/* set the log to default function, called during eal init process. */
-int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-
-	return 0;
-}
diff --git a/lib/log/meson.build b/lib/log/meson.build
index 0d4319b36f..160cf34f50 100644
--- a/lib/log/meson.build
+++ b/lib/log/meson.build
@@ -4,6 +4,10 @@ 
 includes += global_inc
 sources = files(
         'log.c',
-        'log_' + exec_env + '.c',
 )
+
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
diff --git a/lib/log/version.map b/lib/log/version.map
index 19d7f9cdb6..1637fba3b9 100644
--- a/lib/log/version.map
+++ b/lib/log/version.map
@@ -29,6 +29,6 @@  INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
+	eal_log_syslog; # WINDOWS_NO_EXPORT
 	rte_eal_log_cleanup;
 };