* PROBLEM: small socket send/receive buffers on TCP stream result in data not being transferred
@ 2001-02-01 9:12 Nicholas Daley
2001-02-01 18:53 ` kuznet
0 siblings, 1 reply; 2+ messages in thread
From: Nicholas Daley @ 2001-02-01 9:12 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 3471 bytes --]
I'm pretty sure this is a kernel problem
1. small socket send/receive buffers result in data not being transferred
2. I was playing with socket buffers using setsockopt() and SO_SNDBUF
and SO_RCVBUF (see small attached programs), I found that given small
enough buffers, data would stop being sent, although more was available.
I suspect what is happening is that one of the buffers fills, stops
accepting data, but doesn't reenable it when there's room again.
When I use netstat I find the buffer on the send side full, and the
buffer on the receive end empty.
This behaviour may depend on the speed of the system, on mine I can
usually get it to happen with buffer sizes around 100, especially if the
side sending data has a larger buffer.
I've tested this on a couple of machines running a 2.2 kernel, and one
running a 2.4 kernel.
3. Keywords: Networking, TCP, kernel
4. Kernel version (output of /proc/version):
Linux version 2.4.0 (root@viola) (gcc version egcs-2.91.66
19990314/Linux (egcs-1.1.2 release)) #2 Thu Jan 25 19:56:28 NZDT 2001
6. Attached at the end are two C++ programs (though they could as easily
have been C),
fakefeed - run first, acts as a server that just keeps sending data on a
connection.
fakesim - run second, connects to fake feed, and outputs what's received.
They both take as parameters a port number, and a buffer size.
e.g. fakefeed 8001 500
fakesim 8001 100
7.1. output of ver_linux script:
-- Versions installed: (if some fields are empty or look
-- unusual then possibly you have very old versions)
Linux viola 2.4.0 #2 Thu Jan 25 19:56:28 NZDT 2001 i586 unknown
Kernel modules 2.4.0
Gnu C egcs-2.91.66
Gnu Make 3.77
Binutils 2.9.1.0.25
Linux C Library 2.1.2
Dynamic linker ldd: version 1.9.9
Procps 2.0.2
Mount 2.9v
Net-tools 1.52
Kbd 0.99
Sh-utils 1.16
Modules Loaded ppp_deflate ipt_state ipt_MASQUERADE
iptable_filter ip_nat_ftp iptable_nat ip_conntrack ip_tables de4x5
v_midi opl3 mpu401 sb sb_lib uart401 sound bsd_comp ppp_async
7.2 output of /proc/cpuinfo
processor
: 0
vendor_id
: GenuineIntel
cpu family : 5
model
: 4
model name : Pentium MMX
stepping
: 4
cpu MHz : 167.049
fdiv_bug
: no
hlt_bug
: no
f00f_bug
: yes
coma_bug
: no
fpu
: yes
fpu_exception
: yes
cpuid level : 1
wp
: yes
flags
: fpu vme de pse tsc msr mce cx8 mmx
bogomips
: 333.41
7.3 output of /proc/modules
ppp_deflate 40912 0 (autoclean)
ipt_state 800 2 (autoclean)
ipt_MASQUERADE 1312 1 (autoclean)
iptable_filter 1856 0 (autoclean) (unused)
ip_nat_ftp 3440 0 (unused)
iptable_nat 12608 1 [ipt_MASQUERADE ip_nat_ftp]
ip_conntrack 12992 2 [ipt_state ipt_MASQUERADE ip_nat_ftp
iptable_nat]
ip_tables 10656 6 [ipt_state ipt_MASQUERADE
iptable_filter iptable_nat]
de4x5 42496 1
v_midi 5264 0 (unused)
opl3 11792 0 (unused)
mpu401 18960 0 (unused)
sb 6656 0 (unused)
sb_lib 34352 0 [sb]
uart401 6416 0 [sb_lib]
sound 57280 0 [v_midi opl3 mpu401 sb_lib uart401]
bsd_comp 4160 0
ppp_async 6464 1
Thanks
--
bits and peace
Nicholas Daley <mailto:ntd1@cs.waikato.ac.nz>
insert :-)=s as appropriate
[-- Attachment #2: fakefeed.cc --]
[-- Type: text/plain, Size: 1431 bytes --]
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <iostream.h>
int openList(int port) {
int fd=-1;
sockaddr_in sa;
fd=socket(PF_INET, SOCK_STREAM, 0);
if(fd<0) return -1;
sa.sin_family=AF_INET;
sa.sin_port=htons(port);
sa.sin_addr.s_addr=htonl(INADDR_ANY);
int s=1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&s,sizeof(s));
if(bind(fd,(struct sockaddr*)&sa,sizeof(sa))<0) {
shutdown(fd,2);
fd=-1;
return fd;
};
if(listen(fd,1)<0) {
shutdown(fd,2);
fd=-1;
return fd;
};
return fd;
};
int main(int argc, char** argv) {
int listener=openList(argc>1?atoi(argv[1]):8001);
int stream=accept(listener,NULL,NULL);
size_t s;
s=argc>2?atoi(argv[2]):3000;
setsockopt(stream,SOL_SOCKET,SO_RCVBUF,&s,sizeof(s));
setsockopt(stream,SOL_SOCKET,SO_SNDBUF,&s,sizeof(s));
close(listener);
char buff[200];
long long sent=0;
for(int i=1;i;i++) {
sprintf(buff,"%d\n",i);
int writeres=write(stream,buff,strlen(buff));
if(writeres<0) { cerr<<"Write error "<<writeres<<','<<errno<<"\a\n";break;}
if(writeres==0) { cerr<<"Write EOF\a\n";break;}
if(writeres!=strlen(buff)) {cerr <<"Didn't finish writing\a\n";break;}
cerr<<buff<<" Total bytes sent="<<(sent+=writeres)<<endl;
}
};
[-- Attachment #3: fakesim.cc --]
[-- Type: text/plain, Size: 1041 bytes --]
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <iostream.h>
typedef double sk_time;
int openCon(const char* hostname, int port) {
int fd=-1;
sockaddr_in sa;
hostent *he;
fd=socket(PF_INET, SOCK_STREAM, 0);
if(fd<0) return -1;
sa.sin_family=AF_INET;
sa.sin_port=htons(port);
he=gethostbyname(hostname);
if(he==NULL) return fd=-1;
sa.sin_addr=*(struct in_addr*) he->h_addr;
if(connect(fd,(struct sockaddr*) &sa, sizeof(sa))<0) return fd=-1;
return fd;
}
int main(int argc, char** argv) {
int tracestream=openCon("localhost",argc>1?atoi(argv[1]):8001);
size_t s;
s=argc>2?atoi(argv[2]):3000;
setsockopt(tracestream,SOL_SOCKET,SO_RCVBUF,&s,sizeof(s));
setsockopt(tracestream,SOL_SOCKET,SO_SNDBUF,&s,sizeof(s));
while(1) {
char c;
if(read(tracestream,&c,1)<=0) break;
cerr<<c;
}
close(tracestream);
};
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: PROBLEM: small socket send/receive buffers on TCP stream result in data not being transferred
2001-02-01 9:12 PROBLEM: small socket send/receive buffers on TCP stream result in data not being transferred Nicholas Daley
@ 2001-02-01 18:53 ` kuznet
0 siblings, 0 replies; 2+ messages in thread
From: kuznet @ 2001-02-01 18:53 UTC (permalink / raw)
To: Nicholas Daley; +Cc: linux-kernel
Hello!
> 1. small socket send/receive buffers result in data not being transferred
I know why your test does not work in 2.4 (sort of bug, fix is appended).
But I have no idea, why it does not work with 2.2. Please, make
tcpdump in this case.
> and SO_RCVBUF (see small attached programs), I found that given small
> enough buffers, data would stop being sent, although more was available.
No doubts. If you think that tcp must work like gun no matter
what silly things application makes, you are mistaken.
TCP works like gun when application does not try to interlope. 8)
You have made two capital mistakes:
1. RCVBUF/SNDBUF are not arbibrary numbers. Of course, kernel tries
to adjust them to something reasonable, when user asks something
wicked (like your case), but it cannot do this in all the cases.
2. Playing with buffer sizes after connection is established
is very bad idea, tcp is defenceless in this case.
> This behaviour may depend on the speed of the system, on mine I can
Surely, it is not.
> usually get it to happen with buffer sizes around 100
Advice: do not play with these sockopts. Kernel does this better,
than any application.
Application may set them, when it wants to set large values.
Values, selected by kernel by default, are minimal ones in fact.
Alexey
--- ../vger3-010130/linux/include/net/tcp.h Wed Dec 13 22:37:49 2000
+++ linux/include/net/tcp.h Thu Feb 1 21:08:45 2001
@@ -1304,7 +1305,8 @@
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
if (tp->ucopy.task) {
- if ((tp->ucopy.memory += skb->truesize) <= (sk->rcvbuf<<1)) {
+ if (tp->ucopy.memory < (sk->rcvbuf<<1)) {
+ tp->ucopy.memory += skb->truesize;
__skb_queue_tail(&tp->ucopy.prequeue, skb);
if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
wake_up_interruptible(sk->sleep);
@@ -1313,7 +1315,6 @@
}
} else {
NET_INC_STATS_BH(TCPPrequeueDropped);
- tp->ucopy.memory -= skb->truesize;
__kfree_skb(skb);
}
return 1;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2001-02-01 18:54 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-02-01 9:12 PROBLEM: small socket send/receive buffers on TCP stream result in data not being transferred Nicholas Daley
2001-02-01 18:53 ` kuznet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®