mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-18 20:10:53 +00:00
* tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission
timer is reset to fix bug#19434, with help from Oleg Tyshev.
This commit is contained in:
parent
58b3b0603d
commit
79be888b6f
@ -500,18 +500,24 @@ tcp_slowtmr(void)
|
||||
++pcb_remove;
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
|
||||
} else {
|
||||
++pcb->rtime;
|
||||
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
||||
/* Increase the retransmission timer if it is running */
|
||||
if(pcb->rtime >= 0)
|
||||
++pcb->rtime;
|
||||
|
||||
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
||||
/* Time for a retransmission. */
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
|
||||
pcb->rtime, pcb->rto));
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F" pcb->rto %"S16_F"\n",
|
||||
pcb->rtime, pcb->rto));
|
||||
|
||||
/* Double retransmission time-out unless we are trying to
|
||||
* connect to somebody (i.e., we are in SYN_SENT). */
|
||||
if (pcb->state != SYN_SENT) {
|
||||
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
||||
}
|
||||
|
||||
/* Reset the retransmission timer. */
|
||||
pcb->rtime = 0;
|
||||
|
||||
/* Reduce congestion window and ssthresh. */
|
||||
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
||||
pcb->ssthresh = eff_wnd >> 1;
|
||||
@ -520,11 +526,11 @@ tcp_slowtmr(void)
|
||||
}
|
||||
pcb->cwnd = pcb->mss;
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\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 */
|
||||
if (pcb->state == FIN_WAIT_2) {
|
||||
@ -844,7 +850,7 @@ tcp_alloc(u8_t prio)
|
||||
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
|
||||
pcb->sa = 0;
|
||||
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
||||
pcb->rtime = 0;
|
||||
pcb->rtime = -1;
|
||||
pcb->cwnd = 1;
|
||||
iss = tcp_next_iss();
|
||||
pcb->snd_wl2 = iss;
|
||||
@ -994,6 +1000,10 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
|
||||
}
|
||||
|
||||
/* Stop the retransmission timer as it will expect data on unacked
|
||||
queue if it fires */
|
||||
pcb->rtime = -1;
|
||||
|
||||
tcp_segs_free(pcb->ooseq);
|
||||
pcb->ooseq = NULL;
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
@ -282,12 +282,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
} else if (recv_flags & TF_CLOSED) {
|
||||
} else if (recv_flags & TF_CLOSED) {
|
||||
/* The connection has been closed and we will deallocate the
|
||||
PCB. */
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
} else {
|
||||
} else {
|
||||
err = ERR_OK;
|
||||
/* If the application has registered a "sent" function to be
|
||||
called when new send buffer space is available, we call it
|
||||
@ -504,6 +504,14 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||
rseg = pcb->unacked;
|
||||
pcb->unacked = rseg->next;
|
||||
|
||||
/* If there's nothing left to acknowledge, stop the retransmit
|
||||
timer, otherwise reset it to start again */
|
||||
if(pcb->unacked == NULL)
|
||||
pcb->rtime = -1;
|
||||
else
|
||||
pcb->rtime = 0;
|
||||
|
||||
tcp_seg_free(rseg);
|
||||
|
||||
/* Parse any options in the SYNACK. */
|
||||
@ -700,10 +708,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
|
||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||
}
|
||||
} else
|
||||
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)) { */
|
||||
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
|
||||
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
|
||||
/* We come here when the ACK acknowledges new data. */
|
||||
|
||||
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
||||
@ -775,6 +780,14 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's nothing left to acknowledge, stop the retransmit
|
||||
timer, otherwise reset it to start again */
|
||||
if(pcb->unacked == NULL)
|
||||
pcb->rtime = -1;
|
||||
else
|
||||
pcb->rtime = 0;
|
||||
|
||||
pcb->polltmr = 0;
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
|
||||
}
|
||||
|
||||
pcb->rtime = 0;
|
||||
/* Set retransmission timer running if it is not currently enabled */
|
||||
if(pcb->rtime == -1)
|
||||
pcb->rtime = 0;
|
||||
|
||||
if (pcb->rttest == 0) {
|
||||
pcb->rttest = tcp_ticks;
|
||||
@ -674,7 +676,6 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
/* Do the actual retransmission. */
|
||||
snmp_inc_tcpretranssegs();
|
||||
tcp_output(pcb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -253,7 +253,7 @@ struct tcp_pcb {
|
||||
u8_t polltmr, pollinterval;
|
||||
|
||||
/* Retransmission timer. */
|
||||
u16_t rtime;
|
||||
s16_t rtime;
|
||||
|
||||
u16_t mss; /* maximum segment size */
|
||||
|
||||
@ -262,7 +262,7 @@ struct tcp_pcb {
|
||||
u32_t rtseq; /* sequence number being timed */
|
||||
s16_t sa, sv; /* @todo document this */
|
||||
|
||||
u16_t rto; /* retransmission time-out */
|
||||
s16_t rto; /* retransmission time-out */
|
||||
u8_t nrtx; /* number of retransmissions */
|
||||
|
||||
/* fast retransmit/recovery */
|
||||
|
Loading…
Reference in New Issue
Block a user