title: Application control of TCP retransmission on Linux
body: <p><strong>For the impatient:</strong></p>
  <p>How to change the value of <code>/proc/sys/net/ipv4/tcp_retries2</code> for a single connection in Linux, using <code>setsockopt()</code>, <code>ioctl()</code> or such, or is it possible?</p>
  <p><strong>Longer decription:</strong></p>
  <p>I'm developing an application that uses long polling HTTP requests. On the server side, it needs to be known when the client has closed the connection. The accuracy is not critical, but it certainly cannot be 15 minutes. Closer to a minute would do fine.</p>
  <p>For those not familiar with the concept, a long polling HTTP request works like this:</p>
  <ul>
  <li>The client sends a request</li>
  <li>The server responds with HTTP headers, but leaves the response open. Chunked transfer encoding is used, allowing the server to sends bits of data as they become available.</li>
  <li>When all the data is sent, the server sends a &quot;closing chunk&quot; to signal that the response is complete.</li>
  </ul>
  <p>In my application, the server sends &quot;heartbeats&quot; to the client every now an then (30 seconds by default). A heartbeat is just a newline character that is sent as a response chunk. This is meant to keep the line busy so that we notify the connection loss.</p>
  <p>There's no problem when the client shuts down correctly. But when it's shut down with force (the client machine loses power, for example), a TCP reset is not sent. In this case, the server sends a heartbeat, which the client doesn't ACK. After this, the server keeps retransmitting the packet for roughly 15 minutes after giving up and reporting the failure to the application layer (our HTTP server). And 15 minutes is too long a wait in my case.</p>
  <p>I can control the retransmission time by writing to the following files in <code>/proc/sys/net/ipv4/</code>:</p>
  <pre class="lang-none prettyprint-override"><code>tcp_retries1 - INTEGER
      This value influences the time, after which TCP decides, that
      something is wrong due to unacknowledged RTO retransmissions,
      and reports this suspicion to the network layer.
      See tcp_retries2 for more details.
  
      RFC 1122 recommends at least 3 retransmissions, which is the
      default.
  
  tcp_retries2 - INTEGER
      This value influences the timeout of an alive TCP connection,
      when RTO retransmissions remain unacknowledged.
      Given a value of N, a hypothetical TCP connection following
      exponential backoff with an initial RTO of TCP_RTO_MIN would
      retransmit N times before killing the connection at the (N+1)th RTO.
  
      The default value of 15 yields a hypothetical timeout of 924.6
      seconds and is a lower bound for the effective timeout.
      TCP will effectively time out at the first RTO which exceeds the
      hypothetical timeout.
  
      RFC 1122 recommends at least 100 seconds for the timeout,
      which corresponds to a value of at least 8.
  </code></pre>
  <p>The default value of <code>tcp_retries2</code> is indeed 8, and my experience of 15 minutes (900 seconds) of retransmission is in line with the kernel documentation quoted above.</p>
  <p>If I change the value of <code>tcp_retries2</code> to 5 for example, the connection dies much more quicker. But setting it like this affects all the connections in the system, and I'd really like to set it for this one long polling connection only.</p>
  <p>A quote from RFC 1122:</p>
  <pre class="lang-none prettyprint-override"><code>4.2.3.5  TCP Connection Failures
  
     Excessive retransmission of the same segment by TCP
     indicates some failure of the remote host or the Internet
     path.  This failure may be of short or long duration.  The
     following procedure MUST be used to handle excessive
     retransmissions of data segments [IP:11]:
  
     (a)  There are two thresholds R1 and R2 measuring the amount
          of retransmission that has occurred for the same
          segment.  R1 and R2 might be measured in time units or
          as a count of retransmissions.
  
     (b)  When the number of transmissions of the same segment
          reaches or exceeds threshold R1, pass negative advice
          (see Section 3.3.1.4) to the IP layer, to trigger
          dead-gateway diagnosis.
  
     (c)  When the number of transmissions of the same segment
          reaches a threshold R2 greater than R1, close the
          connection.
  
     (d)  An application MUST be able to set the value for R2 for
          a particular connection.  For example, an interactive
          application might set R2 to &quot;infinity,&quot; giving the user
          control over when to disconnect.
  
     (e)  TCP SHOULD inform the application of the delivery
          problem (unless such information has been disabled by
          the application; see Section 4.2.4.1), when R1 is
          reached and before R2.  This will allow a remote login
          (User Telnet) application program to inform the user,
          for example.
  </code></pre>
  <p>It seems to me that <code>tcp_retries1</code> and <code>tcp_retries2</code> in Linux correspond to <code>R1</code> and <code>R2</code> in the RFC. The RFC clearly states (in item d) that a conforming implementation MUST allow setting the value of <code>R2</code>, but I have found no way to do it using <code>setsockopt()</code>, <code>ioctl()</code> or such.</p>
  <p>Another option would be to get a notification when <code>R1</code> is exceeded (item e). This is not as good as setting <code>R2</code>, though, as I think <code>R1</code> is hit pretty soon (in a few seconds), and the value of <code>R1</code> cannot be set per connection, or at least the RFC doesn't require it.</p>