Bug 49915 - Excessive Send-Q memory waste
Excessive Send-Q memory waste
Product: Red Hat Linux
Classification: Retired
Component: kernel (Show other bugs)
All Linux
medium Severity high
: ---
: ---
Assigned To: David Miller
Brock Organ
Depends On:
  Show dependency treegraph
Reported: 2001-07-24 21:32 EDT by Need Real Name
Modified: 2007-04-18 12:35 EDT (History)
1 user (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2001-08-02 14:10:54 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description Need Real Name 2001-07-24 21:32:22 EDT
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
time.  Many of such connections can cause the kernel to waste hundreds of
(if available).

How reproducible:

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 14:10:50 EDT
This is assigned to the wrong person.  Re-assigning.
Comment 2 David Miller 2001-08-03 01:38:56 EDT
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.