mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-01 04:12:07 +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;
|
++pcb_remove;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
|
||||||
} else {
|
} else {
|
||||||
++pcb->rtime;
|
/* Increase the retransmission timer if it is running */
|
||||||
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
if(pcb->rtime >= 0)
|
||||||
|
++pcb->rtime;
|
||||||
|
|
||||||
|
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
||||||
/* Time for a retransmission. */
|
/* Time for a retransmission. */
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F" pcb->rto %"S16_F"\n",
|
||||||
pcb->rtime, pcb->rto));
|
pcb->rtime, pcb->rto));
|
||||||
|
|
||||||
/* Double retransmission time-out unless we are trying to
|
/* Double retransmission time-out unless we are trying to
|
||||||
* connect to somebody (i.e., we are in SYN_SENT). */
|
* connect to somebody (i.e., we are in SYN_SENT). */
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset the retransmission timer. */
|
||||||
|
pcb->rtime = 0;
|
||||||
|
|
||||||
/* 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;
|
||||||
@ -520,11 +526,11 @@ tcp_slowtmr(void)
|
|||||||
}
|
}
|
||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
|
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 */
|
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
|
||||||
tcp_rexmit_rto(pcb);
|
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) {
|
||||||
@ -844,7 +850,7 @@ tcp_alloc(u8_t prio)
|
|||||||
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
|
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
|
||||||
pcb->sa = 0;
|
pcb->sa = 0;
|
||||||
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
|
||||||
pcb->rtime = 0;
|
pcb->rtime = -1;
|
||||||
pcb->cwnd = 1;
|
pcb->cwnd = 1;
|
||||||
iss = tcp_next_iss();
|
iss = tcp_next_iss();
|
||||||
pcb->snd_wl2 = iss;
|
pcb->snd_wl2 = iss;
|
||||||
@ -993,7 +999,11 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
|||||||
if (pcb->ooseq != NULL) {
|
if (pcb->ooseq != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
|
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);
|
tcp_segs_free(pcb->ooseq);
|
||||||
pcb->ooseq = NULL;
|
pcb->ooseq = NULL;
|
||||||
#endif /* TCP_QUEUE_OOSEQ */
|
#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_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||||
memp_free(MEMP_TCP_PCB, 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
|
/* The connection has been closed and we will deallocate the
|
||||||
PCB. */
|
PCB. */
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
} else {
|
} else {
|
||||||
err = ERR_OK;
|
err = ERR_OK;
|
||||||
/* If the application has registered a "sent" function to be
|
/* If the application has registered a "sent" function to be
|
||||||
called when new send buffer space is available, we call it
|
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));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||||
rseg = pcb->unacked;
|
rseg = pcb->unacked;
|
||||||
pcb->unacked = rseg->next;
|
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);
|
tcp_seg_free(rseg);
|
||||||
|
|
||||||
/* Parse any options in the SYNACK. */
|
/* 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",
|
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
|
||||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||||
}
|
}
|
||||||
} else
|
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
|
||||||
/*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)){
|
|
||||||
/* We come here when the ACK acknowledges new data. */
|
/* We come here when the ACK acknowledges new data. */
|
||||||
|
|
||||||
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
||||||
@ -775,6 +780,14 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
pcb->unsent != NULL);
|
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;
|
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));
|
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) {
|
if (pcb->rttest == 0) {
|
||||||
pcb->rttest = tcp_ticks;
|
pcb->rttest = tcp_ticks;
|
||||||
@ -674,7 +676,6 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
|||||||
/* Do the actual retransmission. */
|
/* Do the actual retransmission. */
|
||||||
snmp_inc_tcpretranssegs();
|
snmp_inc_tcpretranssegs();
|
||||||
tcp_output(pcb);
|
tcp_output(pcb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ struct tcp_pcb {
|
|||||||
u8_t polltmr, pollinterval;
|
u8_t polltmr, pollinterval;
|
||||||
|
|
||||||
/* Retransmission timer. */
|
/* Retransmission timer. */
|
||||||
u16_t rtime;
|
s16_t rtime;
|
||||||
|
|
||||||
u16_t mss; /* maximum segment size */
|
u16_t mss; /* maximum segment size */
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ struct tcp_pcb {
|
|||||||
u32_t rtseq; /* sequence number being timed */
|
u32_t rtseq; /* sequence number being timed */
|
||||||
s16_t sa, sv; /* @todo document this */
|
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 */
|
u8_t nrtx; /* number of retransmissions */
|
||||||
|
|
||||||
/* fast retransmit/recovery */
|
/* fast retransmit/recovery */
|
||||||
|
Loading…
Reference in New Issue
Block a user