Bug 108191 - tcp option TCP_USER_TIMEOUT working incorrect within tcp keepalive.
Summary: tcp option TCP_USER_TIMEOUT working incorrect within tcp keepalive.
Status: NEW
Alias: None
Product: Networking
Classification: Unclassified
Component: IPV4 (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Stephen Hemminger
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-11-20 11:03 UTC by hujunjie
Modified: 2018-02-22 03:11 UTC (History)
2 users (show)

See Also:
Kernel Version: 4.3
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description hujunjie 2015-11-20 11:03:58 UTC
The TCP_USER_TIMEOUT semantic means when you send an packet,
how long time no received the ACK should disconnect the connection.

In tcp retransmits case, 
retransmits_timed_out checkout this timeout, it walks well.

but in keepalive case.
the code below may have bugs:

....
    elapsed = keepalive_time_elapsed(tp);

    if (elapsed >= keepalive_time_when(tp)) {
        /* If the TCP_USER_TIMEOUT option is enabled, use that
         * to determine when to timeout instead.
         */
        if ((icsk->icsk_user_timeout != 0 &&
            elapsed >= icsk->icsk_user_timeout &&
            icsk->icsk_probes_out > 0) ||
            (icsk->icsk_user_timeout == 0 &&
            icsk->icsk_probes_out >= keepalive_probes(tp))) {
            tcp_send_active_reset(sk, GFP_ATOMIC);
            tcp_write_err(sk);
            goto out;
        }
.....
elapsed >= icsk->icsk_user_timeout should be
elapsed-keepalive_time_when(tp) >= icsk->icsk_user_timeout 

here is the timeline:

idle   .......   keepalive1         ......       keepalive2 ... keepalive_probes
<- katime_when ->          <- keepalive_intvl  ->
                 <-  TCP_USER_TIMEOUT ->  // user expected timeout
<---------------elapsed---------------->
                 <-elapsed-katime_when->


/* test code */
int v;
v=1;setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &v, 4);
v=30;setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &v, 4);
v=5;setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &v, 4);
v=3;setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &v, 4);
v=20*1000; setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, &v, 4); 
connect(fd, addr, sizeof(addr);
// when connect
// drop the recv data
// iptables -t filter -A INPUT --protocol tcp --dport 8888 -j DROP
pause();

we can see 30s later, tcp start keepalive, and close connection
without do the  first retransmits (because 30+5 > 20)
but we want waiting 20 second.
Comment 1 [account disabled by administrator] 2016-04-21 17:24:10 UTC
That is not a complete program can you send me the complete code as a attachment so I can make sure that there is indeed a issue here. Seems correct but would like to verify it.
Comment 2 wangbojing 2018-02-22 03:11:47 UTC
your should use tcpdump to catch packet and paste your message.

Note You need to log in before you can comment on or make changes to this bug.