TCP timeouts: Fix some logic when there are multiple network interfaces. In this case, TCP timeout events can really only being processed when the poll from the correct device is received.

This commit is contained in:
Gregory Nutt 2016-03-20 08:19:00 -06:00
parent 75a4a5dcbe
commit 4639cdd894
8 changed files with 81 additions and 17 deletions

View File

@ -11574,4 +11574,7 @@
status is not real time but is delayed. This was fixed; now when the DMA status is not real time but is delayed. This was fixed; now when the DMA
completes and NBUSYBKS > 0, the NBUSYBK is interrupt is enabled and the completes and NBUSYBKS > 0, the NBUSYBK is interrupt is enabled and the
operations are deferred until NBUSYBKS is truly zero (2016-03-17). operations are deferred until NBUSYBKS is truly zero (2016-03-17).
* net/tcp/tcp_timer.c: Fix some logic when there are multiple network
interfaces. In this case, TCP timeout events can really only bei
processed when the poll from the correct device is received (2016-03-20).

3
TODO
View File

@ -1,5 +1,4 @@
NuttX TODO List (Last updated February 18, 2016) NuttX TODO List (Last updated March 19, 2016)
NuttX TODO List (Last updated February 18, 2016)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with This file summarizes known NuttX bugs, limitations, inconsistencies with

2
arch

@ -1 +1 @@
Subproject commit 528a3292a06c79dec673cf85008f5aee7aec9ef7 Subproject commit 38d940d253cac5b5d9fbe014051789efb2ff2d5d

@ -1 +1 @@
Subproject commit f7c42ff4a006f5d37fa6a818aafaf20886309fd1 Subproject commit f5cb53174df1ed2e0669fc9295c8e52f424c7d5b

View File

@ -152,7 +152,7 @@ static void tcp_input(FAR struct net_driver_s *dev, unsigned int iplen)
} }
} }
/* If we didn't find and active connection that expected the packet, /* If we didn't find an active connection that expected the packet,
* either (1) this packet is an old duplicate, or (2) this is a SYN packet * either (1) this packet is an old duplicate, or (2) this is a SYN packet
* destined for a connection in LISTEN. If the SYN flag isn't set, * destined for a connection in LISTEN. If the SYN flag isn't set,
* it is an old packet and we send a RST. * it is an old packet and we send a RST.

View File

@ -339,7 +339,7 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev,
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
/* The TCP socket is connected and, hence, should be bound to a device. /* The TCP socket is connected and, hence, should be bound to a device.
* Make sure that the polling device is the own that we are bound to. * Make sure that the polling device is the one that we are bound to.
*/ */
DEBUGASSERT(conn->dev != NULL); DEBUGASSERT(conn->dev != NULL);

View File

@ -292,7 +292,7 @@ static uint16_t tcpsend_interrupt(FAR struct net_driver_s *dev,
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
/* The TCP socket is connected and, hence, should be bound to a device. /* The TCP socket is connected and, hence, should be bound to a device.
* Make sure that the polling device is the own that we are bound to. * Make sure that the polling device is the one that we are bound to.
*/ */
DEBUGASSERT(conn->dev != NULL); DEBUGASSERT(conn->dev != NULL);

View File

@ -131,18 +131,51 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
if (conn->tcpstateflags == TCP_TIME_WAIT || if (conn->tcpstateflags == TCP_TIME_WAIT ||
conn->tcpstateflags == TCP_FIN_WAIT_2) conn->tcpstateflags == TCP_FIN_WAIT_2)
{ {
unsigned int newtimer;
/* Increment the connection timer */ /* Increment the connection timer */
conn->timer += hsec; newtimer = (unsigned int)conn->timer + hsec;
if (conn->timer >= TCP_TIME_WAIT_TIMEOUT)
/* Check if the timer exceeds the timeout value */
if (newtimer >= TCP_TIME_WAIT_TIMEOUT)
{ {
conn->tcpstateflags = TCP_CLOSED; /* Set the timer to the maximum value */
/* Notify upper layers about the timeout */ conn->timer = TCP_TIME_WAIT_TIMEOUT;
result = tcp_callback(dev, conn, TCP_TIMEDOUT); #ifdef CONFIG_NETDEV_MULTINIC
/* The TCP connection was established and, hence, should be bound
* to a device. Make sure that the polling device is the one that
* we are bound to.
*
* If not, then we will catch the timeout on the next poll from
* the correct device.
*/
nllvdbg("TCP state: TCP_CLOSED\n"); DEBUGASSERT(conn->dev != NULL);
if (dev != conn->dev)
{
nllvdbg("TCP: TCP_CLOSED pending\n");
}
else
#endif
{
conn->tcpstateflags = TCP_CLOSED;
/* Notify upper layers about the timeout */
result = tcp_callback(dev, conn, TCP_TIMEDOUT);
nllvdbg("TCP state: TCP_CLOSED\n");
}
}
else
{
/* No timeout. Just update the incremented timer */
conn->timer = newtimer;
} }
} }
else if (conn->tcpstateflags != TCP_CLOSED) else if (conn->tcpstateflags != TCP_CLOSED)
@ -168,6 +201,22 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
conn->timer = 0; conn->timer = 0;
#ifdef CONFIG_NETDEV_MULTINIC
/* The TCP is connected and, hence, should be bound to a
* device. Make sure that the polling device is the one that
* we are bound to.
*
* If not, then we will catch the timeout on the next poll
* from the correct device.
*/
DEBUGASSERT(conn->dev != NULL);
if (dev != conn->dev)
{
nllvdbg("TCP: TCP_CLOSED pending\n");
goto done;
}
#endif
/* Should we close the connection? */ /* Should we close the connection? */
if ( if (
@ -250,7 +299,9 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
} }
} }
/* The connection does not have outstanding data */ /* The connection does not have outstanding data. Check if the TCP
* connection has been established.
*/
else if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED) else if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
{ {
@ -258,9 +309,20 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
* application for new data. * application for new data.
*/ */
result = tcp_callback(dev, conn, TCP_POLL); #ifdef CONFIG_NETDEV_MULTINIC
tcp_appsend(dev, conn, result); /* The TCP connection is established and, hence, should be bound
goto done; * to a device. Make sure that the polling device is the one that
* we are bound to.
*/
DEBUGASSERT(conn->dev != NULL);
if (dev == conn->dev)
#endif
{
result = tcp_callback(dev, conn, TCP_POLL);
tcp_appsend(dev, conn, result);
goto done;
}
} }
} }