summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-11-27 18:01:54 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-11-27 18:01:54 +0000
commit28932ba103428768ef0fbcecfb9e507685acb3b0 (patch)
tree48b9b39114448ee2fd57b9e7531504a02faaff7c
parenta8182f15c4fff323262be45ac4299ca2e6653c73 (diff)
downloadpx4-nuttx-28932ba103428768ef0fbcecfb9e507685acb3b0.tar.gz
px4-nuttx-28932ba103428768ef0fbcecfb9e507685acb3b0.tar.bz2
px4-nuttx-28932ba103428768ef0fbcecfb9e507685acb3b0.zip
Fix TCP sequence number error
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3136 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/net/send.c13
-rw-r--r--nuttx/net/uip/uip_tcpinput.c117
2 files changed, 81 insertions, 49 deletions
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 553722353..768d9ce9d 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -233,6 +233,8 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
if ((flags & UIP_NEWDATA) == 0 && pstate->snd_sent < pstate->snd_buflen)
{
+ uint32_t seqno;
+
/* Get the amount of data that we can send in the next packet */
uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;
@@ -241,9 +243,16 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
sndlen = uip_mss(conn);
}
- /* Set the sequence number for this packet */
+ /* Set the sequence number for this packet. NOTE: uIP updates
+ * sndseq on recept of ACK *before* this function is called. In that
+ * case sndseq will point to the next unacknowledge byte (which might
+ * have already been sent). We will overwrite the value of sndseq
+ * here before the packet is sent.
+ */
- uip_tcpsetsequence(conn->sndseq, pstate->snd_sent + pstate->snd_isn);
+ seqno = pstate->snd_sent + pstate->snd_isn;
+ nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno);
+ uip_tcpsetsequence(conn->sndseq, seqno);
/* Then send that amount of data */
diff --git a/nuttx/net/uip/uip_tcpinput.c b/nuttx/net/uip/uip_tcpinput.c
index 32b3b8195..e95ded119 100644
--- a/nuttx/net/uip/uip_tcpinput.c
+++ b/nuttx/net/uip/uip_tcpinput.c
@@ -261,7 +261,7 @@ void uip_tcpinput(struct uip_driver_s *dev)
/* We do not send resets in response to resets. */
- if (pbuf->flags & TCP_RST)
+ if ((pbuf->flags & TCP_RST) != 0)
{
goto drop;
}
@@ -282,7 +282,7 @@ found:
* before we accept the reset.
*/
- if (pbuf->flags & TCP_RST)
+ if ((pbuf->flags & TCP_RST) != 0)
{
conn->tcpstateflags = UIP_CLOSED;
nlldbg("RESET - TCP state: UIP_CLOSED\n");
@@ -328,62 +328,84 @@ found:
if ((pbuf->flags & TCP_ACK) != 0 && conn->unacked > 0)
{
- uint32_t seqno;
- uint32_t ackno;
+ uint32_t unackseq;
+ uint32_t ackseq;
/* The next sequence number is equal to the current sequence
- * number (sndseq) plus the size of the oustanding data (len).
+ * number (sndseq) plus the size of the oustanding, unacknowledged
+ * data (unacked).
*/
- seqno = uip_tcpaddsequence(conn->sndseq, conn->unacked);
+ unackseq = uip_tcpaddsequence(conn->sndseq, conn->unacked);
- /* Check if all of the outstanding bytes have been acknowledged. For
- * a "generic" send operation, this should always be true. However,
+ /* Get the sequence number of that has just been acknowledged by this
+ * incoming packet.
+ */
+
+ ackseq = uip_tcpgetsequence(pbuf->ackno);
+
+ /* Check how many of the outstanding bytes have been acknowledged. For
+ * a most uIP send operation, this should always be true. However,
* the send() API sends data ahead when it can without waiting for
- * the ACK. In this case, the 'ackno' could be less than then the
+ * the ACK. In this case, the 'ackseq' could be less than then the
* new sequence number.
*/
- ackno = uip_tcpgetsequence(pbuf->ackno);
- if (ackno <= seqno)
+ if (ackseq <= unackseq)
{
- /* Update sequence number. */
+ /* Calculate the new number of oustanding, unacknowledged bytes */
- uip_tcpsetsequence(conn->sndseq, seqno);
+ conn->unacked = unackseq - ackseq;
+ }
+ else
+ {
+ /* What would it mean if ackseq > unackseq? The peer has ACKed
+ * more bytes than we think we have sent? Someone has lost it.
+ * Complain and reset the number of outstanding, unackowledged
+ * bytes
+ */
- /* Do RTT estimation, unless we have done retransmissions. */
+ nlldbg("ERROR: ackseq[%08x] > unackseq[%08x]\n", ackseq, unackseq);
+ conn->unacked = 0;
+ }
- if (conn->nrtx == 0)
- {
- signed char m;
- m = conn->rto - conn->timer;
+ /* Update sequence number to the unacknowledge sequence number. If
+ * there is still outstanding, unacknowledged data, then this will
+ * be beyond ackseq.
+ */
- /* This is taken directly from VJs original code in his paper */
+ nllvdbg("sndseq: %08x->%08x unackseq: %08x new unacked: %d\n",
+ conn->sndseq, ackseq, unackseq, conn->unacked);
+ uip_tcpsetsequence(conn->sndseq, ackseq);
- m = m - (conn->sa >> 3);
- conn->sa += m;
- if (m < 0)
- {
- m = -m;
- }
+ /* Do RTT estimation, unless we have done retransmissions. */
- m = m - (conn->sv >> 2);
- conn->sv += m;
- conn->rto = (conn->sa >> 3) + conn->sv;
- }
+ if (conn->nrtx == 0)
+ {
+ signed char m;
+ m = conn->rto - conn->timer;
- /* Set the acknowledged flag. */
+ /* This is taken directly from VJs original code in his paper */
+
+ m = m - (conn->sa >> 3);
+ conn->sa += m;
+ if (m < 0)
+ {
+ m = -m;
+ }
- flags = UIP_ACKDATA;
+ m = m - (conn->sv >> 2);
+ conn->sv += m;
+ conn->rto = (conn->sa >> 3) + conn->sv;
+ }
- /* Reset the retransmission timer. */
+ /* Set the acknowledged flag. */
- conn->timer = conn->rto;
+ flags |= UIP_ACKDATA;
- /* Reset length of outstanding data. */
+ /* Reset the retransmission timer. */
- conn->unacked = 0;
- }
+ conn->timer = conn->rto;
}
/* Do different things depending on in what state the connection is. */
@@ -403,7 +425,7 @@ found:
* flag set. If so, we enter the ESTABLISHED state.
*/
- if (flags & UIP_ACKDATA)
+ if ((flags & UIP_ACKDATA) != 0)
{
conn->tcpstateflags = UIP_ESTABLISHED;
conn->unacked = 0;
@@ -431,7 +453,7 @@ found:
* state.
*/
- if ((flags & UIP_ACKDATA) && (pbuf->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))
+ if ((flags & UIP_ACKDATA) != 0 && (pbuf->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))
{
/* Parse the TCP MSS option, if present. */
@@ -511,7 +533,7 @@ found:
/* We do not send resets in response to resets. */
- if (pbuf->flags & TCP_RST)
+ if ((pbuf->flags & TCP_RST) != 0)
{
goto drop;
}
@@ -531,7 +553,7 @@ found:
* sequence numbers will be screwed up.
*/
- if (pbuf->flags & TCP_FIN && !(conn->tcpstateflags & UIP_STOPPED))
+ if ((pbuf->flags & TCP_FIN) != 0 && (conn->tcpstateflags & UIP_STOPPED) == 0)
{
if (conn->unacked > 0)
{
@@ -639,7 +661,7 @@ found:
* send, d_len must be set to 0.
*/
- if (flags & (UIP_NEWDATA | UIP_ACKDATA))
+ if ((flags & (UIP_NEWDATA | UIP_ACKDATA)) != 0)
{
dev->d_sndlen = 0;
result = uip_tcpcallback(dev, conn, flags);
@@ -653,7 +675,7 @@ found:
* FIN. This is indicated by the UIP_ACKDATA flag.
*/
- if (flags & UIP_ACKDATA)
+ if ((flags & UIP_ACKDATA) != 0)
{
conn->tcpstateflags = UIP_CLOSED;
nllvdbg("UIP_LAST_ACK TCP state: UIP_CLOSED\n");
@@ -672,9 +694,10 @@ found:
{
uip_incr32(conn->rcvseq, dev->d_len);
}
- if (pbuf->flags & TCP_FIN)
+
+ if ((pbuf->flags & TCP_FIN) != 0)
{
- if (flags & UIP_ACKDATA)
+ if ((flags & UIP_ACKDATA) != 0)
{
conn->tcpstateflags = UIP_TIME_WAIT;
conn->timer = 0;
@@ -692,7 +715,7 @@ found:
uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);
return;
}
- else if (flags & UIP_ACKDATA)
+ else if ((flags & UIP_ACKDATA) != 0)
{
conn->tcpstateflags = UIP_FIN_WAIT_2;
conn->unacked = 0;
@@ -713,7 +736,7 @@ found:
uip_incr32(conn->rcvseq, dev->d_len);
}
- if (pbuf->flags & TCP_FIN)
+ if ((pbuf->flags & TCP_FIN) != 0)
{
conn->tcpstateflags = UIP_TIME_WAIT;
conn->timer = 0;
@@ -737,7 +760,7 @@ found:
return;
case UIP_CLOSING:
- if (flags & UIP_ACKDATA)
+ if ((flags & UIP_ACKDATA) != 0)
{
conn->tcpstateflags = UIP_TIME_WAIT;
conn->timer = 0;