This commit adds an initial implemented of TCP delayed ACKs as specified in RFC 1122.
Squashed commit of the following: net/tmp: Rename the unacked field of the tcp connection structure to tx_unacked. Too confusing with the implementation of delayed RX ACKs. net/tcp: Initial implementation of TCP delayed ACKs. net/tcp: Add delayed ACK configuration selection. Rename tcp_ack() to tcp_synack(). It may or may not send a ACK. It will always send SYN or SYN/ACK.
This commit is contained in:
parent
594734e0ae
commit
66ef6d143a
@ -164,7 +164,7 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev,
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Check if all outstanding bytes have been ACKed */
|
||||
|
||||
if (conn->unacked != 0 || !sq_empty(&conn->write_q))
|
||||
if (conn->tx_unacked != 0 || !sq_empty(&conn->write_q))
|
||||
{
|
||||
/* No... we are still waiting for ACKs. Drop any received data, but
|
||||
* do not yet report TCP_CLOSE in the response.
|
||||
|
@ -557,29 +557,29 @@ static uint16_t tcp_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
/* Increment the count of bytes sent, the number of unacked bytes,
|
||||
* and the total count of TCP packets sent.
|
||||
*
|
||||
* NOTE: tcp_appsend() normally increments conn->unacked based on
|
||||
* NOTE: tcp_appsend() normally increments conn->tx_unacked based on
|
||||
* the value of dev->d_sndlen. However, dev->d_len is always
|
||||
* zero for 6LoWPAN since it does not send via the dev->d_buf
|
||||
* but, rather, uses a backdoor frame interface with the IEEE
|
||||
* 802.15.4 MAC.
|
||||
*/
|
||||
|
||||
sinfo->s_sent += sndlen;
|
||||
conn->unacked += sndlen;
|
||||
sinfo->s_sent += sndlen;
|
||||
conn->tx_unacked += sndlen;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* For compability with buffered send logic */
|
||||
|
||||
conn->sndseq_max = tcp_addsequence(conn->sndseq, conn->unacked);
|
||||
conn->sndseq_max = tcp_addsequence(conn->sndseq, conn->tx_unacked);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
g_netstats.tcp.sent++;
|
||||
#endif
|
||||
|
||||
ninfo("Sent: acked=%d sent=%d buflen=%d unacked=%d\n",
|
||||
ninfo("Sent: acked=%d sent=%d buflen=%d tx_unacked=%d\n",
|
||||
sinfo->s_acked, sinfo->s_sent, sinfo->s_buflen,
|
||||
conn->unacked);
|
||||
conn->tx_unacked);
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,7 +612,7 @@ end_wait:
|
||||
|
||||
/* There are no outstanding, unacknowledged bytes */
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
@ -710,7 +710,7 @@ static int sixlowpan_send_packet(FAR struct socket *psock,
|
||||
* initial sequence number.
|
||||
*/
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
/* Notify the IEEE802.15.4 MAC that we have data to send. */
|
||||
|
||||
|
@ -20,6 +20,20 @@ config NET_TCP_NO_STACK
|
||||
|
||||
if NET_TCP && !NET_TCP_NO_STACK
|
||||
|
||||
config NET_TCP_DELAYED_ACK
|
||||
bool "TCP/IP Delayed ACK"
|
||||
default n
|
||||
---help---
|
||||
RFC 1122: A host that is receiving a stream of TCP data segments
|
||||
can increase efficiency in both the Internet and the hosts
|
||||
by sending fewer than one ACK (acknowledgment) segment per data
|
||||
segment received; this is known as a "delayed ACK".
|
||||
|
||||
TCP should implement a delayed ACK, but an ACK should not be
|
||||
excessively delayed; in particular, the delay MUST be less than
|
||||
0.5 seconds, and in a stream of full-sized segments there should
|
||||
be an ACK for at least every second segments.
|
||||
|
||||
config NET_TCP_KEEPALIVE
|
||||
bool "TCP/IP Keep-alive support"
|
||||
default n
|
||||
|
@ -175,15 +175,19 @@ struct tcp_conn_s
|
||||
uint8_t timer; /* The retransmission timer (units: half-seconds) */
|
||||
uint8_t nrtx; /* The number of retransmissions for the last
|
||||
* segment sent */
|
||||
#ifdef CONFIG_NET_TCP_DELAYED_ACK
|
||||
uint8_t rx_unackseg; /* Number of un-ACKed received segments */
|
||||
uint8_t rx_acktimer; /* Time since last ACK sent (units: half-seconds) */
|
||||
#endif
|
||||
uint16_t lport; /* The local TCP port, in network byte order */
|
||||
uint16_t rport; /* The remoteTCP port, in network byte order */
|
||||
uint16_t mss; /* Current maximum segment size for the
|
||||
* connection */
|
||||
uint16_t winsize; /* Current window size of the connection */
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
uint32_t unacked; /* Number bytes sent but not yet ACKed */
|
||||
uint32_t tx_unacked; /* Number bytes sent but not yet ACKed */
|
||||
#else
|
||||
uint16_t unacked; /* Number bytes sent but not yet ACKed */
|
||||
uint16_t tx_unacked; /* Number bytes sent but not yet ACKed */
|
||||
#endif
|
||||
|
||||
/* If the TCP socket is bound to a local address, then this is
|
||||
@ -941,7 +945,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile,
|
||||
void tcp_reset(FAR struct net_driver_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ack
|
||||
* Name: tcp_synack
|
||||
*
|
||||
* Description:
|
||||
* Send the SYN or SYNACK response.
|
||||
@ -959,8 +963,8 @@ void tcp_reset(FAR struct net_driver_s *dev);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
uint8_t ack);
|
||||
void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
uint8_t ack);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_appsend
|
||||
|
@ -85,10 +85,49 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
{
|
||||
uint8_t hdrlen;
|
||||
|
||||
/* Handle the result based on the application response */
|
||||
ninfo("result: %04x d_sndlen: %d conn->tx_unacked: %d\n",
|
||||
result, dev->d_sndlen, conn->tx_unacked);
|
||||
|
||||
ninfo("result: %04x d_sndlen: %d conn->unacked: %d\n",
|
||||
result, dev->d_sndlen, conn->unacked);
|
||||
#ifdef CONFIG_NET_TCP_DELAYED_ACK
|
||||
/* Did the caller request that an ACK be sent? */
|
||||
|
||||
if ((result & TCP_SNDACK) != 0)
|
||||
{
|
||||
/* Yes.. Handle delayed acknowledgments */
|
||||
|
||||
/* Reset the ACK timer in any event. */
|
||||
|
||||
conn->rx_acktimer = 0;
|
||||
|
||||
/* Per RFC 1122: "...there SHOULD be an ACK for at least every second
|
||||
* segment."
|
||||
*/
|
||||
|
||||
if (conn->rx_unackseg > 0)
|
||||
{
|
||||
/* Reset the delayed ACK state and send the ACK with this packet. */
|
||||
|
||||
conn->rx_unackseg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Indicate that there is one un-ACKed segment and don't send the
|
||||
* ACK on this pack.
|
||||
*/
|
||||
|
||||
result &= ~TCP_SNDACK;
|
||||
conn->rx_unackseg = 1;
|
||||
|
||||
/* A special case is if there are not other flags and no TCP TX
|
||||
* data payload. In this case, don't send anything.*/
|
||||
|
||||
if (result == 0 && dev->d_sndlen == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the IP header length associated with the IP domain configured for
|
||||
* this TCP connection.
|
||||
@ -143,7 +182,7 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
else if ((result & TCP_CLOSE) != 0)
|
||||
{
|
||||
conn->tcpstateflags = TCP_FIN_WAIT_1;
|
||||
conn->unacked = 1;
|
||||
conn->tx_unacked = 1;
|
||||
conn->nrtx = 0;
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
conn->sndseq_max = tcp_getsequence(conn->sndseq) + 1;
|
||||
@ -172,10 +211,10 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
* do not go through this path.
|
||||
*/
|
||||
|
||||
conn->unacked += dev->d_sndlen;
|
||||
conn->tx_unacked += dev->d_sndlen;
|
||||
|
||||
/* The application cannot send more than what is allowed by the
|
||||
* MSS (the minumum of the MSS and the available window).
|
||||
* MSS (the minimum of the MSS and the available window).
|
||||
*/
|
||||
|
||||
DEBUGASSERT(dev->d_sndlen <= conn->mss);
|
||||
@ -183,6 +222,7 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
|
||||
conn->nrtx = 0;
|
||||
#endif
|
||||
|
||||
/* Then handle the rest of the operation just as for the rexmit case */
|
||||
|
||||
tcp_rexmit(dev, conn, result);
|
||||
@ -213,8 +253,8 @@ void tcp_rexmit(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
{
|
||||
uint8_t hdrlen;
|
||||
|
||||
ninfo("result: %04x d_sndlen: %d conn->unacked: %d\n",
|
||||
result, dev->d_sndlen, conn->unacked);
|
||||
ninfo("result: %04x d_sndlen: %d conn->tx_unacked: %d\n",
|
||||
result, dev->d_sndlen, conn->tx_unacked);
|
||||
|
||||
/* Get the IP header length associated with the IP domain configured for
|
||||
* this TCP connection.
|
||||
@ -247,7 +287,7 @@ 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->unacked > 0)
|
||||
if (dev->d_sndlen > 0 && conn->tx_unacked > 0)
|
||||
#endif
|
||||
{
|
||||
/* We always set the ACK flag in response packets adding the length of
|
||||
|
@ -1008,7 +1008,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
||||
conn->tcpstateflags = TCP_SYN_RCVD;
|
||||
|
||||
tcp_initsequence(conn->sndseq);
|
||||
conn->unacked = 1;
|
||||
conn->tx_unacked = 1;
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
conn->expired = 0;
|
||||
conn->isn = 0;
|
||||
@ -1243,7 +1243,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
conn->tcpstateflags = TCP_SYN_SENT;
|
||||
tcp_initsequence(conn->sndseq);
|
||||
|
||||
conn->unacked = 1; /* TCP length of the SYN is one. */
|
||||
conn->tx_unacked = 1; /* TCP length of the SYN is one. */
|
||||
conn->nrtx = 0;
|
||||
conn->timer = 1; /* Send the SYN next time around. */
|
||||
conn->rto = TCP_RTO;
|
||||
|
@ -295,7 +295,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
|
||||
/* Our response will be a SYNACK. */
|
||||
|
||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -416,7 +416,7 @@ found:
|
||||
(tcp->flags & (TCP_SYN | TCP_FIN | TCP_RST)) == 0 &&
|
||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED &&
|
||||
(dev->d_len == 0 || dev->d_len == 1) &&
|
||||
conn->unacked <= 0)
|
||||
conn->tx_unacked <= 0)
|
||||
{
|
||||
uint32_t ackseq;
|
||||
uint32_t rcvseq;
|
||||
@ -471,20 +471,20 @@ found:
|
||||
* data, calculate RTT estimations, and reset the retransmission timer.
|
||||
*/
|
||||
|
||||
if ((tcp->flags & TCP_ACK) != 0 && conn->unacked > 0)
|
||||
if ((tcp->flags & TCP_ACK) != 0 && conn->tx_unacked > 0)
|
||||
{
|
||||
uint32_t unackseq;
|
||||
uint32_t ackseq;
|
||||
|
||||
/* The next sequence number is equal to the current sequence
|
||||
* number (sndseq) plus the size of the outstanding, unacknowledged
|
||||
* data (unacked).
|
||||
* data (tx_unacked).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
unackseq = conn->sndseq_max;
|
||||
#else
|
||||
unackseq = tcp_addsequence(conn->sndseq, conn->unacked);
|
||||
unackseq = tcp_addsequence(conn->sndseq, conn->tx_unacked);
|
||||
#endif
|
||||
|
||||
/* Get the sequence number of that has just been acknowledged by this
|
||||
@ -504,7 +504,7 @@ found:
|
||||
{
|
||||
/* Calculate the new number of outstanding, unacknowledged bytes */
|
||||
|
||||
conn->unacked = unackseq - ackseq;
|
||||
conn->tx_unacked = unackseq - ackseq;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -517,11 +517,11 @@ found:
|
||||
if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
|
||||
{
|
||||
nwarn("WARNING: ackseq > unackseq\n");
|
||||
nwarn(" sndseq=%u unacked=%u unackseq=%u ackseq=%u\n",
|
||||
tcp_getsequence(conn->sndseq), conn->unacked, unackseq,
|
||||
nwarn(" sndseq=%u tx_unacked=%u unackseq=%u ackseq=%u\n",
|
||||
tcp_getsequence(conn->sndseq), conn->tx_unacked, unackseq,
|
||||
ackseq);
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,8 +530,8 @@ found:
|
||||
* be beyond ackseq.
|
||||
*/
|
||||
|
||||
ninfo("sndseq: %08x->%08x unackseq: %08x new unacked: %d\n",
|
||||
tcp_getsequence(conn->sndseq), ackseq, unackseq, conn->unacked);
|
||||
ninfo("sndseq: %08x->%08x unackseq: %08x new tx_unacked: %d\n",
|
||||
tcp_getsequence(conn->sndseq), ackseq, unackseq, conn->tx_unacked);
|
||||
tcp_setsequence(conn->sndseq, ackseq);
|
||||
|
||||
/* Do RTT estimation, unless we have done retransmissions. */
|
||||
@ -619,7 +619,7 @@ found:
|
||||
conn->sent = 0;
|
||||
conn->sndseq_max = 0;
|
||||
#endif
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
flags = TCP_CONNECTED;
|
||||
ninfo("TCP state: TCP_ESTABLISHED\n");
|
||||
|
||||
@ -639,7 +639,7 @@ found:
|
||||
|
||||
if ((tcp->flags & TCP_CTL) == TCP_SYN)
|
||||
{
|
||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -714,7 +714,7 @@ found:
|
||||
memcpy(conn->rcvseq, tcp->seqno, 4);
|
||||
|
||||
net_incr32(conn->rcvseq, 1);
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
conn->isn = tcp_getsequence(tcp->ackno);
|
||||
@ -770,7 +770,7 @@ found:
|
||||
* if the connection is going to be closed.
|
||||
*/
|
||||
#if 0
|
||||
if (conn->unacked > 0)
|
||||
if (conn->tx_unacked > 0)
|
||||
{
|
||||
goto drop;
|
||||
}
|
||||
@ -791,7 +791,7 @@ found:
|
||||
(void)tcp_callback(dev, conn, flags);
|
||||
|
||||
conn->tcpstateflags = TCP_LAST_ACK;
|
||||
conn->unacked = 1;
|
||||
conn->tx_unacked = 1;
|
||||
conn->nrtx = 0;
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
conn->sndseq_max = tcp_getsequence(conn->sndseq) + 1;
|
||||
@ -943,7 +943,7 @@ found:
|
||||
|
||||
if ((tcp->flags & TCP_FIN) != 0)
|
||||
{
|
||||
if ((flags & TCP_ACKDATA) != 0 && conn->unacked == 0)
|
||||
if ((flags & TCP_ACKDATA) != 0 && conn->tx_unacked == 0)
|
||||
{
|
||||
conn->tcpstateflags = TCP_TIME_WAIT;
|
||||
conn->timer = 0;
|
||||
@ -960,7 +960,7 @@ found:
|
||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||
return;
|
||||
}
|
||||
else if ((flags & TCP_ACKDATA) != 0 && conn->unacked == 0)
|
||||
else if ((flags & TCP_ACKDATA) != 0 && conn->tx_unacked == 0)
|
||||
{
|
||||
conn->tcpstateflags = TCP_FIN_WAIT_2;
|
||||
ninfo("TCP state: TCP_FIN_WAIT_2\n");
|
||||
|
@ -547,10 +547,10 @@ void tcp_reset(FAR struct net_driver_s *dev)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ack
|
||||
* Name: tcp_synack
|
||||
*
|
||||
* Description:
|
||||
* Send the SYN or SYNACK response.
|
||||
* Send the SYN, ACK, or SYNACK response.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device driver structure to use in the send operation
|
||||
@ -565,8 +565,8 @@ void tcp_reset(FAR struct net_driver_s *dev)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
uint8_t ack)
|
||||
void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
uint8_t ack)
|
||||
{
|
||||
struct tcp_hdr_s *tcp;
|
||||
uint16_t tcp_mss;
|
||||
@ -609,7 +609,7 @@ void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
|
||||
tcp->flags = ack;
|
||||
|
||||
/* We send out the TCP Maximum Segment Size option with our ack. */
|
||||
/* We send out the TCP Maximum Segment Size option with our ACK. */
|
||||
|
||||
tcp->optdata[0] = TCP_OPT_MSS;
|
||||
tcp->optdata[1] = TCP_OPT_MSS_LEN;
|
||||
|
@ -531,13 +531,13 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
/* Yes.. Reset the number of bytes sent sent from the write buffer */
|
||||
|
||||
sent = TCP_WBSENT(wrb);
|
||||
if (conn->unacked > sent)
|
||||
if (conn->tx_unacked > sent)
|
||||
{
|
||||
conn->unacked -= sent;
|
||||
conn->tx_unacked -= sent;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
}
|
||||
|
||||
if (conn->sent > sent)
|
||||
@ -550,8 +550,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
}
|
||||
|
||||
TCP_WBSENT(wrb) = 0;
|
||||
ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n",
|
||||
wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent);
|
||||
ninfo("REXMIT: wrb=%p sent=%u, conn tx_unacked=%d sent=%d\n",
|
||||
wrb, TCP_WBSENT(wrb), conn->tx_unacked, conn->sent);
|
||||
|
||||
/* Increment the retransmit count on this write buffer. */
|
||||
|
||||
@ -603,13 +603,13 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
/* Reset the number of bytes sent sent from the write buffer */
|
||||
|
||||
sent = TCP_WBSENT(wrb);
|
||||
if (conn->unacked > sent)
|
||||
if (conn->tx_unacked > sent)
|
||||
{
|
||||
conn->unacked -= sent;
|
||||
conn->tx_unacked -= sent;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
}
|
||||
|
||||
if (conn->sent > sent)
|
||||
@ -622,8 +622,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
}
|
||||
|
||||
TCP_WBSENT(wrb) = 0;
|
||||
ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n",
|
||||
wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent);
|
||||
ninfo("REXMIT: wrb=%p sent=%u, conn tx_unacked=%d sent=%d\n",
|
||||
wrb, TCP_WBSENT(wrb), conn->tx_unacked, conn->sent);
|
||||
|
||||
/* Free any write buffers that have exceed the retry count */
|
||||
|
||||
@ -767,8 +767,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
* number calculations.
|
||||
*/
|
||||
|
||||
conn->unacked += sndlen;
|
||||
conn->sent += sndlen;
|
||||
conn->tx_unacked += sndlen;
|
||||
conn->sent += sndlen;
|
||||
|
||||
/* Below prediction will become true, unless retransmission occurrence */
|
||||
|
||||
@ -780,8 +780,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
||||
conn->sndseq_max = predicted_seqno;
|
||||
}
|
||||
|
||||
ninfo("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n",
|
||||
wrb, TCP_WBNRTX(wrb), conn->unacked, conn->sent);
|
||||
ninfo("SEND: wrb=%p nrtx=%u tx_unacked=%u sent=%u\n",
|
||||
wrb, TCP_WBNRTX(wrb), conn->tx_unacked, conn->sent);
|
||||
|
||||
/* Increment the count of bytes sent from this write buffer */
|
||||
|
||||
|
@ -530,7 +530,7 @@ end_wait:
|
||||
|
||||
/* There are no outstanding, unacknowledged bytes */
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
@ -747,7 +747,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
|
||||
* initial sequence number.
|
||||
*/
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
/* Set the initial time for calculating timeouts */
|
||||
|
||||
|
@ -614,7 +614,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile,
|
||||
* initial sequence number.
|
||||
*/
|
||||
|
||||
conn->unacked = 0;
|
||||
conn->tx_unacked = 0;
|
||||
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
/* Set the initial time for calculating timeouts */
|
||||
|
@ -60,6 +60,20 @@
|
||||
#include "socket/socket.h"
|
||||
#include "tcp/tcp.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Per RFC 1122: "... an ACK should not be excessively delayed; in
|
||||
* particular, the delay MUST be less than 0.5 seconds ..."
|
||||
*
|
||||
* NOTE: We only have 0.5 timing resolution here so the delay will be
|
||||
* between 0.5 and 1.0 seconds, and may be delayed further, depending on the
|
||||
* polling rate of the the driver (often 1 second).
|
||||
*/
|
||||
|
||||
#define ACK_DELAY (1)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -187,7 +201,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
* retransmit.
|
||||
*/
|
||||
|
||||
if (conn->unacked > 0)
|
||||
if (conn->tx_unacked > 0)
|
||||
{
|
||||
/* The connection has outstanding data */
|
||||
|
||||
@ -315,14 +329,14 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
* SYNACK.
|
||||
*/
|
||||
|
||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||
goto done;
|
||||
|
||||
case TCP_SYN_SENT:
|
||||
|
||||
/* In the SYN_SENT state, we retransmit out SYN. */
|
||||
|
||||
tcp_ack(dev, conn, TCP_SYN);
|
||||
tcp_synack(dev, conn, TCP_SYN);
|
||||
goto done;
|
||||
|
||||
case TCP_ESTABLISHED:
|
||||
@ -454,7 +468,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
* dummy byte that we just sent.
|
||||
*/
|
||||
|
||||
conn->unacked++;
|
||||
conn->tx_unacked++;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Increment the un-ACKed sequence number */
|
||||
@ -472,9 +486,40 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_TCP_DELAYED_ACK
|
||||
/* Handle delayed acknowledgments. Is there a segment with a
|
||||
* delayed acknowledgment?
|
||||
*/
|
||||
|
||||
if (conn->rx_unackseg > 0)
|
||||
{
|
||||
/* Increment the ACK delay. */
|
||||
|
||||
conn->rx_acktimer += hsec;
|
||||
|
||||
/* Per RFC 1122: "...an ACK should not be excessively
|
||||
* delayed; in particular, the delay must be less than
|
||||
* 0.5 seconds..."
|
||||
*/
|
||||
|
||||
if (conn->rx_acktimer >= ACK_DELAY)
|
||||
{
|
||||
/* Reset the delayed ACK state and send the ACK
|
||||
* packet.
|
||||
*/
|
||||
|
||||
conn->rx_unackseg = 0;
|
||||
conn->rx_acktimer = 0;
|
||||
tcp_synack(dev, conn, TCP_ACK);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* There was no need for a retransmission and there was no
|
||||
* need to probe the remote peer. We poll the application for
|
||||
* new outgoing data.
|
||||
* need to probe the remote peer and there was no need to
|
||||
* send a delayed ACK. We poll the application for new
|
||||
* outgoing data.
|
||||
*/
|
||||
|
||||
result = tcp_callback(dev, conn, TCP_POLL);
|
||||
|
Loading…
Reference in New Issue
Block a user