mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-27 12:35:26 +00:00
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:
parent
fae1397468
commit
2ed5bc5195
@ -590,7 +590,6 @@ tcp_slowtmr(void)
|
|||||||
if (pcb->state != SYN_SENT) {
|
if (pcb->state != SYN_SENT) {
|
||||||
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
||||||
}
|
}
|
||||||
tcp_rexmit(pcb);
|
|
||||||
/* Reduce congestion window and ssthresh. */
|
/* Reduce congestion window and ssthresh. */
|
||||||
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
||||||
pcb->ssthresh = eff_wnd >> 1;
|
pcb->ssthresh = eff_wnd >> 1;
|
||||||
@ -600,7 +599,10 @@ tcp_slowtmr(void)
|
|||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
|
||||||
pcb->cwnd, pcb->ssthresh));
|
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 */
|
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
|
||||||
if (pcb->state == FIN_WAIT_2) {
|
if (pcb->state == FIN_WAIT_2) {
|
||||||
|
@ -818,10 +818,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
rationale is that lwIP puts all outstanding segments on the
|
rationale is that lwIP puts all outstanding segments on the
|
||||||
->unsent list after a retransmission, so these segments may
|
->unsent list after a retransmission, so these segments may
|
||||||
in fact have been sent once. */
|
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 &&
|
while (pcb->unsent != NULL &&
|
||||||
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
|
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
|
||||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
|
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);
|
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/* End of ACK for new data processing. */
|
/* End of ACK for new data processing. */
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
|
||||||
|
@ -462,8 +462,16 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
pcb->unacked = seg;
|
pcb->unacked = seg;
|
||||||
useg = seg;
|
useg = seg;
|
||||||
} else {
|
} else {
|
||||||
useg->next = seg;
|
/* In the case of fast retransmit, the packet should not go to the end
|
||||||
useg = useg->next;
|
* 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 {
|
} else {
|
||||||
tcp_seg_free(seg);
|
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));
|
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
|
void
|
||||||
tcp_rexmit(struct tcp_pcb *pcb)
|
tcp_rexmit(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@ -595,6 +630,7 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_keepalive(struct tcp_pcb *pcb)
|
tcp_keepalive(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
@ -105,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
|
|||||||
/* Used within the TCP code only: */
|
/* Used within the TCP code only: */
|
||||||
err_t tcp_output (struct tcp_pcb *pcb);
|
err_t tcp_output (struct tcp_pcb *pcb);
|
||||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||||
|
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user