Bug 49915 - Excessive Send-Q memory waste
Summary: Excessive Send-Q memory waste
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: kernel
Version: 7.1
Hardware: All
OS: Linux
medium
high
Target Milestone: ---
Assignee: David Miller
QA Contact: Brock Organ
URL: http://personal.inktomi.com/~jplevyak...
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2001-07-25 01:32 UTC by Need Real Name
Modified: 2007-04-18 16:35 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2001-08-02 18:10:54 UTC
Embargoed:


Attachments (Terms of Use)

Description Need Real Name 2001-07-25 01:32:22 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.75 [en] (X11; U; Linux 2.4.7 i686)

Description of problem:
Both 2.2.X kernels and 2.4.X kernels fail to free sk->write_queue memory
on transition from TCP_CLOSE_WAIT to TCP_LAST_ACK.  For certain ill behaved
connections, this results in the socket buffer being full in LAST_ACK for a
long
time.  Many of such connections can cause the kernel to waste hundreds of
MB
(if available).

How reproducible:
Always

Steps to Reproduce:
1. run an HTTP proxy (e.g. traffic_server (Inktomi) or likely squid) 
2. the proxy sends data
3. before the socket buffer drains a FIN arrives from the client
   (connection is now in CLOSE_WAIT with data in Send-Q)
4. the proxy closes the connection (connection now in LAST_ACK) FIN sent
5. ACK not received (lost)
6. memory wasted in Send-Q		
	

Actual Results:  after a long run of clients with the above behavior, 
netstat reports hundreds of megabytes of data in Send-Q of connections
in LAST_ACK state.

Expected Results:  netstat reports all connections in LAST_ACK have at most
the FIN packet waiting

Additional info:

See the URL also for the patches, but here is the one for 2.4.7:

*** linux-2.4.7.orig/net/ipv4/tcp.c     Tue Jul 24 14:48:58 2001
--- linux-2.4.7/net/ipv4/tcp.c  Tue Jul 24 14:51:48 2001
***************
*** 1711,1716 ****
--- 1711,1722 ----
        int next = (int) new_state[sk->state];
        int ns = (next & TCP_STATE_MASK);
  
+       if (sk->state == TCP_CLOSE_WAIT) {
+               struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+               tcp_writequeue_purge(sk);
+               tp->send_head = 0;
+       }
+ 
        tcp_set_state(sk, ns);
  
        return (next & TCP_ACTION_FIN);

Basically just purge the write_queue on this transition.

I have tested this code and it works.

Comment 1 Doug Ledford 2001-08-02 18:10:50 UTC
This is assigned to the wrong person.  Re-assigning.

Comment 2 David Miller 2001-08-03 05:38:56 UTC
This suggested change is invalid.

The sender must attempt to send the rest of the send queue
before the ACK.  So if the socket is holding onto the memory
this is because the receiving side has not ACK'd the data yet.
Once the data is ACK'd the send queue data will be freed up.

shutdown(SEND) or close() does not mean "all pending send data
is invalid", it means "send all pending data then FIN".

We free up the data as early as is legally possible.



Note You need to log in before you can comment on or make changes to this bug.