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

Reply via email to