Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: add TCP_INFO status for failed client TFO

The TCPI_OPT_SYN_DATA bit as part of tcpi_options currently reports whether
or not data-in-SYN was ack'd on both the client and server side. We'd like
to gather more information on the client-side in the failure case in order
to indicate the reason for the failure. This can be useful for not only
debugging TFO, but also for creating TFO socket policies. For example, if
a middle box removes the TFO option or drops a data-in-SYN, we can
can detect this case, and turn off TFO for these connections saving the
extra retransmits.

The newly added tcpi_fastopen_client_fail status is 2 bits and has the
following 4 states:

1) TFO_STATUS_UNSPEC

Catch-all state which includes when TFO is disabled via black hole
detection, which is indicated via LINUX_MIB_TCPFASTOPENBLACKHOLE.

2) TFO_COOKIE_UNAVAILABLE

If TFO_CLIENT_NO_COOKIE mode is off, this state indicates that no cookie
is available in the cache.

3) TFO_DATA_NOT_ACKED

Data was sent with SYN, we received a SYN/ACK but it did not cover the data
portion. Cookie is not accepted by server because the cookie may be invalid
or the server may be overloaded.

4) TFO_SYN_RETRANSMITTED

Data was sent with SYN, we received a SYN/ACK which did not cover the data
after at least 1 additional SYN was sent (without data). It may be the case
that a middle-box is dropping data-in-SYN packets. Thus, it would be more
efficient to not use TFO on this connection to avoid extra retransmits
during connection establishment.

These new fields do not cover all the cases where TFO may fail, but other
failures, such as SYN/ACK + data being dropped, will result in the
connection not becoming established. And a connection blackhole after
session establishment shows up as a stalled connection.

Signed-off-by: Jason Baron <jbaron@akamai.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Christoph Paasch <cpaasch@apple.com>
Cc: Yuchung Cheng <ycheng@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jason Baron and committed by
David S. Miller
48027478 79f2056b

+20 -3
+1 -1
include/linux/tcp.h
··· 223 223 fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */ 224 224 fastopen_no_cookie:1, /* Allow send/recv SYN+data without a cookie */ 225 225 is_sack_reneg:1, /* in recovery from loss with SACK reneg? */ 226 - unused:2; 226 + fastopen_client_fail:2; /* reason why fastopen failed */ 227 227 u8 nonagle : 4,/* Disable Nagle algorithm? */ 228 228 thin_lto : 1,/* Use linear timeouts for thin streams */ 229 229 recvmsg_inq : 1,/* Indicate # of bytes in queue upon recvmsg */
+9 -1
include/uapi/linux/tcp.h
··· 155 155 TCP_QUEUES_NR, 156 156 }; 157 157 158 + /* why fastopen failed from client perspective */ 159 + enum tcp_fastopen_client_fail { 160 + TFO_STATUS_UNSPEC, /* catch-all */ 161 + TFO_COOKIE_UNAVAILABLE, /* if not in TFO_CLIENT_NO_COOKIE mode */ 162 + TFO_DATA_NOT_ACKED, /* SYN-ACK did not ack SYN data */ 163 + TFO_SYN_RETRANSMITTED, /* SYN-ACK did not ack SYN data after timeout */ 164 + }; 165 + 158 166 /* for TCP_INFO socket option */ 159 167 #define TCPI_OPT_TIMESTAMPS 1 160 168 #define TCPI_OPT_SACK 2 ··· 219 211 __u8 tcpi_backoff; 220 212 __u8 tcpi_options; 221 213 __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; 222 - __u8 tcpi_delivery_rate_app_limited:1; 214 + __u8 tcpi_delivery_rate_app_limited:1, tcpi_fastopen_client_fail:2; 223 215 224 216 __u32 tcpi_rto; 225 217 __u32 tcpi_ato;
+2
net/ipv4/tcp.c
··· 2666 2666 /* Clean up fastopen related fields */ 2667 2667 tcp_free_fastopen_req(tp); 2668 2668 inet->defer_connect = 0; 2669 + tp->fastopen_client_fail = 0; 2669 2670 2670 2671 WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); 2671 2672 ··· 3306 3305 info->tcpi_reord_seen = tp->reord_seen; 3307 3306 info->tcpi_rcv_ooopack = tp->rcv_ooopack; 3308 3307 info->tcpi_snd_wnd = tp->snd_wnd; 3308 + info->tcpi_fastopen_client_fail = tp->fastopen_client_fail; 3309 3309 unlock_sock_fast(sk, slow); 3310 3310 } 3311 3311 EXPORT_SYMBOL_GPL(tcp_get_info);
+4 -1
net/ipv4/tcp_fastopen.c
··· 422 422 cookie->len = -1; 423 423 return true; 424 424 } 425 - return cookie->len > 0; 425 + if (cookie->len > 0) 426 + return true; 427 + tcp_sk(sk)->fastopen_client_fail = TFO_COOKIE_UNAVAILABLE; 428 + return false; 426 429 } 427 430 428 431 /* This function checks if we want to defer sending SYN until the first
+4
net/ipv4/tcp_input.c
··· 5814 5814 tcp_fastopen_cache_set(sk, mss, cookie, syn_drop, try_exp); 5815 5815 5816 5816 if (data) { /* Retransmit unacked data in SYN */ 5817 + if (tp->total_retrans) 5818 + tp->fastopen_client_fail = TFO_SYN_RETRANSMITTED; 5819 + else 5820 + tp->fastopen_client_fail = TFO_DATA_NOT_ACKED; 5817 5821 skb_rbtree_walk_from(data) { 5818 5822 if (__tcp_retransmit_skb(sk, data, 1)) 5819 5823 break;