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