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 2021/11/10 18:21:14 UTC
[incubator-nuttx] branch master updated: net/tcp(unbuffered):
retransmit only one the earliest not acknowledged segment (according to RFC
6298 (5.4)).
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 1e07b6d net/tcp(unbuffered): retransmit only one the earliest not acknowledged segment (according to RFC 6298 (5.4)).
1e07b6d is described below
commit 1e07b6d528ab52dd179e6631991c683749c7635d
Author: Alexander Lunev <al...@mail.ru>
AuthorDate: Tue Oct 12 07:15:54 2021 +0300
net/tcp(unbuffered): retransmit only one the earliest not acknowledged segment
(according to RFC 6298 (5.4)).
---
net/tcp/tcp.h | 3 +++
net/tcp/tcp_appsend.c | 18 +++++++++++++++++-
net/tcp/tcp_send_unbuffered.c | 36 ++++++++++++++++++++++++++++++++----
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h
index 7e55d36..245cba1 100644
--- a/net/tcp/tcp.h
+++ b/net/tcp/tcp.h
@@ -172,6 +172,9 @@ struct tcp_conn_s
uint8_t rcvseq[4]; /* The sequence number that we expect to
* receive next */
uint8_t sndseq[4]; /* The sequence number that was last sent by us */
+#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
+ uint32_t rexmit_seq; /* The sequence number to be retrasmitted */
+#endif
uint8_t crefs; /* Reference counts on this instance */
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
uint8_t domain; /* IP domain: PF_INET or PF_INET6 */
diff --git a/net/tcp/tcp_appsend.c b/net/tcp/tcp_appsend.c
index c31a942..467d567 100644
--- a/net/tcp/tcp_appsend.c
+++ b/net/tcp/tcp_appsend.c
@@ -316,7 +316,23 @@ void tcp_rexmit(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
if (dev->d_sndlen > 0)
#else
- if (dev->d_sndlen > 0 && conn->tx_unacked > 0)
+ if ((result & TCP_REXMIT) != 0 &&
+ dev->d_sndlen > 0 && conn->tx_unacked > 0)
+ {
+ uint32_t saveseq;
+
+ /* According to RFC 6298 (5.4), retransmit the earliest segment
+ * that has not been acknowledged by the TCP receiver.
+ */
+
+ saveseq = tcp_getsequence(conn->sndseq);
+ tcp_setsequence(conn->sndseq, conn->rexmit_seq);
+
+ tcp_send(dev, conn, TCP_ACK | TCP_PSH, dev->d_sndlen + hdrlen);
+
+ tcp_setsequence(conn->sndseq, saveseq);
+ }
+ else if (dev->d_sndlen > 0 && conn->tx_unacked > 0)
#endif
{
uint32_t seq;
diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c
index c309e27..aa3605b 100644
--- a/net/tcp/tcp_send_unbuffered.c
+++ b/net/tcp/tcp_send_unbuffered.c
@@ -236,13 +236,41 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
else if ((flags & TCP_REXMIT) != 0)
{
- /* Yes.. in this case, reset the number of bytes that have been sent
- * to the number of bytes that have been ACKed.
+ /* According to RFC 6298 (5.4), retransmit the earliest segment
+ * that has not been acknowledged by the TCP receiver.
*/
- pstate->snd_sent = pstate->snd_acked;
+ /* Reconstruct the length of the earliest segment to be retransmitted */
- /* Fall through to re-send data from the last that was ACKed */
+ uint32_t sndlen = pstate->snd_buflen - pstate->snd_acked;
+
+ if (sndlen > conn->mss)
+ {
+ sndlen = conn->mss;
+ }
+
+ conn->rexmit_seq = pstate->snd_isn + pstate->snd_acked;
+
+#ifdef NEED_IPDOMAIN_SUPPORT
+ /* If both IPv4 and IPv6 support are enabled, then we will need to
+ * select which one to use when generating the outgoing packet.
+ * If only one domain is selected, then the setup is already in
+ * place and we need do nothing.
+ */
+
+ tcpsend_ipselect(dev, conn);
+#endif
+ /* Then set-up to send that amount of data. (this won't actually
+ * happen until the polling cycle completes).
+ */
+
+ devif_send(dev,
+ &pstate->snd_buffer[pstate->snd_acked],
+ sndlen);
+
+ /* Continue waiting */
+
+ return flags;
}
/* Check for a loss of connection */