diff --git a/ChangeLog b/ChangeLog index b77ba0222b4..77778f1eaa4 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11574,4 +11574,7 @@ 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 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). diff --git a/TODO b/TODO index 74e94c7b5a1..5ee0060a09a 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ -NuttX TODO List (Last updated February 18, 2016) -NuttX TODO List (Last updated February 18, 2016) +NuttX TODO List (Last updated March 19, 2016) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with diff --git a/arch b/arch index 528a3292a06..38d940d253c 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 528a3292a06c79dec673cf85008f5aee7aec9ef7 +Subproject commit 38d940d253cac5b5d9fbe014051789efb2ff2d5d diff --git a/configs b/configs index f7c42ff4a00..f5cb53174df 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit f7c42ff4a006f5d37fa6a818aafaf20886309fd1 +Subproject commit f5cb53174df1ed2e0669fc9295c8e52f424c7d5b diff --git a/net/tcp/tcp_input.c b/net/tcp/tcp_input.c index 3db34ae3846..97bcb402fd7 100644 --- a/net/tcp/tcp_input.c +++ b/net/tcp/tcp_input.c @@ -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 * destined for a connection in LISTEN. If the SYN flag isn't set, * it is an old packet and we send a RST. diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index 3ab9f269d7a..af4766c3098 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -339,7 +339,7 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev, #ifdef CONFIG_NETDEV_MULTINIC /* 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); diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c index 7c0faac458c..6d5c608ba37 100644 --- a/net/tcp/tcp_send_unbuffered.c +++ b/net/tcp/tcp_send_unbuffered.c @@ -292,7 +292,7 @@ static uint16_t tcpsend_interrupt(FAR struct net_driver_s *dev, #ifdef CONFIG_NETDEV_MULTINIC /* 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); diff --git a/net/tcp/tcp_timer.c b/net/tcp/tcp_timer.c index a9681a5c8a1..f14e9b9d688 100644 --- a/net/tcp/tcp_timer.c +++ b/net/tcp/tcp_timer.c @@ -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 || conn->tcpstateflags == TCP_FIN_WAIT_2) { + unsigned int newtimer; + /* Increment the connection timer */ - conn->timer += hsec; - if (conn->timer >= TCP_TIME_WAIT_TIMEOUT) + newtimer = (unsigned int)conn->timer + hsec; + + /* 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) @@ -168,6 +201,22 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, 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? */ 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) { @@ -258,9 +309,20 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, * application for new data. */ - result = tcp_callback(dev, conn, TCP_POLL); - tcp_appsend(dev, conn, result); - goto done; +#ifdef CONFIG_NETDEV_MULTINIC + /* The TCP connection is established and, hence, should be bound + * 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; + } } }