Fixed bug in duplicate ack handling

(see http://www.sics.se/mailing-lists/lwip.html/msg01460.html)
Solution adds check on right window edge when duplicate ack received, if it is different it is not a duplicate.
This commit is contained in:
kieranm 2002-10-24 13:14:52 +00:00
parent ef6b7099ba
commit 4933bfaaa0

View File

@ -604,6 +604,8 @@ tcp_receive(struct tcp_pcb *pcb)
if(flags & TCP_ACK) { if(flags & TCP_ACK) {
unsigned long int right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;
/* Update window. */ /* Update window. */
if(TCP_SEQ_LT(pcb->snd_wl1, seqno) || if(TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
(pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
@ -623,29 +625,33 @@ tcp_receive(struct tcp_pcb *pcb)
if(pcb->lastack == ackno) { if(pcb->lastack == ackno) {
++pcb->dupacks; if(pcb->snd_wl1+pcb->snd_wnd==right_wnd_edge){
if(pcb->dupacks >= 3 && pcb->unacked != NULL) { ++pcb->dupacks;
if(!(pcb->flags & TF_INFR)) { if(pcb->dupacks >= 3 && pcb->unacked != NULL) {
/* This is fast retransmit. Retransmit the first unacked segment. */ if(!(pcb->flags & TF_INFR)) {
DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n", /* This is fast retransmit. Retransmit the first unacked segment. */
pcb->dupacks, pcb->lastack, DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n",
ntohl(pcb->unacked->tcphdr->seqno))); pcb->dupacks, pcb->lastack,
tcp_rexmit(pcb); ntohl(pcb->unacked->tcphdr->seqno)));
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */ tcp_rexmit(pcb);
pcb->ssthresh = UMAX((pcb->snd_max - /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
pcb->lastack) / 2, pcb->ssthresh = UMAX((pcb->snd_max -
2 * pcb->mss); pcb->lastack) / 2,
2 * pcb->mss);
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
pcb->flags |= TF_INFR; pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
} else { pcb->flags |= TF_INFR;
/* Inflate the congestion window, but not if it means that } else {
the value overflows. */ /* Inflate the congestion window, but not if it means that
if((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { the value overflows. */
pcb->cwnd += pcb->mss; if((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss;
}
} }
}
} }
else{
DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n", pcb->snd_wl1+pcb->snd_wnd, right_wnd_edge));
} }
} else if(TCP_SEQ_LT(pcb->lastack, ackno) && } else if(TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)) { TCP_SEQ_LEQ(ackno, pcb->snd_max)) {