* 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:
kieranm 2007-04-12 14:56:07 +00:00
parent 58b3b0603d
commit 79be888b6f
4 changed files with 42 additions and 18 deletions

View File

@ -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;
@ -993,7 +999,11 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
if (pcb->ooseq != NULL) {
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 */

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 */