fixed bug #24212: "Deadlocked tcp_retransmit due to exceeded pcb->cwnd": Fixed by sorting the unsent and unacked queues (segments are inserted at the right place in tcp_output and tcp_rexmit)

This commit is contained in:
goldsimon 2009-04-26 12:27:11 +00:00
parent cbfacb7ed9
commit 261dfdf010
2 changed files with 26 additions and 8 deletions

View File

@ -92,6 +92,11 @@ HISTORY
++ Bugfixes:
2009-04-25 Simon Goldschmidt, Oleg Tyshev
* tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd
Fixed by sorting the unsent and unacked queues (segments are inserted at the
right place in tcp_output and tcp_rexmit).
2009-04-25 Simon Goldschmidt
* memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation
when debugging": memp_sizes contained the wrong sizes (including sanity

View File

@ -595,12 +595,17 @@ tcp_output(struct tcp_pcb *pcb)
/* unacked list is not empty? */
} else {
/* In the case of fast retransmit, the packet should not go to the tail
* of the unacked queue, but rather at the head. We need to check for
* of the unacked queue, but rather somewhere before it. We need to check for
* this case. -STJ Jul 27, 2004 */
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
/* add segment to head of unacked list */
seg->next = pcb->unacked;
pcb->unacked = seg;
/* add segment to before tail of unacked list, keeping the list sorted */
struct tcp_seg **cur_seg = &(pcb->unacked);
while (*cur_seg &&
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
cur_seg = &((*cur_seg)->next );
}
seg->next = (*cur_seg);
(*cur_seg) = seg;
} else {
/* add segment to tail of unacked list */
useg->next = seg;
@ -820,16 +825,24 @@ void
tcp_rexmit(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
struct tcp_seg **cur_seg;
if (pcb->unacked == NULL) {
return;
}
/* Move the first unacked segment to the unsent queue */
seg = pcb->unacked->next;
pcb->unacked->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = seg;
/* Keep the unsent queue sorted. */
seg = pcb->unacked;
pcb->unacked = seg->next;
cur_seg = &(pcb->unsent);
while (*cur_seg &&
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
cur_seg = &((*cur_seg)->next );
}
seg->next = *cur_seg;
*cur_seg = seg;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);