Description

UTO stands for User Timeout Option. It's a TCP option (option kind 28) described in RFC5482.

User Timeout

The concept of User Timeout is specified in RFC793 as a general timeout used for various purposes. In particular TCP will tear down the connection if this timeout expires in any state. RFC 793 specifies that a user should be allowed to specify a timeout for "Open" and "Send" (the last timeout specified overrides previous values). FreeBSD (and other Unix implementations) generally support an option called SO_SNDTIMEO. However, there is no provision for advertising this value to the other peer.

TCP UTO Benefits

The ability to change the local value is useless if not advertised to the other peer since he will still close the connection after his timeout expires (in other words he has no idea of the User Timeout chosen by the other side).

Operation

The users should be allowed to specify the option (perhaps via setsockopt). The RFC specifies it should also be controllable system-wide (for example enabling it for all connections).

An implementation is free to disregard the timeout specified via TCP UTO. Also, it is an "advisory" option and it doesn't have to be exchanged reliably.

Project status

Download

Using the option

Currently an application is allowed to specify via setsockopt:

Sysctls controlling UTO operation:

Examples

This example instructs TCP to advertise 7200 seconds of UTO. If the peer accepts this, the connection will stay up even if the underlying link is broken for two hours.

int optval;
int s;

/* ... */

s = socket(AF_INET, SOCK_STREAM, 0);
optval = 7200; /* Two hours. */
rc = setsockopt(s, IPPROTO_TCP, TCP_SNDUTO_TIMEOUT, &optval, sizeof(optval));
if (rc != 0) {
        perror("setsockopt");
        exit(1);
}

This example instructs TCP to accept any timeout suggestion from the peer.

s = socket(AF_INET, SOCK_STREAM, 0);
optval = 1;
rc = setsockopt(s, IPPROTO_TCP, TCP_RCVUTO_TIMEOUT, &optval, sizeof(optval));
if (0 != rc) {
        perror("setsockopt");
        exit(1);
}

Via TCP_RCVUTO_TIMEOUT an application can retrieve the timeout received from the peer.

socklen_t optlen;
int optval;
int s;

s = socket(AF_INET, SOCK_STREAM, 0);
/* ... */
rc = connect(s, (struct sockaddr *)&address, sizeof(address));
if (0 != rc) {
        perror("connect");
}

/* See if our peer suggested some timeout. */
optlen = 4;
rc = getsockopt(s, IPPROTO_TCP, TCP_RCVUTO_TIMEOUT, &optval, &optlen);
if (rc != 0) {
        printf("Errno %d\n", errno);
}

Captures

My version of tcpdump doesn't display sequence numbers unless I force it with -vv which brings along a lot of uninteresting stuff. I am using tshark to parse the pcap files and I am annotating the output, but the pcap files are also attached.

Exchanging UTO values

In this example the peers simply send UTO values. Both peers send UTO

Normal TCP connection without UTO

no-uto.pcap

In this scenario the client doesn't answer to the 12 retransmits so the server resets the connection after 5 minutes of silence. This is the classic operation of a TCP connection on FreeBSD.

# Initial handshake
  1   0.000000 192.168.12.2 -> 192.168.13.3 TCP 74 19517 > 1296 [SYN] Seq=0
  2   0.000345 192.168.13.3 -> 192.168.12.2 TCP 74 1296 > 19517 [SYN, ACK] Seq=0 Ack=1
  3   0.000741 192.168.12.2 -> 192.168.13.3 TCP 66 19517 > 1296 [ACK] Seq=1 Ack=1

# The server tries to send 3 packets but the client is disconnected (ipfw)
  4   6.482818 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 19517 [ACK] Seq=1 Ack=1
  5   6.482985 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 19517 [ACK] Seq=1449 Ack=1
  6   6.483067 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 19517 [ACK] Seq=2897 Ack=1

# 12 retransmits follow (notice how it backs off to larger and larger timeouts)
  7   6.916564 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
  8   7.596579 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
  9   8.756604 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 10  10.876683 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 11  14.916880 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 12  21.836082 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 13  35.475604 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 14  62.553711 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 15 116.510775 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 16 180.506086 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 17 244.502654 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1
 18 308.499215 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 19517 [ACK] Seq=1 Ack=1

# The server closes the connection
 19 372.495322 192.168.13.3 -> 192.168.12.2 TCP 66 1296 > 19517 [RST, ACK] Seq=4345 Ack=1

# The client comes back and decides to close the connection but the server treats the FIN as an invalid segment.
 20 387.982898 192.168.12.2 -> 192.168.13.3 TCP 66 19517 > 1296 [FIN, ACK] Seq=1 Ack=1
 21 387.983274 192.168.13.3 -> 192.168.12.2 TCP 60 1296 > 19517 [RST] Seq=1

600 seconds UTO

600uto.pcap In this capture the server chooses a 600 seconds user timeout.

# Initial handshake
  1   0.000000 192.168.12.2 -> 192.168.13.3 TCP 74 33687 > 1296 [SYN] Seq=0
  2   0.000504 192.168.13.3 -> 192.168.12.2 TCP 78 1296 > 33687 [SYN, ACK] Seq=0 Ack=1 Win=65535 USER_TO=600
  3   0.000876 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [ACK] Seq=1 Ack=1

# 3 packets sent
  4   7.717107 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 33687 [ACK] Seq=1 Ack=1
  5   7.717309 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 33687 [ACK] Seq=1449 Ack=1
  6   7.717382 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 33687 [ACK] Seq=2897 Ack=1

