Kieran Mansley - kjm25@cam.ac.uk - 12th September 2004

Applied patch from Sam Jansen as detailed in
http://lists.gnu.org/archive/html/lwip-users/2004-07/msg00106.html
to correctly handle retransmission after a retransmission timeout
This commit is contained in:
kieranm 2004-09-12 16:34:06 +00:00
parent fae1397468
commit 2ed5bc5195
4 changed files with 43 additions and 9 deletions

View File

@ -590,7 +590,6 @@ tcp_slowtmr(void)
if (pcb->state != SYN_SENT) {
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
}
tcp_rexmit(pcb);
/* Reduce congestion window and ssthresh. */
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
pcb->ssthresh = eff_wnd >> 1;
@ -600,7 +599,10 @@ tcp_slowtmr(void)
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
pcb->cwnd, pcb->ssthresh));
}
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
tcp_rexmit_rto(pcb);
}
}
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
if (pcb->state == FIN_WAIT_2) {

View File

@ -818,10 +818,6 @@ tcp_receive(struct tcp_pcb *pcb)
rationale is that lwIP puts all outstanding segments on the
->unsent list after a retransmission, so these segments may
in fact have been sent once. */
/* KJM 13th July 2004
I don't think is is necessary as we no longer move all unacked
segments on the unsent queue when performing retransmit */
#if 0
while (pcb->unsent != NULL &&
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
@ -846,7 +842,6 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
}
}
#endif
/* End of ACK for new data processing. */
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",

View File

@ -462,8 +462,16 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unacked = seg;
useg = seg;
} else {
useg->next = seg;
useg = useg->next;
/* In the case of fast retransmit, the packet should not go to the end
* of the unacked queue, but rather at the start. We need to check for
* this case. -STJ Jul 27, 2004 */
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
seg->next = pcb->unacked;
pcb->unacked = seg;
} else {
useg->next = seg;
useg = useg->next;
}
}
} else {
tcp_seg_free(seg);
@ -568,6 +576,33 @@ tcp_rst(u32_t seqno, u32_t ackno,
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
}
void
tcp_rexmit_rto(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move all unacked segments to the unsent queue. */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
seg->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = NULL;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
++pcb->nrtx;
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission. */
tcp_output(pcb);
}
void
tcp_rexmit(struct tcp_pcb *pcb)
{
@ -595,6 +630,7 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{

View File

@ -105,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
/* Used within the TCP code only: */
err_t tcp_output (struct tcp_pcb *pcb);
void tcp_rexmit (struct tcp_pcb *pcb);
void tcp_rexmit_rto (struct tcp_pcb *pcb);