RAZ_Muh_Taz
RAZ_Muh_Taz

Reputation: 4089

getsockopt() returns a value twice the value that was previously set by setsockopt()

I am attempting to increase the SO_RCVBUF for a raw socket I am using to interact with a linux device driver. The default rmem_default/rmem_max are both too small, 163840. Therefore I am using the following stack overflow question/answers to help me. Everything is working, or least it looks like it. However, when I get the value I set for the SO_RCVBUF it returns the value I set * 2? Anyone know why that is?

int recv_val = SOCK_RCV_BUF_MAX; socklen_t size = sizeof(recv_val);

if(setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_val, size) < 0)
{
    fprintf(stderr, "Error setsockopt(SO_RCVBUF): %s\n", strerror(errno));
}
else
    printf("Set the SO_RCVBUF to %d\n", recv_val);

recv_val = 0;

if (getsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_val, &size) < 0)
{
    fprintf(stderr, "Error getsockopt(SO_RCVBUF): %s\n", strerror(errno));
}
else if(recv_val == SOCK_RCV_BUF_MAX)
{
    printf("Successfully set the buffer max to %d\n", SOCK_RCV_BUF_MAX);
}
else
    printf("Failed to set the buffer to max (%d), val = %d\n", SOCK_RCV_BUF_MAX, recv_val);

Output

Set the SO_RCVBUF to 64000000
Failed to set the buffer to max (64000000), val = 128000000

Changing to recv_val = SOCK_RCV_BUF_MAX/2 outputs

Set the SO_RCVBUF to 32000000
Successfully set the buffer max to 64000000

If I don't set the value using setsockopt() and call getsockopt() for my socket I get the correct default value

Failed to set the buffer to max (64000000), val = 163840

Upvotes: 2

Views: 1376

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596307

The value you give to setsockopt(SO_RCVBUF) is only a hint, not an absolute. The socket provider is allowed to use a different value if it wants to. What you get back from getsockopt(SO_RCVBUF) is the actual value used.

What you are seeing happen is actually documented behavior:

http://man7.org/linux/man-pages/man7/socket.7.html

SO_RCVBUF
Sets or gets the maximum socket receive buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/rmem_default file, and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file. The minimum (doubled) value for this option is 256.

Upvotes: 4

Related Questions