lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] TCP keep-alive not working on half-closed connections


From: address@hidden
Subject: Re: [lwip-users] TCP keep-alive not working on half-closed connections
Date: Wed, 6 Jun 2018 21:13:37 +0200
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0

On 06.06.2018 16:23, Joel Cunningham wrote:



On 06/06/2018 07:45 AM, address@hidden wrote:
On 06.06.2018 11:42, R. Diez wrote:
[..]
The trouble is, this changes the connection state (pcb->state) from
ESTABLISHED to FIN_WAIT_1, which then turns quickly into FIN_WAIT_2.
Afterwards, TCP keep-alive does not work anymore, because of this logic
in tcp_slowtmr():

    /* Check if KEEPALIVE should be sent */
    if (ip_get_option(pcb, SOF_KEEPALIVE) &&
       ((pcb->state == ESTABLISHED) ||
        (pcb->state == CLOSE_WAIT))) {

If I then pull the server's Ethernet cable while the connection is
transferring data, the connection never times out on the client.

I am no TCP/IP expert. Is there an error in my reasoning regarding
half-closed connections? Can TCP keep-alive packets, whatever they are,
still be sent and/or received on half-closed TCP connections?
Half-opened connections should be usable like you did it, yes. I'm not sure about keepalives though.
Technically, keepalives are just empty ACKs, so that should work.

However, I'm not sure wether tcp keepalive is meant to work on half-open connections.


In order to move from ESTABLISHED to FIN_WAIT_1 and ultimately FIN_WAIT_2, your application would have had to shutdown the TX pathway (either a call to shutdown() or close()). In this scenario, TCP can no longer send data packets, so you couldn't detect a half-open connection by sending data. Since the connection is in a receive only state, either a FIN_WAIT_2 timeout or TCP keepalives with no data could be used.

I believe keepalives are used in this case, I found some evidence with a quick google.

Right. The RFCs I read don't speak about tcp states, so it seems OK to continue keepalives in the FIN_WAIT states.
It might even be OK in CLOSE_WAIT, as RFC 1122 says keepalive packets must only be sent "when no data or acknowledgement packets have been received".

  A more exhaustive study of other stacks would be a good to confirm this behavior.

A quick look at the Linux sources tells me they continue keepalives in all states...


https://stackoverflow.com/questions/18110239/does-tcp-endpoint-that-has-sent-a-fin-still-send-keepalive
https://social.msdn.microsoft.com/Forums/en-US/d20e5e67-d23c-42a5-95c5-ba80f4263546/keepalive-packets-continue-being-sent-after-client-closes-server-socket-is-closewait-client

Here's some findings on a FIN_WAIT_2 timeout:

https://serverfault.com/questions/738300/why-are-connections-in-fin-wait2-state-not-closed-by-the-linux-kernel
https://www.akronohio.gov/manual/misc/fin_wait_2.html

I don't believe a FIN_WAIT_2 timeout is implemented in LwIP.

No, we don't have that. We always said it's OK for a connection to stay in FIN_WAIT_2. However, it seems we must handle this differently depending on wether the user has called "shutdown" or "close". Then we can implement a timeout.

I'm also thinking this issue may not be that common since tcp_alloc would reap the half-open connection eventually to prevent pcb exhaustion

I don't think tcp_alloc will kill pcbs in FIN_WAIT_2 unless they have a lower priority. A timeout on FIN_WAIT_2 *does* make sense!


Simon

reply via email to

[Prev in Thread] Current Thread [Next in Thread]