mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 23:40:19 +08:00
net/tcp/sendfile: retransmit only one the earliest not acknowledged segment
(according to RFC 6298 (5.4)). The issue is the same as it was in tcp_send_unbuffered.c.
This commit is contained in:
committed by
Xiang Xiao
parent
133faf203d
commit
64dd669749
+2
-1
@@ -172,7 +172,8 @@ struct tcp_conn_s
|
|||||||
uint8_t rcvseq[4]; /* The sequence number that we expect to
|
uint8_t rcvseq[4]; /* The sequence number that we expect to
|
||||||
* receive next */
|
* receive next */
|
||||||
uint8_t sndseq[4]; /* The sequence number that was last sent by us */
|
uint8_t sndseq[4]; /* The sequence number that was last sent by us */
|
||||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS) || \
|
||||||
|
defined(CONFIG_NET_SENDFILE)
|
||||||
uint32_t rexmit_seq; /* The sequence number to be retrasmitted */
|
uint32_t rexmit_seq; /* The sequence number to be retrasmitted */
|
||||||
#endif
|
#endif
|
||||||
uint8_t crefs; /* Reference counts on this instance */
|
uint8_t crefs; /* Reference counts on this instance */
|
||||||
|
|||||||
+28
-18
@@ -322,26 +322,36 @@ void tcp_rexmit(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
|||||||
* new data in it, we must send out a packet.
|
* new data in it, we must send out a packet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_NET_SENDFILE)
|
||||||
|
if (conn->sendfile)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_SENDFILE)
|
||||||
|
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);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||||
if (dev->d_sndlen > 0)
|
if (dev->d_sndlen > 0)
|
||||||
#else
|
#else
|
||||||
if ((result & TCP_REXMIT) != 0 &&
|
if (dev->d_sndlen > 0 && conn->tx_unacked > 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
|
#endif
|
||||||
{
|
{
|
||||||
uint32_t seq;
|
uint32_t seq;
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
if ((flags & TCP_REXMIT) != 0)
|
if ((flags & TCP_REXMIT) != 0)
|
||||||
{
|
{
|
||||||
|
nwarn("WARNING: TCP_REXMIT\n");
|
||||||
|
|
||||||
/* According to RFC 6298 (5.4), retransmit the earliest segment
|
/* According to RFC 6298 (5.4), retransmit the earliest segment
|
||||||
* that has not been acknowledged by the TCP receiver.
|
* that has not been acknowledged by the TCP receiver.
|
||||||
*/
|
*/
|
||||||
@@ -430,6 +432,10 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
ninfo("SEND: acked=%" PRId32 " sent=%zd buflen=%zd\n",
|
ninfo("SEND: acked=%" PRId32 " sent=%zd buflen=%zd\n",
|
||||||
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
|
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nwarn("WARNING: Window full, wait for ack\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Continue waiting */
|
/* Continue waiting */
|
||||||
|
|||||||
+39
-6
@@ -276,14 +276,47 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
{
|
{
|
||||||
nwarn("WARNING: TCP_REXMIT\n");
|
nwarn("WARNING: TCP_REXMIT\n");
|
||||||
|
|
||||||
/* Yes.. in this case, reset the number of bytes that have been sent
|
/* According to RFC 6298 (5.4), retransmit the earliest segment
|
||||||
* to the number of bytes that have been ACKed.
|
* 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 */
|
||||||
#ifndef CONFIG_NET_TCP_WRITE_BUFFERS
|
|
||||||
conn->rexmit_seq = pstate->snd_sent + pstate->snd_isn;
|
uint32_t sndlen = pstate->snd_flen - pstate->snd_acked;
|
||||||
#endif
|
|
||||||
|
if (sndlen > conn->mss)
|
||||||
|
{
|
||||||
|
sndlen = conn->mss;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->rexmit_seq = pstate->snd_isn + pstate->snd_acked;
|
||||||
|
|
||||||
|
/* Then set-up to send that amount of data. (this won't actually
|
||||||
|
* happen until the polling cycle completes).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = file_seek(pstate->snd_file,
|
||||||
|
pstate->snd_foffset + pstate->snd_acked, SEEK_SET);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nerr("ERROR: Failed to lseek: %d\n", ret);
|
||||||
|
pstate->snd_sent = ret;
|
||||||
|
goto end_wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = file_read(pstate->snd_file, dev->d_appdata, sndlen);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nerr("ERROR: Failed to read from input file: %d\n", (int)ret);
|
||||||
|
pstate->snd_sent = ret;
|
||||||
|
goto end_wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->d_sndlen = sndlen;
|
||||||
|
|
||||||
|
/* Continue waiting */
|
||||||
|
|
||||||
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for a loss of connection.
|
/* Check for a loss of connection.
|
||||||
|
|||||||
Reference in New Issue
Block a user