如何知道TCP Fast Open的sendto()实际上是否使用了Fast Open?

时间:2014-10-07 20:19:04

标签: c linux sockets tcp

我在Linux 3.15机器上编写了一个TCP客户端,它可以使用TCP Fast Open:

        status = sendto(sd, (const void *) data, data_len, MSG_FASTOPEN,
                        (const struct sockaddr *) hostref->ai_addr,
                        sizeof(struct sockaddr_in));
        if (status < 0) {
            fprintf(stderr, "sendto: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
        fprintf(stdout, "TFO connection successful to %s\n",
                    text_of(hostref->ai_addr));

使用tcpdump,我可以检查TCP Fast Open选项的发送,并且它确实绕过了3次握手(使用Google服务器测试过)。

但是,对于接受TCP快速打开的服务器,sendto仍然成功,并显示消息“TFO连接成功”。显然,如果服务器不支持TCP Fast Open(再次使用tcpdump检查),Linux内核代码将回退到常规TCP。

如何确定我的连接是否使用TCP Fast Open?

1 个答案:

答案 0 :(得分:6)

通过查看在Linux内核中添加TCP快速打开的补丁集,您会注意到它没有添加任何使用快速打开的外部指示。

您可以间接注意某些未使用快速打开的情况以及某些明确使用快速打开的情况。

如果在成功发送sendto()连接后TCPFastOpenActive计数器的值未在/ proc / net / netstat中递增,则表示您确定未使用快速打开的情况:

+   if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) {
+       NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
+       goto done;
+   }

你肯定使用快速打开的情况是当你有一个非阻塞套接字时,你已经有一个快速打开的cookie并且sendto()没有返回EINPROGRESS:

  

对于非阻塞套接字,它返回排队的字节数(和   如果cookie可用,则在SYN数据包中传输)。如果是cookie   它不可用,它使用Fast Open传输无数据的SYN数据包   cookie请求选项并返回-EINPROGRESS,如connect()。

对于剩下的情况,也就是说,你没有cookie,但是你能够连接并且TCPFastOpenActive会增加,你不能说是否使用了快速打开(TCPFastOpenActive增量是由您的快速打开)或者如果没有使用快速打开(TCPFastOpenActive增量不是由您的快速打开引起的)。

http://kernelnewbies.org/Linux_3.6#head-ac78950a7b57d92d5835642926f0e147c680b99c

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=cf60af03ca4e71134206809ea892e49b92a88896

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/diff/net/ipv4/tcp_output.c?id=783237e8daf13481ee234997cbbbb823872ac388