listen(2): improve administrator control over logging

As documented in listen.2 manual page, the kernel emits a LOG_DEBUG
syslog message if a socket listen queue overflows. For some appliances,
it may be desirable to change the priority to some higher value
like LOG_INFO while keeping other debugging suppressed.

OTOH there are cases when such overflows are normal and expected.
Then it may be desirable to suppress overflow logging altogether,
so that dmesg buffer is not flooded over long run.

In addition to existing sysctl kern.ipc.sooverinterval,
introduce new sysctl kern.ipc.sooverprio that defaults to 7 (LOG_DEBUG)
to preserve current behavior. It may be changed to any value
in a range of 0..7 for corresponding priority or to -1 to suppress logging.
Document it in the listen.2 manual page.

MFC after:	1 month
This commit is contained in:
Eugene Grosbein 2023-05-01 03:14:30 +07:00
parent 8c48f4c537
commit 4824d78872
2 changed files with 23 additions and 5 deletions

View File

@ -28,7 +28,7 @@
.\" From: @(#)listen.2 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
.Dd April 14, 2020
.Dd April 30, 2023
.Dt LISTEN 2
.Os
.Sh NAME
@ -111,10 +111,20 @@ or less than zero is specified,
is silently forced to
.Va kern.ipc.soacceptqueue .
.Pp
If the listen queue overflows, the kernel will emit a LOG_DEBUG syslog message.
If the listen queue overflows, the kernel will emit a syslog message
using default priority LOG_DEBUG (7).
The
.Xr sysctl 3
MIB variable
.Va kern.ipc.sooverprio
may be used to change this priority to any value in a range of 0..7
(LOG_EMERG..LOG_DEBUG).
See
.Xr syslog 3
for details.
It may be set to -1 to disable these messages.
.Pp
The variable
.Va kern.ipc.sooverinterval
specifies a per-socket limit on how often the kernel will emit these messages.
.Sh INTERACTION WITH ACCEPT FILTERS
@ -164,6 +174,7 @@ The socket is not of a type that supports the operation
.Xr connect 2 ,
.Xr socket 2 ,
.Xr sysctl 3 ,
.Xr syslog 3 ,
.Xr sysctl 8 ,
.Xr accept_filter 9
.Sh HISTORY

View File

@ -578,6 +578,10 @@ SYSCTL_INT(_regression, OID_AUTO, sonewconn_earlytest, CTLFLAG_RW,
&regression_sonewconn_earlytest, 0, "Perform early sonewconn limit test");
#endif
static int sooverprio = LOG_DEBUG;
SYSCTL_INT(_kern_ipc, OID_AUTO, sooverprio, CTLFLAG_RW,
&sooverprio, 0, "Log priority for listen socket overflows: 0..7 or -1 to disable");
static struct timeval overinterval = { 60, 0 };
SYSCTL_TIMEVAL_SEC(_kern_ipc, OID_AUTO, sooverinterval, CTLFLAG_RW,
&overinterval,
@ -617,7 +621,8 @@ solisten_clone(struct socket *head)
if (over) {
#endif
head->sol_overcount++;
dolog = !!ratecheck(&head->sol_lastover, &overinterval);
dolog = (sooverprio >= 0) &&
!!ratecheck(&head->sol_lastover, &overinterval);
/*
* If we're going to log, copy the overflow count and queue
@ -706,14 +711,16 @@ solisten_clone(struct socket *head)
* sys/kern/sonewconn_overflow checks for it.
*/
if (head->so_cred == 0) {
log(LOG_DEBUG, "sonewconn: pcb %p (%s): "
log(LOG_PRI(sooverprio),
"sonewconn: pcb %p (%s): "
"Listen queue overflow: %i already in "
"queue awaiting acceptance (%d "
"occurrences)\n", head->so_pcb,
sbuf_data(&descrsb),
qlen, overcount);
} else {
log(LOG_DEBUG, "sonewconn: pcb %p (%s): "
log(LOG_PRI(sooverprio),
"sonewconn: pcb %p (%s): "
"Listen queue overflow: "
"%i already in queue awaiting acceptance "
"(%d occurrences), euid %d, rgid %d, jail %s\n",