mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Fix TCP sequence number error
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3136 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
+11
-2
@@ -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)
|
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 */
|
/* Get the amount of data that we can send in the next packet */
|
||||||
|
|
||||||
uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;
|
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);
|
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 */
|
/* Then send that amount of data */
|
||||||
|
|
||||||
|
|||||||
+78
-55
@@ -261,7 +261,7 @@ void uip_tcpinput(struct uip_driver_s *dev)
|
|||||||
|
|
||||||
/* We do not send resets in response to resets. */
|
/* We do not send resets in response to resets. */
|
||||||
|
|
||||||
if (pbuf->flags & TCP_RST)
|
if ((pbuf->flags & TCP_RST) != 0)
|
||||||
{
|
{
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ found:
|
|||||||
* before we accept the reset.
|
* before we accept the reset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pbuf->flags & TCP_RST)
|
if ((pbuf->flags & TCP_RST) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_CLOSED;
|
conn->tcpstateflags = UIP_CLOSED;
|
||||||
nlldbg("RESET - TCP state: UIP_CLOSED\n");
|
nlldbg("RESET - TCP state: UIP_CLOSED\n");
|
||||||
@@ -328,62 +328,84 @@ found:
|
|||||||
|
|
||||||
if ((pbuf->flags & TCP_ACK) != 0 && conn->unacked > 0)
|
if ((pbuf->flags & TCP_ACK) != 0 && conn->unacked > 0)
|
||||||
{
|
{
|
||||||
uint32_t seqno;
|
uint32_t unackseq;
|
||||||
uint32_t ackno;
|
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 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
|
/* Get the sequence number of that has just been acknowledged by this
|
||||||
* a "generic" send operation, this should always be true. However,
|
* 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 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.
|
* new sequence number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ackno = uip_tcpgetsequence(pbuf->ackno);
|
if (ackseq <= unackseq)
|
||||||
if (ackno <= seqno)
|
|
||||||
{
|
{
|
||||||
/* Update sequence number. */
|
/* Calculate the new number of oustanding, unacknowledged bytes */
|
||||||
|
|
||||||
uip_tcpsetsequence(conn->sndseq, seqno);
|
conn->unacked = unackseq - ackseq;
|
||||||
|
}
|
||||||
/* Do RTT estimation, unless we have done retransmissions. */
|
else
|
||||||
|
{
|
||||||
if (conn->nrtx == 0)
|
/* What would it mean if ackseq > unackseq? The peer has ACKed
|
||||||
{
|
* more bytes than we think we have sent? Someone has lost it.
|
||||||
signed char m;
|
* Complain and reset the number of outstanding, unackowledged
|
||||||
m = conn->rto - conn->timer;
|
* bytes
|
||||||
|
*/
|
||||||
/* This is taken directly from VJs original code in his paper */
|
|
||||||
|
|
||||||
m = m - (conn->sa >> 3);
|
|
||||||
conn->sa += m;
|
|
||||||
if (m < 0)
|
|
||||||
{
|
|
||||||
m = -m;
|
|
||||||
}
|
|
||||||
|
|
||||||
m = m - (conn->sv >> 2);
|
|
||||||
conn->sv += m;
|
|
||||||
conn->rto = (conn->sa >> 3) + conn->sv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the acknowledged flag. */
|
|
||||||
|
|
||||||
flags = UIP_ACKDATA;
|
|
||||||
|
|
||||||
/* Reset the retransmission timer. */
|
|
||||||
|
|
||||||
conn->timer = conn->rto;
|
|
||||||
|
|
||||||
/* Reset length of outstanding data. */
|
|
||||||
|
|
||||||
|
nlldbg("ERROR: ackseq[%08x] > unackseq[%08x]\n", ackseq, unackseq);
|
||||||
conn->unacked = 0;
|
conn->unacked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update sequence number to the unacknowledge sequence number. If
|
||||||
|
* there is still outstanding, unacknowledged data, then this will
|
||||||
|
* be beyond ackseq.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nllvdbg("sndseq: %08x->%08x unackseq: %08x new unacked: %d\n",
|
||||||
|
conn->sndseq, ackseq, unackseq, conn->unacked);
|
||||||
|
uip_tcpsetsequence(conn->sndseq, ackseq);
|
||||||
|
|
||||||
|
/* Do RTT estimation, unless we have done retransmissions. */
|
||||||
|
|
||||||
|
if (conn->nrtx == 0)
|
||||||
|
{
|
||||||
|
signed char m;
|
||||||
|
m = conn->rto - conn->timer;
|
||||||
|
|
||||||
|
/* This is taken directly from VJs original code in his paper */
|
||||||
|
|
||||||
|
m = m - (conn->sa >> 3);
|
||||||
|
conn->sa += m;
|
||||||
|
if (m < 0)
|
||||||
|
{
|
||||||
|
m = -m;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = m - (conn->sv >> 2);
|
||||||
|
conn->sv += m;
|
||||||
|
conn->rto = (conn->sa >> 3) + conn->sv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the acknowledged flag. */
|
||||||
|
|
||||||
|
flags |= UIP_ACKDATA;
|
||||||
|
|
||||||
|
/* Reset the retransmission timer. */
|
||||||
|
|
||||||
|
conn->timer = conn->rto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do different things depending on in what state the connection is. */
|
/* 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.
|
* flag set. If so, we enter the ESTABLISHED state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (flags & UIP_ACKDATA)
|
if ((flags & UIP_ACKDATA) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_ESTABLISHED;
|
conn->tcpstateflags = UIP_ESTABLISHED;
|
||||||
conn->unacked = 0;
|
conn->unacked = 0;
|
||||||
@@ -431,7 +453,7 @@ found:
|
|||||||
* state.
|
* 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. */
|
/* Parse the TCP MSS option, if present. */
|
||||||
|
|
||||||
@@ -511,7 +533,7 @@ found:
|
|||||||
|
|
||||||
/* We do not send resets in response to resets. */
|
/* We do not send resets in response to resets. */
|
||||||
|
|
||||||
if (pbuf->flags & TCP_RST)
|
if ((pbuf->flags & TCP_RST) != 0)
|
||||||
{
|
{
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
@@ -531,7 +553,7 @@ found:
|
|||||||
* sequence numbers will be screwed up.
|
* 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)
|
if (conn->unacked > 0)
|
||||||
{
|
{
|
||||||
@@ -639,7 +661,7 @@ found:
|
|||||||
* send, d_len must be set to 0.
|
* 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;
|
dev->d_sndlen = 0;
|
||||||
result = uip_tcpcallback(dev, conn, flags);
|
result = uip_tcpcallback(dev, conn, flags);
|
||||||
@@ -653,7 +675,7 @@ found:
|
|||||||
* FIN. This is indicated by the UIP_ACKDATA flag.
|
* FIN. This is indicated by the UIP_ACKDATA flag.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (flags & UIP_ACKDATA)
|
if ((flags & UIP_ACKDATA) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_CLOSED;
|
conn->tcpstateflags = UIP_CLOSED;
|
||||||
nllvdbg("UIP_LAST_ACK TCP state: UIP_CLOSED\n");
|
nllvdbg("UIP_LAST_ACK TCP state: UIP_CLOSED\n");
|
||||||
@@ -672,9 +694,10 @@ found:
|
|||||||
{
|
{
|
||||||
uip_incr32(conn->rcvseq, dev->d_len);
|
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->tcpstateflags = UIP_TIME_WAIT;
|
||||||
conn->timer = 0;
|
conn->timer = 0;
|
||||||
@@ -692,7 +715,7 @@ found:
|
|||||||
uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);
|
uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (flags & UIP_ACKDATA)
|
else if ((flags & UIP_ACKDATA) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_FIN_WAIT_2;
|
conn->tcpstateflags = UIP_FIN_WAIT_2;
|
||||||
conn->unacked = 0;
|
conn->unacked = 0;
|
||||||
@@ -713,7 +736,7 @@ found:
|
|||||||
uip_incr32(conn->rcvseq, dev->d_len);
|
uip_incr32(conn->rcvseq, dev->d_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pbuf->flags & TCP_FIN)
|
if ((pbuf->flags & TCP_FIN) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_TIME_WAIT;
|
conn->tcpstateflags = UIP_TIME_WAIT;
|
||||||
conn->timer = 0;
|
conn->timer = 0;
|
||||||
@@ -737,7 +760,7 @@ found:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case UIP_CLOSING:
|
case UIP_CLOSING:
|
||||||
if (flags & UIP_ACKDATA)
|
if ((flags & UIP_ACKDATA) != 0)
|
||||||
{
|
{
|
||||||
conn->tcpstateflags = UIP_TIME_WAIT;
|
conn->tcpstateflags = UIP_TIME_WAIT;
|
||||||
conn->timer = 0;
|
conn->timer = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user