# 12 retransmissions, the client still doesn't answer
  7   8.040890 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
  8   8.500882 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
  9   9.219940 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 10  10.459953 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 11  12.740072 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 12  16.780193 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 13  24.660499 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 14  40.220211 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 15  71.139316 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 16 132.777676 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 17 194.415919 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 18 256.054229 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1

# Another three retransmissions, due to UTO
 19 317.692834 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 20 381.691351 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1
 21 445.690630 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1 Ack=1

# The client finally answers and the connection continues normally
 22 445.786556 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [ACK] Seq=1 Ack=1449
 23 445.786690 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=1449 Ack=1
 24 445.786751 192.168.13.3 -> 192.168.12.2 TCP 1514 [TCP Retransmission] 1296 > 33687 [ACK] Seq=2897 Ack=1
 25 445.787062 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [ACK] Seq=1 Ack=4345
 26 445.787215 192.168.13.3 -> 192.168.12.2 TCP 1514 1296 > 33687 [ACK] Seq=4345 Ack=1
 27 445.787259 192.168.13.3 -> 192.168.12.2 TCP 274 1296 > 33687 [PSH, ACK] Seq=5793 Ack=1
 28 445.787478 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [ACK] Seq=1 Ack=6001
 29 459.007433 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [FIN, ACK] Seq=1 Ack=6001
 30 459.007640 192.168.13.3 -> 192.168.12.2 TCP 66 1296 > 33687 [ACK] Seq=6001 Ack=2
 31 465.031436 192.168.13.3 -> 192.168.12.2 TCP 66 1296 > 33687 [FIN, ACK] Seq=6001 Ack=2
 32 465.031832 192.168.12.2 -> 192.168.13.3 TCP 66 33687 > 1296 [ACK] Seq=2 Ack=6002

IPv6 UTO

uto6.pcap

In this capture IPv6 is used. The server imposes a very small user timeout and the connection is dropped after only 5 seconds.

# Initial handshake
  1   0.000000 2001:db80:2::2 -> 2001:db80:3::3 TCP 94 60795 > 1296 [SYN] Seq=0
  2   0.000332 2001:db80:3::3 -> 2001:db80:2::2 TCP 98 1296 > 60795 [SYN, ACK] Seq=0 Ack=1 Win=65535 USER_TO=5
  3   0.000654 2001:db80:2::2 -> 2001:db80:3::3 TCP 86 60795 > 1296 [ACK] Seq=1 Ack=1

# Server begins sending. Notice the first packet contains the option again
  4  10.425778 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 1296 > 60795 [ACK] Seq=1 Ack=1 Win=65688 USER_TO=5
  5  10.426067 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 1296 > 60795 [ACK] Seq=1425 Ack=1
  6  10.426073 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 1296 > 60795 [ACK] Seq=2853 Ack=1

# The client doesn't answer so retransmissions start
  7  10.994040 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 [TCP Retransmission] 1296 > 60795 [ACK] Seq=1 Ack=1
  8  11.934132 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 [TCP Retransmission] 1296 > 60795 [ACK] Seq=1 Ack=1
  9  13.614167 2001:db80:3::3 -> 2001:db80:2::2 TCP 1514 [TCP Retransmission] 1296 > 60795 [ACK] Seq=1 Ack=1

# After 5 seconds of silence the connection is dropped
 10  16.773308 2001:db80:3::3 -> 2001:db80:2::2 TCP 86 1296 > 60795 [RST, ACK] Seq=4281 Ack=1

Partial UTO

partial.pcap In this scenario the client requests an 1800 seconds UTO but the server is only willing to accept 300 seconds. The server specifies this via:

optval = 300;
setsockopt(s, IPPROTO_TCP, TCP_RCVUTO_TIMEOUT, &optval, sizeof(optval));

# Initial handshake. The client asks for 1800 seconds UTO
  1   0.000000 192.168.13.3 -> 192.168.12.2 TCP 78 45699 > 1296 [SYN] Seq=0 Win=65535 USER_TO=1800
  2   0.001134 192.168.12.2 -> 192.168.13.3 TCP 74 1296 > 45699 [SYN, ACK] Seq=0 Ack=1
  3   0.001664 192.168.13.3 -> 192.168.12.2 TCP 70 45699 > 1296 [ACK] Seq=1 Ack=1 Win=66608 USER_TO=1800

# The server begins sending data
  4  17.894382 192.168.12.2 -> 192.168.13.3 TCP 1514 1296 > 45699 [ACK] Seq=1 Ack=1
  5  17.894516 192.168.12.2 -> 192.168.13.3 TCP 1514 1296 > 45699 [ACK] Seq=1449 Ack=1
  6  17.894839 192.168.12.2 -> 192.168.13.3 TCP 1514 1296 > 45699 [ACK] Seq=2897 Ack=1

# Retransmissions begin
  7  18.125038 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
  8  18.384163 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
  9  18.704084 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 10  19.144236 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 11  19.824865 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 12  20.984525 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 13  23.104820 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 14  27.145233 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 15  35.024713 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 16  50.584673 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 17  66.144520 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 18  81.705064 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1

# 12 retransmissions have been performed but the server doesn't drop the connection yet
 19  97.264822 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 20 161.267272 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 21 225.265957 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1
 22 289.265052 192.168.12.2 -> 192.168.13.3 TCP 1514 [TCP Retransmission] 1296 > 45699 [ACK] Seq=1 Ack=1

# After 300 seconds the server drops the connection
 23 318.464733 192.168.12.2 -> 192.168.13.3 TCP 66 1296 > 45699 [RST, ACK] Seq=4345 Ack=1

CatalinNicutar/TCPUTO (last edited 2011-08-20T14:47:31+0000 by CatalinNicutar)