Setting TCP receive window in C and working with tcpdump in Linux

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.

Answers


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.


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()?


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

recv(sock, buf, rwnd, 0);

This shall receive 1024 bytes.


Need Your Help

Is there a universally accepted value for no value?

default

I've seen N/A (always caps) used most often but I don't know if there is a standard. My data will be seen on Google so I would like to use the most recognized value.

How to connect with an IPv6 address using SSH.NET library in C#

c# ssh ipv6 ssh.net

I want to connect via SSH to a remote GNU+Linux machine and execute a command, but with an IPv6 address. With an IPv4 address it works perfectly fine.