Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of the socket option SO_SNDLOWAT

I'm currently porting a software in C from Tru64 to Linux Suse 11. On Tru64 they are setting the value of SO_SNDLOWAT socket option to 1024 * 64. On Linux this option is not changeable and its value is 1.

I want to figure out, what will be the impact of not setting SO_SNDLOWAT to 1024 * 64 on the software execution on Linux.

The problem is that I found two definitions (interpretations) of the purpose of SO_SNDLOWAT:

  1. Found on the man page of socket on Linux :

    SO_SNDLOWAT
    Specify the minimum number of bytes in the buffer until the socket layer will pass the data to the protocol

    I understood that it specifies the minimum number of bytes in the buffer to proceed (in this case for sending the message). The buffer needs to be filled at least for SO_SNDLOWAT bytes to proceed

  2. Found in the book "UNIX Network Programming: The sockets networking API of W. Richard Stevens, Bill Fenner, Andrew M. Rudoff"

    The send low-water mark is the amount of available space that must exist in the socket send buffer for select to return "writable".

    I understood that, if I want to write in the socket buffer (no matter of the size of what I'm writing) the buffer needs to have at least SO_SNDLOWAT bytes free.

I don't know what to make of SO_SNDLOWAT.

like image 590
greg Avatar asked Nov 23 '11 16:11

greg


2 Answers

As you can see at this question, which covers other socket options, the answer depends on operating system, so both answers may be correct, as one is an answer from the Linux world and one is an answer from the UNIX (BSD and Co) world.

In BSD and BSD clones, this option means the following:

  1. If the socket is non-blocking and you call send(), it must be able to either accept all supplied data at once or accept at least SO_SNDLOWAT bytes of data; if that is not possible, it will not accept any data and send() fails with error.

    So if you set SO_SNDLOWAT to 100 and try to send 50 bytes, it will send 50 bytes or nothing. If you set SO_SNDLOWAT to 100 and try to send 200 bytes, it must at least accept 100 bytes of data, it can accept more, up to the entire 200 bytes, as well as any value between 100 and 200, just not less than 100. Keep in mind, the default value of SO_SNDLOWAT is 1 and that's also the default behavior of a non-blocking socket (it must accept at least 1 byte or fail with EWOULDBLOCK)

    Note that UDP sockets are always all-or-nothing, they never accept only "part of the data", thus setting SO_SNDLOWAT is only relevant for TCP sockets, that may accept only a part of the data offered.

  2. If the socket is blocking, setting SO_SNDLOWAT has no real effect on the send() call, as in that case the socket will always accept all data or it will block and then it will block until all data have been accepted or the send timeout is hit (if a send timeout has been set with SO_SNDTIMEO or the underlying protocol has an own timeout for sending).

  3. Regardless if the socket is blocking or not, regardless if it is UDP or TCP, a poll() or select() call will only claim that this socket is writable, if at least SO_SNDLOWAT bytes can be accepted by a send() call.

So what is this option really good for? Usually it is used to avoid that your process feeds data in byte-for-byte once the socket buffer ran full but in larger chunks as with default behavior, select() and poll() will say the socket is writable, even if there's just room for a single byte in the socket buffer. In other words, it's just a performance optimization, as code that works correctly with arbitrary socket writes will work correctly regardless if SO_SNDLOWAT is set and regardless to which value, it may just need a lot less CPU time in some extreme situations if SO_SNDLOWAT has a reasonable value. But as with all performance tweaks, if you don't know exactly what you are doing, you may easily make things much worse by setting the wrong values, so if in doubt, don't touch that setting.

like image 132
Mecki Avatar answered Nov 17 '22 16:11

Mecki


The first description is the correct interpretation.

As for the impact of not being able to set SO_SNDLOWAT, I don't think it will matter, since performance depends on things like Nagle's algorithm, path-MTU discovery, etc. I suspect that other TCP/IP implementations silently ignore this option.

like image 1
Brett Hale Avatar answered Nov 17 '22 17:11

Brett Hale