net/tcp: support OTW check and response with an empty acknowledgment segment

According RFC793,p72~p73 In states from ESTABLISHED to LASTACK:"If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK, drop the segment, and return"

Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
This commit is contained in:
wenquan1
2025-08-25 13:34:49 +08:00
committed by Xiang Xiao
parent facb9d4e65
commit 8ead446ee4
2 changed files with 31 additions and 14 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ static void tcp_close_work(FAR void *param)
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)param; FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)param;
conn->flags &= ~TCP_CLOSE_ARRANGED; conn->flags &= ~TCP_CLOSE_ARRANGED;
if (conn->crefs == 0) if (conn->crefs == 0 && conn->tcpstateflags == TCP_CLOSED)
{ {
/* Stop the network monitor for all sockets */ /* Stop the network monitor for all sockets */
+30 -13
View File
@@ -992,8 +992,9 @@ found:
* data, calculate RTT estimations, and reset the retransmission timer. * data, calculate RTT estimations, and reset the retransmission timer.
*/ */
if ((tcp->flags & TCP_ACK) != 0 && conn->tx_unacked > 0) if ((tcp->flags & TCP_ACK) != 0)
{ {
uint32_t lasttxunacked = conn->tx_unacked;
uint32_t unackseq; uint32_t unackseq;
uint32_t ackseq; uint32_t ackseq;
int timeout; int timeout;
@@ -1035,7 +1036,17 @@ found:
{ {
/* Calculate the new number of outstanding, unacknowledged bytes */ /* Calculate the new number of outstanding, unacknowledged bytes */
conn->tx_unacked = unackseq - ackseq; if (conn->tx_unacked < unackseq - ackseq)
{
/* old ack */
tcp_send(dev, conn, TCP_ACK, tcpiplen);
return;
}
else
{
conn->tx_unacked = unackseq - ackseq;
}
} }
else else
{ {
@@ -1045,20 +1056,24 @@ found:
* bytes * bytes
*/ */
if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED || /* RFC793,p72~p73 In states from ESTABLISHED to LASTACK:"If the
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_CLOSE_WAIT) * ACK acks something not yet sent (SEG.ACK > SND.NXT) then send
{ * an ACK, drop the segment, and return."
nwarn("WARNING: ackseq > unackseq\n"); */
nwarn("sndseq=%" PRIu32 " tx_unacked=%" PRIu32
" unackseq=%" PRIu32 " ackseq=%" PRIu32 "\n",
tcp_getsequence(conn->sndseq),
(uint32_t)conn->tx_unacked,
unackseq, ackseq);
conn->tx_unacked = 0; if ((conn->tcpstateflags & TCP_STATE_MASK) >= TCP_ESTABLISHED &&
(conn->tcpstateflags & TCP_STATE_MASK) <= TCP_LAST_ACK)
{
tcp_send(dev, conn, TCP_ACK, tcpiplen);
return;
} }
} }
if (lasttxunacked == 0)
{
goto skip_rtt;
}
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS #ifdef CONFIG_NET_TCP_WRITE_BUFFERS
#ifdef CONFIG_NET_SENDFILE #ifdef CONFIG_NET_SENDFILE
if (!conn->sendfile) if (!conn->sendfile)
@@ -1127,6 +1142,8 @@ found:
tcp_update_retrantimer(conn, timeout); tcp_update_retrantimer(conn, timeout);
} }
skip_rtt:
/* 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
* expecting next. If not, we send out an ACK with the correct numbers * expecting next. If not, we send out an ACK with the correct numbers
* in, unless we are in the SYN_RCVD state and receive a SYN, in which * in, unless we are in the SYN_RCVD state and receive a SYN, in which
@@ -1269,7 +1286,7 @@ found:
conn->isn = tcp_getsequence(tcp->ackno); conn->isn = tcp_getsequence(tcp->ackno);
tcp_setsequence(conn->sndseq, conn->isn); tcp_setsequence(conn->sndseq, conn->isn);
conn->sent = 0; conn->sent = 0;
conn->sndseq_max = 0; conn->sndseq_max = conn->isn;
#endif #endif
conn->tx_unacked = 0; conn->tx_unacked = 0;
tcp_snd_wnd_init(conn, tcp); tcp_snd_wnd_init(conn, tcp);