diff -u -wbrP --exclude=config.save linux-2.4.22/net/ipv4/tcp_input.c linux-2.4.22-retrans/net/ipv4/tcp_input.c --- linux-2.4.22/net/ipv4/tcp_input.c 2003-06-13 15:51:39.000000000 +0100 +++ linux-2.4.22-retrans/net/ipv4/tcp_input.c 2003-10-09 07:59:48.000000000 +0100 @@ -61,6 +61,7 @@ * Panu Kuhlberg: Experimental audit of TCP (re)transmission * engine. Lots of bugs are found. * Pasi Sarolahti: F-RTO for dealing with spurious RTOs + * Doug Leith: Early retransmission of packets falling into sack holes. */ #include @@ -757,6 +758,10 @@ * for retransmitted and already SACKed segment -> reordering.. * Both of these heuristics are not used in Loss state, when we cannot * account for retransmits accurately. + * + * Retransmission of packets + * ------------------------- + * Extension of Hoe's retransmit to allow early retransmission of packets which fall into sack holes */ static int tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una) @@ -770,6 +775,7 @@ u32 lost_retrans = 0; int flag = 0; int i; + u32 prior_sacked_out=tp->sacked_out; if (!tp->sacked_out) tp->fackets_out = 0; @@ -781,6 +787,7 @@ __u32 end_seq = ntohl(sp->end_seq); int fack_count = 0; int dup_sack = 0; + u32 sack_count=0; /* Check for D-SACK. */ if (i == 0) { @@ -828,6 +835,8 @@ break; fack_count++; + if (sacked&TCPCB_RETRANS) + sack_count++; in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && !before(end_seq, TCP_SKB_CB(skb)->end_seq); @@ -860,8 +869,14 @@ (!lost_retrans || after(end_seq, lost_retrans))) lost_retrans = end_seq; - if (!in_sack) + if (!in_sack) { + /* force early retransmit ? */ + if (!(sacked&TCPCB_TAGBITS) && (prior_sacked_out > sack_count + tp->reordering)) { + TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; + tp->lost_out++; + } continue; + } if (!(sacked&TCPCB_SACKED_ACKED)) { if (sacked & TCPCB_SACKED_RETRANS) { @@ -1599,7 +1614,7 @@ if ((flag&FLAG_DATA_LOST) && before(tp->snd_una, tp->high_seq) && tp->ca_state != TCP_CA_Open && - tp->fackets_out > tp->reordering) { + tp->fackets_out > tp->reordering && IsReno(tp) ) { tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq); NET_INC_STATS_BH(TCPLoss); } @@ -1714,7 +1729,7 @@ tp->ca_state = TCP_CA_Recovery; } - if (is_dupack || tcp_head_timedout(sk, tp)) + if ( (is_dupack || tcp_head_timedout(sk, tp)) && IsReno(tp) ) tcp_update_scoreboard(sk, tp); tcp_cwnd_down(tp); tcp_xmit_retransmit_queue(sk);