48

Hi I have the following program to check the send buffer size for a UDP socket. However, I the return value is a bit confusing to me. I use the following simple app:

#include <sys/socket.h>
#include <stdio.h>

int main(int argc, char **argv)
{
 int sockfd, sendbuff;
 socklen_t optlen;

 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 if(sockfd == -1)
     printf("Error");

 int res = 0;

 // Get buffer size
 optlen = sizeof(sendbuff);
 res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);

 if(res == -1)
     printf("Error getsockopt one");
 else
     printf("send buffer size = %d\n", sendbuff);

 // Set buffer size
 sendbuff = 98304;

 printf("sets the send buffer to %d\n", sendbuff);
 res = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));

 if(res == -1)
     printf("Error setsockopt");


 // Get buffer size
 optlen = sizeof(sendbuff);
 res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);

 if(res == -1)
     printf("Error getsockopt two");
 else
     printf("send buffer size = %d\n", sendbuff);

 return 0;
}

The output on my machine is:

send buffer size = 129024

sets the send buffer to 98304

new send buffer size = 196608

Can anybody clarify what I'm doing wrong here or how to interpret the output?

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
mortenvp
  • 1,095
  • 1
  • 7
  • 13

1 Answers1

61

You're not doing anything wrong. Linux doubles the value (within the kernel) when you set it, and returns the doubled value when you query it. man 7 socket says:

[...]

    SO_SNDBUF
              Sets or gets the maximum socket send buffer in bytes.  The  ker-
              nel doubles this value (to allow space for bookkeeping overhead)
              when it is set using setsockopt(), and  this  doubled  value  is
              returned  by  getsockopt().   The  default  value  is set by the
              wmem_default sysctl and the maximum allowed value is set by  the
              wmem_max sysctl.  The minimum (doubled) value for this option is
              2048.
[...]

NOTES
       Linux assumes that half of the send/receive buffer is used for internal
       kernel structures; thus the sysctls are twice what can be  observed  on
       the wire.
[...]
Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119
  • 14
    Holy networking Batman! That's where all that skbuf stuff goes :) – Nikolai Fetissov Jan 09 '10 at 02:40
  • 1
    @csyangchen: I can only guess, but I would assume that someone had the idea that by setting the buffer to size n, the buffer should be able to hold n bytes of PAYLOAD. So additional buffer size is necessary to hold the message headers (at least in case of connectionless underlying protocol, such as UDP). – Aconcagua Feb 01 '16 at 10:22
  • @csyangchen I also would like to have more details than that vague explanation. I'd guess it could maybe related to how TCP operates, for example, when buffer is XX bytes there could also be that same size of bytes in flight towards destination. Until these were ACKed by remote these bytes have to kept on the sender side, in worst case it could be double of that buffer if remote is slow to reply and TCP window is larger than SNDBUF. – Pavel P Jul 30 '17 at 03:21
  • In short: People from 1983 had little to no experience writing APIs so it makes sense that you have to deal with such nonsense if you want to use those dinosaurs. Sadly, the whole internet is based on this stuff and that's why you have to abstract it in the end (not to mention that, for the same reasons, there are subtle differences in usage -not justified- depending on the platform, so it's not a portable API until you wrap it with proper interfaces and handle those under the covers). – Pablo Ariel Nov 09 '18 at 20:10
  • 1
    @PabloAriel Linux was not written in 1983. This doubling issue is Linux-specific baloney. Other systems do not behave this bizarre way. – jschultz410 Oct 23 '21 at 13:53