2002-02-25 21:08:47

by Raphael Manfredi

[permalink] [raw]
Subject: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

Hi,

I run:

Linux nice 2.4.18-pre7 #1 SMP Mon Jan 28 23:12:48 MET 2002 i686 unknown

I noticed that whenever I do:

setsockopt(fd, SOL_SOCKET, SO_SNDBUF....)

followed by

getsockopt(fd, SOL_SOCKET, SO_SNDBUF....)

to verify what the kernel has set, I read TWICE as much the amount used
for the set. That is, if I set 8192, I read 16384. Therefore, to set
the correct size, I need to half the parameter first.

Is this a known bug? Is it setsockopt or getsockopt which returns the
wrong size?

Here's sample code demonstrating the problem:

--------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

static void set_send_buf(int fd, int size)
{
int new_len;
int arglen = sizeof(new_len);

if (-1 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)))
perror("setsockopt");

if (-1 == getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &new_len, &arglen))
perror("getsockopt");

printf("size was %d, but set %d\n", size, new_len);
}

main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);

set_send_buf(fd, 8192);
set_send_buf(fd, 16384);
}
--------------------------

When run, it displays:

size was 8192, but set 16384
size was 16384, but set 32768

Raphael


2002-02-25 21:31:32

by Richard B. Johnson

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

On Mon, 25 Feb 2002, Raphael Manfredi wrote:

> Hi,
>
> I run:
>
> Linux nice 2.4.18-pre7 #1 SMP Mon Jan 28 23:12:48 MET 2002 i686 unknown
>
> I noticed that whenever I do:
>
> setsockopt(fd, SOL_SOCKET, SO_SNDBUF....)
>
> followed by
>
> getsockopt(fd, SOL_SOCKET, SO_SNDBUF....)
>
> to verify what the kernel has set, I read TWICE as much the amount used
> for the set. That is, if I set 8192, I read 16384. Therefore, to set
> the correct size, I need to half the parameter first.

This came up a few months ago. Don't halve the size. The value was
explained to NOT be a bug even though it doesn't make sense to us
mortals. Just set the buffer size without reading anything. It will
be fine. The explaination was somewhat smokey, but It seems as though
two buffers are set aside or something like that. Just don't read
the size. Set it and forget it.


Cheers,
Dick Johnson

Penguin : Linux version 2.4.1 on an i686 machine (797.90 BogoMips).

111,111,111 * 111,111,111 = 12,345,678,987,654,321

2002-02-25 22:26:45

by Alan

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

> to verify what the kernel has set, I read TWICE as much the amount used
> for the set. That is, if I set 8192, I read 16384. Therefore, to set
> the correct size, I need to half the parameter first.
> Is this a known bug? Is it setsockopt or getsockopt which returns the
> wrong size?

Neither. You asked for 8K the kernel allows a bit more for BSD compatibility
and other things. You query and it gives back the size it chose

2002-02-25 22:59:35

by Raphael Manfredi

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

Quoting [email protected] from ml.linux.kernel:
:This came up a few months ago. Don't halve the size. The value was
:explained to NOT be a bug even though it doesn't make sense to us
:mortals. Just set the buffer size without reading anything. It will
:be fine. The explaination was somewhat smokey, but It seems as though
:two buffers are set aside or something like that. Just don't read
:the size. Set it and forget it.

The problem is that I don't want to shrink the buffer size, hence I need
to read the current size. Do I need to halve the returned value from
getsockopt() then?

Raphael

2002-02-25 23:07:05

by Alan

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

> The problem is that I don't want to shrink the buffer size, hence I need
> to read the current size. Do I need to halve the returned value from
> getsockopt() then?

The kernel always uses a buffer as big or bigger than you asked for

2002-02-26 00:11:37

by linux-kernel

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

In article <[email protected]>,
Alan Cox <[email protected]> writes:
>> to verify what the kernel has set, I read TWICE as much the amount used
>> for the set. That is, if I set 8192, I read 16384. Therefore, to set
>> the correct size, I need to half the parameter first.
>> Is this a known bug? Is it setsockopt or getsockopt which returns the
>> wrong size?
>
> Neither. You asked for 8K the kernel allows a bit more for BSD compatibility
> and other things. You query and it gives back the size it chose

it's still insane it doesn't use the same fudge factor in both directions.

2002-02-26 08:19:54

by Raphael Manfredi

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

Quoting Alan Cox <[email protected]> from ml.linux.kernel:
:Neither. You asked for 8K the kernel allows a bit more for BSD compatibility
:and other things. You query and it gives back the size it chose

I understand the kernel can choose to allocate more than requested.
Even double the size. But it should be consistent, i.e. if when I request
x it allocates 2x, then when I ask the size, I want to know x, not 2x.
Otherwise, how can the application behave sanely if it want to vary the
size?

Linux seems to be the only kernel to lie like that. It's not consistent.
The aim is not for the application to accurately measure the amount of
kernel resources used by sockets, it's to adjust the (perceived) size of the
socket buffer.

If I can't use the returned value from getsockopt(SO_SNDBUF) to do a
setsockopt(SO_SNDBUF), then it's broken! You'll have a hard time convincing
me otherwise.

Now whether it should be fixed is another matter.

Raphael

2002-02-26 09:25:12

by Alan

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

> If I can't use the returned value from getsockopt(SO_SNDBUF) to do a
> setsockopt(SO_SNDBUF), then it's broken! You'll have a hard time convincing
> me otherwise.

I'd like to see a standards document cite for that. The behaviour we follow
is not atypical for a lot of ioctls and syscalls were you ask for one size
and the kernel gives you its preferred variant. In the other cases I can
think of the kernel also does not lie about its preferred variant

2002-02-26 12:54:38

by Raphael Manfredi

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

Quoting Alan Cox <[email protected]> from ml.linux.kernel:
:> If I can't use the returned value from getsockopt(SO_SNDBUF) to do a
:> setsockopt(SO_SNDBUF), then it's broken! You'll have a hard time convincing
:> me otherwise.
:
:I'd like to see a standards document cite for that. The behaviour we follow
:is not atypical for a lot of ioctls and syscalls were you ask for one size
:and the kernel gives you its preferred variant. In the other cases I can
:think of the kernel also does not lie about its preferred variant

Practical experience shows that the test program I sent "works" (i.e.
returns the least surprising results) on OpenBSD, HP-UX 11.x. I'm having
a friend testing it for me on Solaris, but my guess is that it will work
there as well.

Raphael

2002-02-27 16:18:33

by Horst H. von Brand

[permalink] [raw]
Subject: Re: setsockopt(SOL_SOCKET, SO_SNDBUF) broken on 2.4.18?

[email protected] (Raphael Manfredi) said:
> Quoting Alan Cox <[email protected]> from ml.linux.kernel:
> :Neither. You asked for 8K the kernel allows a bit more for BSD compatibility
> :and other things. You query and it gives back the size it chose

> I understand the kernel can choose to allocate more than requested.
> Even double the size. But it should be consistent, i.e. if when I request
> x it allocates 2x, then when I ask the size, I want to know x, not 2x.
> Otherwise, how can the application behave sanely if it want to vary the
> size?

By keeping track of the number, if needed?
--
Dr. Horst H. von Brand User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria +56 32 654239
Casilla 110-V, Valparaiso, Chile Fax: +56 32 797513