Date: 22 Jun 1997 13:36:54 +0000 (GMT) From: sthaug@nethelp.no To: FreeBSD-gnats-submit@FreeBSD.ORG Cc: sthaug@nethelp.no Subject: kern/3925: SO_SNDLOWAT of 0 causes kernel to use 99% of CPU time on TCP send Message-ID: <19970622133654.29391.qmail@verdi.nethelp.no> Resent-Message-ID: <199706221340.GAA02000@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 3925
>Category: kern
>Synopsis: SO_SNDLOWAT of 0 causes kernel to use 99% of CPU time on TCP send
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Jun 22 06:40:01 PDT 1997
>Last-Modified:
>Originator: Steinar Haug
>Organization:
Nethelp Consulting
>Release: FreeBSD 2.2-961014-SNAP i386
>Environment:
This may be a generic 4.4BSD networking bug. It applies to NetBSD-1.2, FreeBSD
(all versions I've checked, eg. 2.2-BETA, 3.0-970124-SNAP). It was discovered
because BIND-8.1.1-T2B named sets SO_SNDLOWAT to 0 if SO_SNDLOWAT is defined.
>Description:
Setting SO_SNDLOWAT to 0 and then sending data with TCP to a site which is more
than a few milliseconds away (eg. connected over a 28.800 link) causes the kernel
to use 99% of the CPU time, as reported by vmstat or top. Using a SO_SNDLOWAT > 0
makes the problem disappear.
It's quite possible that this effect *always* occurs, but it's much more visible
against a slow site.
>How-To-Repeat:
Compile the following program, which sends a number of buffers to the discard
port at a given address. Run the program with
% tstlowat 0 50 ip-address
ie. send 50 buffers to a given address with SO_SNDLOWAT set to 0. Observe with
vmstat how the kernel uses all of the CPU.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main(int argc, char *argv[])
{
struct sockaddr_in sin;
int i, n, s, sndlowat;
char buf[65536];
sndlowat = atoi(argv[1]);
n = atoi(argv[2]);
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket"); exit(1);
}
if (setsockopt(s, SOL_SOCKET, SO_SNDLOWAT, (char *)&sndlowat,
sizeof sndlowat) < 0) {
perror("setsockopt"); exit(1);
}
sin.sin_port = htons(9); /* Discard port */
sin.sin_family = AF_INET;
if (inet_aton(argv[3], &sin.sin_addr) == 0) {
fprintf(stderr, "inet_aton"); exit(1);
}
if (connect(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
perror("connect"); exit(1);
}
for (i=0; i<n; i++) {
if (write(s, buf, sizeof buf) < 0) {
perror("write"); exit(1);
}
}
}
>Fix:
Sorry, no known fix. Easy workaround is to use a SO_SNDLOWAT which is > 0.
>Audit-Trail:
>Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970622133654.29391.qmail>
