query TCP buffer sizes for a socket on linux

Is there any way to lookup the send/receive buffer sizes for TCP sockets?

I've poked around with both netstat and ss, as well as the raw /proc/net/tcp. Lots of goodies there, including the counts of bytes in flight, timers, process name, etc.

But I'd like to be able to diagnose whether some proceses are setting SO_{SND,RCV}BUF...and more interestingly what values the kernel is actually using for each SKB.


From the lsof FAQ (search for "Why doesn't lsof report socket options"), I believe Linux doesn't make the info you're after available. (at least not via /proc)

If it did, you could use lsof -i <pid> -a -i tcp -T f, but -T only takes "qs", not f on Linux. You can get some other info from netstat (netstat --tcp -p -o -e -e -v | grep <pid>) which includes the Send Queue and Receive Queue and some timer info.

What you could do is use strace. You'd have to either run the program via strace (strace -ff -e network,ioctl PROGRAM) or before it sets up the TCP socket (strace -fff -e network,ioctl -p PID). ioctl is how those options would be set, and network should catch enough to tell what connections those are. (but just ioctl and then use lsof to figure out where the connections to should work, too)


You can actually do that using https://github.com/veithen/knetstat.

E.g. for nc -I 8192 -O 8192 www.google.com 80 this would give (see the SO_RCVBUF and SO_SNDBUF on the third row):

$ cat /proc/net/tcpstat
Recv-Q Send-Q Local Address           Foreign Address         Stat Diag Options
     0      0 0.0.0.0:22              0.0.0.0:*               LSTN      SO_REUSEADDR=1,SO_REUSEPORT=0,SO_KEEPALIVE=0,TCP_NODELAY=0
     0      0 10.132.0.4:22           74.125.73.164:38922     ESTB      SO_REUSEADDR=1,SO_REUSEPORT=0,SO_KEEPALIVE=1,TCP_NODELAY=1
     0      0 10.132.0.4:44058        74.125.206.103:80       ESTB      SO_REUSEADDR=0,SO_REUSEPORT=0,SO_KEEPALIVE=0,SO_RCVBUF=8192,SO_SNDBUF=8192,TCP_NODELAY=0
     0      0 10.132.0.4:44054        74.125.206.103:80       TIMW 
     0      0 10.132.0.4:22           74.125.73.96:45722      ESTB      SO_REUSEADDR=1,SO_REUSEPORT=0,SO_KEEPALIVE=1,TCP_NODELAY=1

You can change the size of the receive and the send buffer as follows (send buffer shown):

int buffersize = 64*1024;  // 64k
setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &buffersize, sizeof(buffersize));

and to get the current size, use:

socklen_t buffersize_len = sizeof(buffersize); // in/out parameter
getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &buffersize, &buffersize_len);

There is a known bug in Linux that reports the current buffer size as 1/2 the set value. I can't remember if the internal value is 1/2 of what was requested, or whether the report is 1/2 of what it really is.