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
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
/* Check if all outstanding bytes have been ACKed */
|
/* 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
|
/* No... we are still waiting for ACKs. Drop any received data, but
|
||||||
* do not yet report TCP_CLOSE in the response.
|
* do not yet report TCP_CLOSE in the response.
|
||||||
|
@ -557,7 +557,7 @@ static uint16_t tcp_send_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
/* Increment the count of bytes sent, the number of unacked bytes,
|
/* Increment the count of bytes sent, the number of unacked bytes,
|
||||||
* and the total count of TCP packets sent.
|
* 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
|
* 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
|
* zero for 6LoWPAN since it does not send via the dev->d_buf
|
||||||
* but, rather, uses a backdoor frame interface with the IEEE
|
* but, rather, uses a backdoor frame interface with the IEEE
|
||||||
@ -565,21 +565,21 @@ static uint16_t tcp_send_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sinfo->s_sent += sndlen;
|
sinfo->s_sent += sndlen;
|
||||||
conn->unacked += sndlen;
|
conn->tx_unacked += sndlen;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
/* For compability with buffered send logic */
|
/* 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
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
g_netstats.tcp.sent++;
|
g_netstats.tcp.sent++;
|
||||||
#endif
|
#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,
|
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 */
|
/* There are no outstanding, unacknowledged bytes */
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
/* Wake up the waiting thread */
|
/* Wake up the waiting thread */
|
||||||
|
|
||||||
@ -710,7 +710,7 @@ static int sixlowpan_send_packet(FAR struct socket *psock,
|
|||||||
* initial sequence number.
|
* initial sequence number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
/* Notify the IEEE802.15.4 MAC that we have data to send. */
|
/* 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
|
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
|
config NET_TCP_KEEPALIVE
|
||||||
bool "TCP/IP Keep-alive support"
|
bool "TCP/IP Keep-alive support"
|
||||||
default n
|
default n
|
||||||
|
@ -175,15 +175,19 @@ struct tcp_conn_s
|
|||||||
uint8_t timer; /* The retransmission timer (units: half-seconds) */
|
uint8_t timer; /* The retransmission timer (units: half-seconds) */
|
||||||
uint8_t nrtx; /* The number of retransmissions for the last
|
uint8_t nrtx; /* The number of retransmissions for the last
|
||||||
* segment sent */
|
* 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 lport; /* The local TCP port, in network byte order */
|
||||||
uint16_t rport; /* The remoteTCP port, in network byte order */
|
uint16_t rport; /* The remoteTCP port, in network byte order */
|
||||||
uint16_t mss; /* Current maximum segment size for the
|
uint16_t mss; /* Current maximum segment size for the
|
||||||
* connection */
|
* connection */
|
||||||
uint16_t winsize; /* Current window size of the connection */
|
uint16_t winsize; /* Current window size of the connection */
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#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
|
#else
|
||||||
uint16_t unacked; /* Number bytes sent but not yet ACKed */
|
uint16_t tx_unacked; /* Number bytes sent but not yet ACKed */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the TCP socket is bound to a local address, then this is
|
/* 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);
|
void tcp_reset(FAR struct net_driver_s *dev);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: tcp_ack
|
* Name: tcp_synack
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Send the SYN or SYNACK response.
|
* Send the SYN or SYNACK response.
|
||||||
@ -959,7 +963,7 @@ void tcp_reset(FAR struct net_driver_s *dev);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||||
uint8_t ack);
|
uint8_t ack);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -85,10 +85,49 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
|||||||
{
|
{
|
||||||
uint8_t hdrlen;
|
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",
|
#ifdef CONFIG_NET_TCP_DELAYED_ACK
|
||||||
result, dev->d_sndlen, conn->unacked);
|
/* 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
|
/* Get the IP header length associated with the IP domain configured for
|
||||||
* this TCP connection.
|
* 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)
|
else if ((result & TCP_CLOSE) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = TCP_FIN_WAIT_1;
|
conn->tcpstateflags = TCP_FIN_WAIT_1;
|
||||||
conn->unacked = 1;
|
conn->tx_unacked = 1;
|
||||||
conn->nrtx = 0;
|
conn->nrtx = 0;
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
conn->sndseq_max = tcp_getsequence(conn->sndseq) + 1;
|
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.
|
* 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
|
/* 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);
|
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;
|
conn->nrtx = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Then handle the rest of the operation just as for the rexmit case */
|
/* Then handle the rest of the operation just as for the rexmit case */
|
||||||
|
|
||||||
tcp_rexmit(dev, conn, result);
|
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;
|
uint8_t hdrlen;
|
||||||
|
|
||||||
ninfo("result: %04x d_sndlen: %d conn->unacked: %d\n",
|
ninfo("result: %04x d_sndlen: %d conn->tx_unacked: %d\n",
|
||||||
result, dev->d_sndlen, conn->unacked);
|
result, dev->d_sndlen, conn->tx_unacked);
|
||||||
|
|
||||||
/* Get the IP header length associated with the IP domain configured for
|
/* Get the IP header length associated with the IP domain configured for
|
||||||
* this TCP connection.
|
* 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
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
if (dev->d_sndlen > 0)
|
if (dev->d_sndlen > 0)
|
||||||
#else
|
#else
|
||||||
if (dev->d_sndlen > 0 && conn->unacked > 0)
|
if (dev->d_sndlen > 0 && conn->tx_unacked > 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* We always set the ACK flag in response packets adding the length of
|
/* 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;
|
conn->tcpstateflags = TCP_SYN_RCVD;
|
||||||
|
|
||||||
tcp_initsequence(conn->sndseq);
|
tcp_initsequence(conn->sndseq);
|
||||||
conn->unacked = 1;
|
conn->tx_unacked = 1;
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
conn->expired = 0;
|
conn->expired = 0;
|
||||||
conn->isn = 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;
|
conn->tcpstateflags = TCP_SYN_SENT;
|
||||||
tcp_initsequence(conn->sndseq);
|
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->nrtx = 0;
|
||||||
conn->timer = 1; /* Send the SYN next time around. */
|
conn->timer = 1; /* Send the SYN next time around. */
|
||||||
conn->rto = TCP_RTO;
|
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. */
|
/* Our response will be a SYNACK. */
|
||||||
|
|
||||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,7 +416,7 @@ found:
|
|||||||
(tcp->flags & (TCP_SYN | TCP_FIN | TCP_RST)) == 0 &&
|
(tcp->flags & (TCP_SYN | TCP_FIN | TCP_RST)) == 0 &&
|
||||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED &&
|
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED &&
|
||||||
(dev->d_len == 0 || dev->d_len == 1) &&
|
(dev->d_len == 0 || dev->d_len == 1) &&
|
||||||
conn->unacked <= 0)
|
conn->tx_unacked <= 0)
|
||||||
{
|
{
|
||||||
uint32_t ackseq;
|
uint32_t ackseq;
|
||||||
uint32_t rcvseq;
|
uint32_t rcvseq;
|
||||||
@ -471,20 +471,20 @@ found:
|
|||||||
* data, calculate RTT estimations, and reset the retransmission timer.
|
* 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 unackseq;
|
||||||
uint32_t ackseq;
|
uint32_t ackseq;
|
||||||
|
|
||||||
/* The next sequence number is equal to the current sequence
|
/* The next sequence number is equal to the current sequence
|
||||||
* number (sndseq) plus the size of the outstanding, unacknowledged
|
* number (sndseq) plus the size of the outstanding, unacknowledged
|
||||||
* data (unacked).
|
* data (tx_unacked).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
unackseq = conn->sndseq_max;
|
unackseq = conn->sndseq_max;
|
||||||
#else
|
#else
|
||||||
unackseq = tcp_addsequence(conn->sndseq, conn->unacked);
|
unackseq = tcp_addsequence(conn->sndseq, conn->tx_unacked);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the sequence number of that has just been acknowledged by this
|
/* 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 */
|
/* Calculate the new number of outstanding, unacknowledged bytes */
|
||||||
|
|
||||||
conn->unacked = unackseq - ackseq;
|
conn->tx_unacked = unackseq - ackseq;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -517,11 +517,11 @@ found:
|
|||||||
if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
|
if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
|
||||||
{
|
{
|
||||||
nwarn("WARNING: ackseq > unackseq\n");
|
nwarn("WARNING: ackseq > unackseq\n");
|
||||||
nwarn(" sndseq=%u unacked=%u unackseq=%u ackseq=%u\n",
|
nwarn(" sndseq=%u tx_unacked=%u unackseq=%u ackseq=%u\n",
|
||||||
tcp_getsequence(conn->sndseq), conn->unacked, unackseq,
|
tcp_getsequence(conn->sndseq), conn->tx_unacked, unackseq,
|
||||||
ackseq);
|
ackseq);
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,8 +530,8 @@ found:
|
|||||||
* be beyond ackseq.
|
* be beyond ackseq.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ninfo("sndseq: %08x->%08x unackseq: %08x new unacked: %d\n",
|
ninfo("sndseq: %08x->%08x unackseq: %08x new tx_unacked: %d\n",
|
||||||
tcp_getsequence(conn->sndseq), ackseq, unackseq, conn->unacked);
|
tcp_getsequence(conn->sndseq), ackseq, unackseq, conn->tx_unacked);
|
||||||
tcp_setsequence(conn->sndseq, ackseq);
|
tcp_setsequence(conn->sndseq, ackseq);
|
||||||
|
|
||||||
/* Do RTT estimation, unless we have done retransmissions. */
|
/* Do RTT estimation, unless we have done retransmissions. */
|
||||||
@ -619,7 +619,7 @@ found:
|
|||||||
conn->sent = 0;
|
conn->sent = 0;
|
||||||
conn->sndseq_max = 0;
|
conn->sndseq_max = 0;
|
||||||
#endif
|
#endif
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
flags = TCP_CONNECTED;
|
flags = TCP_CONNECTED;
|
||||||
ninfo("TCP state: TCP_ESTABLISHED\n");
|
ninfo("TCP state: TCP_ESTABLISHED\n");
|
||||||
|
|
||||||
@ -639,7 +639,7 @@ found:
|
|||||||
|
|
||||||
if ((tcp->flags & TCP_CTL) == TCP_SYN)
|
if ((tcp->flags & TCP_CTL) == TCP_SYN)
|
||||||
{
|
{
|
||||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +714,7 @@ found:
|
|||||||
memcpy(conn->rcvseq, tcp->seqno, 4);
|
memcpy(conn->rcvseq, tcp->seqno, 4);
|
||||||
|
|
||||||
net_incr32(conn->rcvseq, 1);
|
net_incr32(conn->rcvseq, 1);
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
conn->isn = tcp_getsequence(tcp->ackno);
|
conn->isn = tcp_getsequence(tcp->ackno);
|
||||||
@ -770,7 +770,7 @@ found:
|
|||||||
* if the connection is going to be closed.
|
* if the connection is going to be closed.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
if (conn->unacked > 0)
|
if (conn->tx_unacked > 0)
|
||||||
{
|
{
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
@ -791,7 +791,7 @@ found:
|
|||||||
(void)tcp_callback(dev, conn, flags);
|
(void)tcp_callback(dev, conn, flags);
|
||||||
|
|
||||||
conn->tcpstateflags = TCP_LAST_ACK;
|
conn->tcpstateflags = TCP_LAST_ACK;
|
||||||
conn->unacked = 1;
|
conn->tx_unacked = 1;
|
||||||
conn->nrtx = 0;
|
conn->nrtx = 0;
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
conn->sndseq_max = tcp_getsequence(conn->sndseq) + 1;
|
conn->sndseq_max = tcp_getsequence(conn->sndseq) + 1;
|
||||||
@ -943,7 +943,7 @@ found:
|
|||||||
|
|
||||||
if ((tcp->flags & TCP_FIN) != 0)
|
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->tcpstateflags = TCP_TIME_WAIT;
|
||||||
conn->timer = 0;
|
conn->timer = 0;
|
||||||
@ -960,7 +960,7 @@ found:
|
|||||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||||
return;
|
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;
|
conn->tcpstateflags = TCP_FIN_WAIT_2;
|
||||||
ninfo("TCP state: TCP_FIN_WAIT_2\n");
|
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:
|
* Description:
|
||||||
* Send the SYN or SYNACK response.
|
* Send the SYN, ACK, or SYNACK response.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* dev - The device driver structure to use in the send operation
|
* dev - The device driver structure to use in the send operation
|
||||||
@ -565,7 +565,7 @@ void tcp_reset(FAR struct net_driver_s *dev)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||||
uint8_t ack)
|
uint8_t ack)
|
||||||
{
|
{
|
||||||
struct tcp_hdr_s *tcp;
|
struct tcp_hdr_s *tcp;
|
||||||
@ -609,7 +609,7 @@ void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
|||||||
|
|
||||||
tcp->flags = ack;
|
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[0] = TCP_OPT_MSS;
|
||||||
tcp->optdata[1] = TCP_OPT_MSS_LEN;
|
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 */
|
/* Yes.. Reset the number of bytes sent sent from the write buffer */
|
||||||
|
|
||||||
sent = TCP_WBSENT(wrb);
|
sent = TCP_WBSENT(wrb);
|
||||||
if (conn->unacked > sent)
|
if (conn->tx_unacked > sent)
|
||||||
{
|
{
|
||||||
conn->unacked -= sent;
|
conn->tx_unacked -= sent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->sent > sent)
|
if (conn->sent > sent)
|
||||||
@ -550,8 +550,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TCP_WBSENT(wrb) = 0;
|
TCP_WBSENT(wrb) = 0;
|
||||||
ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n",
|
ninfo("REXMIT: wrb=%p sent=%u, conn tx_unacked=%d sent=%d\n",
|
||||||
wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent);
|
wrb, TCP_WBSENT(wrb), conn->tx_unacked, conn->sent);
|
||||||
|
|
||||||
/* Increment the retransmit count on this write buffer. */
|
/* 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 */
|
/* Reset the number of bytes sent sent from the write buffer */
|
||||||
|
|
||||||
sent = TCP_WBSENT(wrb);
|
sent = TCP_WBSENT(wrb);
|
||||||
if (conn->unacked > sent)
|
if (conn->tx_unacked > sent)
|
||||||
{
|
{
|
||||||
conn->unacked -= sent;
|
conn->tx_unacked -= sent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->sent > sent)
|
if (conn->sent > sent)
|
||||||
@ -622,8 +622,8 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TCP_WBSENT(wrb) = 0;
|
TCP_WBSENT(wrb) = 0;
|
||||||
ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n",
|
ninfo("REXMIT: wrb=%p sent=%u, conn tx_unacked=%d sent=%d\n",
|
||||||
wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent);
|
wrb, TCP_WBSENT(wrb), conn->tx_unacked, conn->sent);
|
||||||
|
|
||||||
/* Free any write buffers that have exceed the retry count */
|
/* Free any write buffers that have exceed the retry count */
|
||||||
|
|
||||||
@ -767,7 +767,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
* number calculations.
|
* number calculations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->unacked += sndlen;
|
conn->tx_unacked += sndlen;
|
||||||
conn->sent += sndlen;
|
conn->sent += sndlen;
|
||||||
|
|
||||||
/* Below prediction will become true, unless retransmission occurrence */
|
/* 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;
|
conn->sndseq_max = predicted_seqno;
|
||||||
}
|
}
|
||||||
|
|
||||||
ninfo("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n",
|
ninfo("SEND: wrb=%p nrtx=%u tx_unacked=%u sent=%u\n",
|
||||||
wrb, TCP_WBNRTX(wrb), conn->unacked, conn->sent);
|
wrb, TCP_WBNRTX(wrb), conn->tx_unacked, conn->sent);
|
||||||
|
|
||||||
/* Increment the count of bytes sent from this write buffer */
|
/* Increment the count of bytes sent from this write buffer */
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ end_wait:
|
|||||||
|
|
||||||
/* There are no outstanding, unacknowledged bytes */
|
/* There are no outstanding, unacknowledged bytes */
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
/* Wake up the waiting thread */
|
/* Wake up the waiting thread */
|
||||||
|
|
||||||
@ -747,7 +747,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
|
|||||||
* initial sequence number.
|
* initial sequence number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
/* Set the initial time for calculating timeouts */
|
/* 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.
|
* initial sequence number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->unacked = 0;
|
conn->tx_unacked = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_SOCKOPTS
|
#ifdef CONFIG_NET_SOCKOPTS
|
||||||
/* Set the initial time for calculating timeouts */
|
/* Set the initial time for calculating timeouts */
|
||||||
|
@ -60,6 +60,20 @@
|
|||||||
#include "socket/socket.h"
|
#include "socket/socket.h"
|
||||||
#include "tcp/tcp.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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -187,7 +201,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
|||||||
* retransmit.
|
* retransmit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (conn->unacked > 0)
|
if (conn->tx_unacked > 0)
|
||||||
{
|
{
|
||||||
/* The connection has outstanding data */
|
/* 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.
|
* SYNACK.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcp_ack(dev, conn, TCP_ACK | TCP_SYN);
|
tcp_synack(dev, conn, TCP_ACK | TCP_SYN);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
case TCP_SYN_SENT:
|
case TCP_SYN_SENT:
|
||||||
|
|
||||||
/* In the SYN_SENT state, we retransmit out SYN. */
|
/* In the SYN_SENT state, we retransmit out SYN. */
|
||||||
|
|
||||||
tcp_ack(dev, conn, TCP_SYN);
|
tcp_synack(dev, conn, TCP_SYN);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
case TCP_ESTABLISHED:
|
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.
|
* dummy byte that we just sent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->unacked++;
|
conn->tx_unacked++;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
/* Increment the un-ACKed sequence number */
|
/* 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
|
#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
|
/* There was no need for a retransmission and there was no
|
||||||
* need to probe the remote peer. We poll the application for
|
* need to probe the remote peer and there was no need to
|
||||||
* new outgoing data.
|
* send a delayed ACK. We poll the application for new
|
||||||
|
* outgoing data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = tcp_callback(dev, conn, TCP_POLL);
|
result = tcp_callback(dev, conn, TCP_POLL);
|
||||||
|
Loading…
Reference in New Issue
Block a user