You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/01/02 15:25:22 UTC
[incubator-nuttx] branch master updated: net/tcp(unbuffered): fast retransmit on duplicate acknowledgments
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 0afb1d8 net/tcp(unbuffered): fast retransmit on duplicate acknowledgments
0afb1d8 is described below
commit 0afb1d8dbb14c30660a64761fd3b0aaa8e5101a5
Author: Alexander Lunev <al...@mail.ru>
AuthorDate: Sun Jan 2 07:15:57 2022 +0300
net/tcp(unbuffered): fast retransmit on duplicate acknowledgments
---
net/tcp/tcp_send_unbuffered.c | 60 +++++++++++++++++++++++++++++++++++--------
1 file changed, 49 insertions(+), 11 deletions(-)
diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c
index d2e0aa1..01f5055 100644
--- a/net/tcp/tcp_send_unbuffered.c
+++ b/net/tcp/tcp_send_unbuffered.c
@@ -80,14 +80,23 @@
struct send_s
{
- FAR struct socket *snd_sock; /* Points to the parent socket structure */
- FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
- sem_t snd_sem; /* Used to wake up the waiting thread */
- FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */
- size_t snd_buflen; /* Number of bytes in the buffer to send */
- ssize_t snd_sent; /* The number of bytes sent */
- uint32_t snd_isn; /* Initial sequence number */
- uint32_t snd_acked; /* The number of bytes acked */
+ FAR struct socket *snd_sock; /* Points to the parent socket structure */
+ FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
+ sem_t snd_sem; /* Used to wake up the waiting thread */
+ FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */
+ size_t snd_buflen; /* Number of bytes in the buffer to send */
+ ssize_t snd_sent; /* The number of bytes sent */
+ uint32_t snd_isn; /* Initial sequence number */
+ uint32_t snd_acked; /* The number of bytes acked */
+ uint32_t snd_prev_ack; /* The previous ACKed seq number */
+#ifdef CONFIG_NET_TCP_WINDOW_SCALE
+ uint32_t snd_prev_wnd; /* The advertised window in the last
+ * incoming acknowledgment
+ */
+#else
+ uint16_t snd_prev_wnd;
+#endif
+ int snd_dup_acks; /* Duplicate ACK counter */
};
/****************************************************************************
@@ -183,6 +192,7 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
if ((flags & TCP_ACKDATA) != 0)
{
+ uint32_t ackno;
FAR struct tcp_hdr_s *tcp;
/* Get the offset address of the TCP header */
@@ -213,7 +223,8 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
* of bytes to be acknowledged.
*/
- pstate->snd_acked = TCP_SEQ_SUB(tcp_getsequence(tcp->ackno),
+ ackno = tcp_getsequence(tcp->ackno);
+ pstate->snd_acked = TCP_SEQ_SUB(ackno,
pstate->snd_isn);
ninfo("ACK: acked=%" PRId32 " sent=%zd buflen=%zd\n",
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
@@ -229,12 +240,39 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
goto end_wait;
}
- /* No.. fall through to send more data if necessary */
+ /* Fast Retransmit (RFC 5681): an acknowledgment is considered a
+ * "duplicate" when (a) the receiver of the ACK has outstanding data,
+ * (b) the incoming acknowledgment carries no data, (c) the SYN and
+ * FIN bits are both off, (d) the acknowledgment number is equal to
+ * the greatest acknowledgment received on the given connection
+ * and (e) the advertised window in the incoming acknowledgment equals
+ * the advertised window in the last incoming acknowledgment.
+ */
+
+ if (pstate->snd_acked < pstate->snd_sent &&
+ (flags & TCP_NEWDATA) == 0 &&
+ (tcp->flags & (TCP_SYN | TCP_FIN)) == 0 &&
+ ackno == pstate->snd_prev_ack &&
+ conn->snd_wnd == pstate->snd_prev_wnd)
+ {
+ if (++pstate->snd_dup_acks >=
+ CONFIG_NET_TCP_FAST_RETRANSMIT_WATERMARK)
+ {
+ flags |= TCP_REXMIT;
+ }
+ }
+ else
+ {
+ pstate->snd_dup_acks = 0;
+ }
+
+ pstate->snd_prev_ack = ackno;
+ pstate->snd_prev_wnd = conn->snd_wnd;
}
/* Check if we are being asked to retransmit data */
- else if ((flags & TCP_REXMIT) != 0)
+ if ((flags & TCP_REXMIT) != 0)
{
/* According to RFC 6298 (5.4), retransmit the earliest segment
* that has not been acknowledged by the TCP receiver.