1
0
Fork 0
forked from nuttx/nuttx-update

net/tcp(unbuffered): fast retransmit on duplicate acknowledgments

This commit is contained in:
Alexander Lunev 2022-01-02 07:15:57 +03:00 committed by Xiang Xiao
parent f345f3dc2e
commit 0afb1d8dbb

View file

@ -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.