On Tue, Aug 09, 2005 at 10:19:11PM +1000, herbert wrote: > > So cnt is equal to fackets_out - reordering. Normally > fackets_out is less than packets_out. The only reason > I've found that might cause fackets_out to exceed packets_out > is if tcp_fragment is called from tcp_retransmit_skb with a > TSO skb and the current MSS is greater than the MSS stored > in the TSO skb. This might occur as the result of an expiring > dst entry. > > In that case, packets_out may decrease (line 1380-1381 in > tcp_output.c). However, fackets_out is unchanged which means > that it may in fact exceed packets_out. > > Previously tcp_retrans_try_collapse was the only place where > packets_out can go down and it takes care of this by decrementing > fackets_out. > > So we should make sure that fackets_out is reduced by an appropriate > amount here as well.
Here is a patch that adjusts fackets_out accordingly. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1370,15 +1370,21 @@ int tcp_retransmit_skb(struct sock *sk, if (skb->len > cur_mss) { int old_factor = tcp_skb_pcount(skb); - int new_factor; + int diff; if (tcp_fragment(sk, skb, cur_mss, cur_mss)) return -ENOMEM; /* We'll try again later. */ /* New SKB created, account for it. */ - new_factor = tcp_skb_pcount(skb); - tp->packets_out -= old_factor - new_factor; - tp->packets_out += tcp_skb_pcount(skb->next); + diff = old_factor - tcp_skb_pcount(skb) - + tcp_skb_pcount(skb->next); + tp->packets_out -= diff; + + if (diff > 0) { + tp->fackets_out -= diff; + if ((int)tp->fackets_out < 0) + tp->fackets_out = 0; + } } /* Collapse two adjacent packets if worthwhile and we can. */