All of lore.kernel.org
 help / color / mirror / Atom feed
* Possible bug in `tcp(7)` regarding `TCP_USER_TIMEOUT`
@ 2022-01-15 12:23 João Sampaio
  2022-01-15 13:28 ` Alejandro Colomar (man-pages)
  0 siblings, 1 reply; 2+ messages in thread
From: João Sampaio @ 2022-01-15 12:23 UTC (permalink / raw)
  To: mtk.manpages, alx.manpages, linux-man

Hello,

The manpage for TCP (`man 7 tcp`, [1]) reads, in the paragraphs about
`TCP_USER_TIMEOUT`:

[1] https://man7.org/linux/man-pages/man7/tcp.7.html

```
This option can be set during any state of a TCP
connection, but is effective only during the synchronized
states of a connection (ESTABLISHED, FIN-WAIT-1, FIN-
WAIT-2, CLOSE-WAIT, CLOSING, and LAST-ACK).
```

When I read that, I understand that that option should only apply to
established TCP connections, and should not apply when trying to
establish a TCP connection.

I wrote a simple program to test that:

```
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

// We'll skip error-checking since this is just for testing purposes.

void do_connect(int with_tcp_user_timeout) {
    struct addrinfo hint;
    struct addrinfo *ai;
    int sock;
    time_t start;
    time_t end;
    unsigned int timeout = 10000;

    memset(&hint, 0, sizeof(hint));
    hint.ai_family = AF_INET;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = IPPROTO_TCP;
    getaddrinfo("10.0.42.16", "5432", &hint, &ai);

    sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (with_tcp_user_timeout) {
        setsockopt(
            sock, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
            sizeof(timeout)
        );
    }

    printf(
        "Attempting to connect, with_user_tcp_timeout = %d... ",
        with_tcp_user_timeout
    );
    fflush(stdout);

    start = time(NULL);
    connect(sock, ai->ai_addr, ai->ai_addrlen);
    end = time(NULL);
    printf("Done!\n");

    freeaddrinfo(ai);

    printf(
        "with_tcp_user_timeout = %d, took %ld seconds\n",
        with_tcp_user_timeout, end - start
    );
}

int main(void) {
    // Let's connect with TCP_USER_TIMEOUT first for faster useful
    // first data.
    do_connect(1);
    do_connect(0);

    exit(EXIT_SUCCESS);
}
```

This program gives me the following output:

```
$ gcc main.c -Wall -Wextra -Werror && ./a.out
Attempting to connect, with_user_tcp_timeout = 1... Done!
with_tcp_user_timeout = 1, took 10 seconds
Attempting to connect, with_user_tcp_timeout = 0... Done!
with_tcp_user_timeout = 0, took 130 seconds
```

So it seems like that option does apply when trying to establish a
connection! This above output was obtained with Linux 5.15.8 and gcc
9.3.0.

Am I reading the manpage wrong, or is the manpage wrong? Or is this
just an "undocumented behavior" that shouldn't be relied on and can
be removed without warning in future releases?

Thanks,
João Sampaio

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Possible bug in `tcp(7)` regarding `TCP_USER_TIMEOUT`
  2022-01-15 12:23 Possible bug in `tcp(7)` regarding `TCP_USER_TIMEOUT` João Sampaio
@ 2022-01-15 13:28 ` Alejandro Colomar (man-pages)
  0 siblings, 0 replies; 2+ messages in thread
From: Alejandro Colomar (man-pages) @ 2022-01-15 13:28 UTC (permalink / raw)
  To: João Sampaio, H.K. Jerry Chu, Michael Kerrisk (man-pages)
  Cc: David S. Miller, Networking, linux-man

Hello João,

On 1/15/22 13:23, João Sampaio wrote:
> Hello,
> 
> The manpage for TCP (`man 7 tcp`, [1]) reads, in the paragraphs about
> `TCP_USER_TIMEOUT`:
> 
> [1] https://man7.org/linux/man-pages/man7/tcp.7.html
> 
> ```
> This option can be set during any state of a TCP
> connection, but is effective only during the synchronized
> states of a connection (ESTABLISHED, FIN-WAIT-1, FIN-
> WAIT-2, CLOSE-WAIT, CLOSING, and LAST-ACK).
> ```
> 
> When I read that, I understand that that option should only apply to
> established TCP connections, and should not apply when trying to
> establish a TCP connection.
> 
> I wrote a simple program to test that:
> 
> ```
> #include <netdb.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
> #include <time.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <netinet/tcp.h>
> 
> // We'll skip error-checking since this is just for testing purposes.
> 
> void do_connect(int with_tcp_user_timeout) {
>     struct addrinfo hint;
>     struct addrinfo *ai;
>     int sock;
>     time_t start;
>     time_t end;
>     unsigned int timeout = 10000;
> 
>     memset(&hint, 0, sizeof(hint));
>     hint.ai_family = AF_INET;
>     hint.ai_socktype = SOCK_STREAM;
>     hint.ai_protocol = IPPROTO_TCP;
>     getaddrinfo("10.0.42.16", "5432", &hint, &ai);
> 
>     sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
>     if (with_tcp_user_timeout) {
>         setsockopt(
>             sock, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
>             sizeof(timeout)
>         );
>     }
> 
>     printf(
>         "Attempting to connect, with_user_tcp_timeout = %d... ",
>         with_tcp_user_timeout
>     );
>     fflush(stdout);
> 
>     start = time(NULL);
>     connect(sock, ai->ai_addr, ai->ai_addrlen);
>     end = time(NULL);
>     printf("Done!\n");
> 
>     freeaddrinfo(ai);
> 
>     printf(
>         "with_tcp_user_timeout = %d, took %ld seconds\n",
>         with_tcp_user_timeout, end - start
>     );
> }
> 
> int main(void) {
>     // Let's connect with TCP_USER_TIMEOUT first for faster useful
>     // first data.
>     do_connect(1);
>     do_connect(0);
> 
>     exit(EXIT_SUCCESS);
> }
> ```
> 
> This program gives me the following output:
> 
> ```
> $ gcc main.c -Wall -Wextra -Werror && ./a.out
> Attempting to connect, with_user_tcp_timeout = 1... Done!
> with_tcp_user_timeout = 1, took 10 seconds
> Attempting to connect, with_user_tcp_timeout = 0... Done!
> with_tcp_user_timeout = 0, took 130 seconds
> ```
> 
> So it seems like that option does apply when trying to establish a
> connection! This above output was obtained with Linux 5.15.8 and gcc
> 9.3.0.
> 
> Am I reading the manpage wrong, or is the manpage wrong? Or is this
> just an "undocumented behavior" that shouldn't be relied on and can
> be removed without warning in future releases?

I never used TCP_USER_TIMEOUT, so can't answer.  I added Jerry and David
(and netdev@) to the thread, which I guess should know how to answer you
better.

Thanks,

Alex

-- 
Alejandro Colomar
Linux man-pages maintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-01-15 13:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-15 12:23 Possible bug in `tcp(7)` regarding `TCP_USER_TIMEOUT` João Sampaio
2022-01-15 13:28 ` Alejandro Colomar (man-pages)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.