net/tcp_timer: fix tcp_timer idle loop and retransmission bug

1. Tcp will idle loop by tcp_timer when have no packet to send. This will cause low-power devices to be frequently woken up.
2. We should add tcp_timer when timer has been canceled and have packet to send.

Signed-off-by: meijian <meijian@xiaomi.com>
This commit is contained in:
meijian 2024-08-22 21:35:16 +08:00 committed by Xiang Xiao
parent fb72fe6364
commit c0eef6c137
2 changed files with 20 additions and 5 deletions

View File

@ -1028,6 +1028,7 @@ found:
{ {
uint32_t unackseq; uint32_t unackseq;
uint32_t ackseq; uint32_t ackseq;
int timeout;
/* The next sequence number is equal to the current sequence /* The next sequence number is equal to the current sequence
* number (sndseq) plus the size of the outstanding, unacknowledged * number (sndseq) plus the size of the outstanding, unacknowledged
@ -1137,9 +1138,20 @@ found:
flags |= TCP_ACKDATA; flags |= TCP_ACKDATA;
/* Check if no packet need to retransmission, clear timer. */
if (conn->tx_unacked == 0 && conn->tcpstateflags == TCP_ESTABLISHED)
{
timeout = 0;
}
else
{
timeout = conn->rto;
}
/* Reset the retransmission timer. */ /* Reset the retransmission timer. */
tcp_update_retrantimer(conn, conn->rto); tcp_update_retrantimer(conn, timeout);
} }
/* Check if the sequence number of the incoming packet is what we are /* Check if the sequence number of the incoming packet is what we are
@ -1211,10 +1223,6 @@ found:
/* Window updated, set the acknowledged flag. */ /* Window updated, set the acknowledged flag. */
flags |= TCP_ACKDATA; flags |= TCP_ACKDATA;
/* Reset the retransmission timer. */
tcp_update_retrantimer(conn, conn->rto);
} }
} }

View File

@ -55,6 +55,7 @@
#include <nuttx/net/netstats.h> #include <nuttx/net/netstats.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>
#include <nuttx/net/tcp.h> #include <nuttx/net/tcp.h>
#include <nuttx/wqueue.h>
#include "netdev/netdev.h" #include "netdev/netdev.h"
#include "devif/devif.h" #include "devif/devif.h"
@ -146,6 +147,12 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
} }
else else
{ {
if (work_available(&conn->work) && conn->tx_unacked != 0)
{
conn->timeout = false;
tcp_update_retrantimer(conn, conn->rto);
}
/* Update the TCP received window based on I/O buffer availability */ /* Update the TCP received window based on I/O buffer availability */
uint32_t rcvseq = tcp_getsequence(conn->rcvseq); uint32_t rcvseq = tcp_getsequence(conn->rcvseq);