FreeRTOS+TCP KeepAlive behaviour

benzer350 wrote on Monday, October 16, 2017:

For a TCP connection socket, when disconnecting the other device, the stack sends 3 keepalive packets then closes the socket which is great.
The problem happens when the device itself is disconnected from the switch (pulled cable out - link down). The IP task detects the link down successfuly then calls the driver initialization function and blocks there until link up (this is the recommended behavior per a comment in the stack code): from FreeRTOS_IP line 1332:
if( xNetworkInterfaceInitialise() != pdPASS )
{
/* Ideally the network interface initialisation function will only
return when the network is available. In case this is not the case,
wait a while before retrying the initialisation. */
vTaskDelay( ipINITIALISATION_RETRY_DELAY );
FreeRTOS_NetworkDown();
}

The problem with that is that the task is blocked here and as a result the keep alive counters are stopped and the connection never closes. 
Is this the intent? Am I missing  some concept? I would like the connection to timeout after such an event so the server is free again for another device

heinbali01 wrote on Tuesday, October 17, 2017:

Hi Ben,

What platform are you using?

For a TCP connection socket, when disconnecting the other device, the stack
sends 3 keepalive packets then closes the socket which is great.

Just to make it clear, you mean physically disconnecting. The remote device is unplugged and it will no longer respond to the keep-alive messages. After a third message, the socket gets into a eCLOSE_WAIT state, i.e. the socket shall be closed by the application (without shutting it down).

In source code:

	BaseType_t rc = FreeRTOS_recv( xSocket, pucBuffer, sizeof( pucBuffer ), 0 );
	if( rc == -pdFREERTOS_ERRNO_ENOTCONN )
	{
		// The socket is not connected any more
		FreeRTOS_closesocket( xSocket );
		xSocket = NULL;
	}

And now you unplug your +TCP device from the LAN:

…pulled cable out - link down. The IP task detects the link down successfully
then calls the driver initialization function and blocks there until link up
(this is the recommended behavior per a comment in the stack code)

This was indeed how the IP-stack used to work, but since we have keep-alive packets, I tend not to use FreeRTOS_NetworkDown() any more. Once the +TCP stack is up, let it stay up.

It is important that xNetworkInterfaceOutput() does not attempt to send data as long as the Link Status is low. That would lead to delays and errors.

benzer350 wrote on Wednesday, October 18, 2017:

Thanks Hein, Keeping the stack up seems to solve this. When the link is down I make xNetworkInterfaceOutput() return a _FALSE after releasing the packet buffer.

heinbali01 wrote on Wednesday, October 18, 2017:

When the link is down I make xNetworkInterfaceOutput() return
a FALSE after releasing the packet buffer

After checking the value of bReleaseAfterSend, I suppose:

    if( bReleaseAfterSend != pdFALSE )
    {
        vReleaseNetworkBufferAndDescriptor( pxDescriptor );
    }

xNetworkInterfaceOutput() is called from four different places, and the return value is never tested.

Regards.