Number of retries

Can be configured with sysctl net.ipv4.tcp_syn_retries. The default is 6.

#define TCP_SYN_RETRIES	 6	/* This is how many retries are done
				 * when active opening a connection.
				 * RFC1122 says the minimum retry MUST
				 * be at least 180secs.  Nevertheless
				 * this value is corresponding to
				 * 63secs of retransmission with the
				 * current initial RTO.
				 */

Timeout

Default initial RTO is 1 second.

#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ))	/* RFC6298 2.1 initial RTO value	*/

Before Linux 6.5, the default 6 retries correspond to 63 (1+2+4+…+32) seconds from the first SYN packet till the last retransmission, and 127 seconds (64 seconds later) till the final timeout.

After Linux 6.5, the expected time is 67 seconds (with tcp_syn_linear_timeouts = 4) for last retransmission and 131 seconds for final timeout.

net.ipv4.tcp_syn_linear_timeouts - INTEGER (since Linux 6.5)

The number of times for an active TCP connection to retransmit SYNs with a linear backoff timeout before defaulting to an exponential backoff timeout. This has no effect on SYNACK at the passive TCP side.

With an initial RTO of 1 and tcp_syn_linear_timeouts = 4 we would expect SYN RTOs to be: 1, 1, 1, 1, 1, 2, 4, … (4 linear timeouts, and the first exponential backoff using 2^0 * initial_RTO). Default: 4

However, actual time from the last retransmission to connection timeout may vary in different environments. You can test the behavior with:

# nc from nmap
time nc -zv -w 200000ms 1.1.1.1 2345
 
# OpenBSD netcat
time nc -zv -w 200 1.1.1.1 2345
 
# BusyBox nc
time nc 1.1.1.1 2345

For reference, time till final timeout on macOS is 75 seconds.

$ time nc -zv -w 200 1.1.1.1 2345
nc: connectx to 1.1.1.1 port 2345 (tcp) failed: Operation timed out
nc -zv -w 200 1.1.1.1 2345  0.00s user 0.00s system 0% cpu 1:15.01 total

Referenes

Comments on Kernel Source Code

  • 3WHS means three-way handshake.
  • tcp_init_transfer and subsequently tcp_init_metrics are only called after the connection has been established, so TCP_TIMEOUT_FALLBACK is not used during the three-way handshake.