From 3f927b63b75aa3600134be64f99ce9c16ca708a3 Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Wed, 30 Aug 2023 20:45:55 +0800 Subject: [PATCH] tcp_input: update tx_unack before reorder_ofosegs After the sack is enabled and the ofosegs has gap, tcp cannot update the tx_unacked, so the peer received packets are retransmitted after the timer timeout. So update tx_unacked first. Signed-off-by: zhanghongyu --- net/tcp/tcp_input.c | 98 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/net/tcp/tcp_input.c b/net/tcp/tcp_input.c index dcc16d9b07..733e3663ff 100644 --- a/net/tcp/tcp_input.c +++ b/net/tcp/tcp_input.c @@ -1017,55 +1017,6 @@ found: } #endif - /* 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 - * in, unless we are in the SYN_RCVD state and receive a SYN, in which - * case we should retransmit our SYNACK (which is done further down). - */ - - if (!((((conn->tcpstateflags & TCP_STATE_MASK) == TCP_SYN_SENT) && - ((tcp->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) || - (((conn->tcpstateflags & TCP_STATE_MASK) == TCP_SYN_RCVD) && - ((tcp->flags & TCP_CTL) == TCP_SYN)))) - { - uint32_t seq; - uint32_t rcvseq; - - seq = tcp_getsequence(tcp->seqno); - rcvseq = tcp_getsequence(conn->rcvseq); - - if (seq != rcvseq) - { - /* Trim the head of the segment */ - - if (TCP_SEQ_LT(seq, rcvseq)) - { - uint32_t trimlen = TCP_SEQ_SUB(rcvseq, seq); - - if (tcp_trim_head(dev, tcp, trimlen)) - { - /* The segment was completely out of the window. - * E.g. a retransmit which was not necessary. - * E.g. a keep-alive segment. - */ - - tcp_send(dev, conn, TCP_ACK, tcpiplen); - return; - } - } - else - { -#ifdef CONFIG_NET_TCP_OUT_OF_ORDER - /* Queue out-of-order segments. */ - - tcp_input_ofosegs(dev, conn, iplen); -#endif - tcp_send(dev, conn, TCP_ACK, tcpiplen); - return; - } - } - } - /* Check if the incoming segment acknowledges any outstanding data. If so, * we update the sequence number, reset the length of the outstanding * data, calculate RTT estimations, and reset the retransmission timer. @@ -1189,6 +1140,55 @@ found: tcp_update_retrantimer(conn, conn->rto); } + /* 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 + * in, unless we are in the SYN_RCVD state and receive a SYN, in which + * case we should retransmit our SYNACK (which is done further down). + */ + + if (!((((conn->tcpstateflags & TCP_STATE_MASK) == TCP_SYN_SENT) && + ((tcp->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) || + (((conn->tcpstateflags & TCP_STATE_MASK) == TCP_SYN_RCVD) && + ((tcp->flags & TCP_CTL) == TCP_SYN)))) + { + uint32_t seq; + uint32_t rcvseq; + + seq = tcp_getsequence(tcp->seqno); + rcvseq = tcp_getsequence(conn->rcvseq); + + if (seq != rcvseq) + { + /* Trim the head of the segment */ + + if (TCP_SEQ_LT(seq, rcvseq)) + { + uint32_t trimlen = TCP_SEQ_SUB(rcvseq, seq); + + if (tcp_trim_head(dev, tcp, trimlen)) + { + /* The segment was completely out of the window. + * E.g. a retransmit which was not necessary. + * E.g. a keep-alive segment. + */ + + tcp_send(dev, conn, TCP_ACK, tcpiplen); + return; + } + } + else + { +#ifdef CONFIG_NET_TCP_OUT_OF_ORDER + /* Queue out-of-order segments. */ + + tcp_input_ofosegs(dev, conn, iplen); +#endif + tcp_send(dev, conn, TCP_ACK, tcpiplen); + return; + } + } + } + tcp_clear_zero_probe(conn, tcp); /* Update the connection's window size */