views:

404

answers:

3

I am running a Linux box running 2.6.9-55.ELsmp, x86_64.

I am trying to set the TCP receive window by using the setsockopt() function using C. I try the following:

rwnd = 1024;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&rwnd, sizeof(rwnd));

The code segment above is in a client program that receives data from a server. When I kick off the program to receive and observe tcpdump output, I observe window negotiation like so:

11:34:40.257755 IP clientReceiver.42464 > serverSender.8991: 
S 1742042788:1742042788(0) win 5840 
<mss 1460,sackOK,timestamp 1688222886 0,nop,wscale 2>

We see that the client program is in fact negotiating a window different from what I have set in the client program. However, from how I can interpret Steven's text ("TCP/IP Illustrated, Volume 1") Section 20.4, I believe you effect what he refers to in the second block quote in Section 20.4 using the setsockopt() call I use (see above).

I'd like to understand where I have gone wrong.

Perhaps my interpretation of what Stevens is saying is incorrect. In that case, could you point me to the correct way of setting the receive buffer size? As a proof of my confusion, I refer the Linux TCP sockets man page at http://linux.die.net/man/7/tcp (see comment on SO_RCFBUF).

What am I missing in this story? How do I control the receive buffer size (and have it show in the tcpdump output)? Please note that I allude to here a setting of the socket option SO_RCFBUF--I understand that's what shows up in the window negotiation in the SYN.

Any input is appreciated.

+2  A: 

The receive buffer size can be reduced only before you connect the socket - you can increase it at any time. What order are you calling sockopt() in relative to connect()?

anon
Thanks for the quick response. I call setsockopt() before I connect().
Sonny
A: 

For TCP, the rwnd value is to be passed during recv.

recv(sock, buf, rwnd, 0);

This shall receive 1024 bytes.

bluegenetic
Hi, thank you for your response. From what I know this recv() call is for the application--i.e., this is the rate at which the application consumes the byte stream meant for it. In other words, I don't believe this is the receive window that is <i>negotiated</i> by TCP in the beginning with the peer.
Sonny
+4  A: 

You need to also use TCP_WINDOW_CLAMP

rcvbuf = 2048;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)& rcvbuf, sizeof(rcvbuf));
clamp = 1024;
setsockopt(sock, SOL_SOCKET, TCP_WINDOW_CLAMP, (char *)& clamp, sizeof(clamp));

Note the rcvbuf is twice the clamp, it could be more. You can let it autotune, the window clamp will still work. This isn't portable.

Andrew McGregor
Note also that the minimum clamp is limited to half the minimum RCVBUF (usually 4096 - so the minimum clamp is usually 2048).
caf
I checked this, and the numbers are actually 256 and (thereby) 128 for the minimum settable CLAMP value resp. Check the code from tcp.c::setsockopt() under case TCP_WINDOW_CLAMP, and check out sock.h::#define SOCK_MIN_RCVBUF 256. Thanks to everyone. Cheers!
Sonny