Abstract

  1. Quick introduce how TCP handshake works, how listen and accept works.
  2. Introduce several ways and tools to read kernel.
  3. Demonstrate how to do it.

Keywords

Copyright & License

Copyright (C) 2019 Shell.Xu shell909090@gmail.com

Text is available under the Creative Commons Attribution-ShareAlike License

摘要

  1. 简单介绍tcp握手原理,理解listen和accept的机制。
  2. 介绍代码阅读的几种手段和工具。
  3. 简单演示如何阅读linux源码。

TCP握手

TCP握手可以简单分为三步[13],但实际上加上前后过程总共有六步。

假定发起方为A,接收方为B。A的连接socket称为Ac。B的listen socket称为Bl,accept出来的socket成为Ba。

  1. B首先建立Bl,调用listen,设定队列大小。 (前置步骤例如建立socket等省略)
  2. A对Ac调用connect,内核发送SYN报文。
  3. B内核收到SYN报文,找到Bl。Bl在内核经过一定处理后决定是否返回SYN&ACK报文。
  4. A收到SYN&ACK报文,找到Ac。Ac在内核经过一定处理后返回ACK报文,并且A连接建立就绪,可以收发数据。
  5. B收到ACK报文,找到或建立Ba。Ba连接建立就绪,进入accept队列。
  6. B对Bl调用accept,获得Ba。

不同系统实现的差别有:

  1. 第3步中,内核如何决定是否返回SYN&ACK报文。其中主要考虑SYN flood[3][4]的防御。
  2. Ba在第3步建立还是第5步建立。
  3. Ba在第3步到第5步的状态(我们称为半握手状态),是否放入accept队列,还是保持一个单独队列[1]。
  4. 如何加速上述流程。

manual

根据文献[10]

The behavior of the backlog argument on TCP sockets changed with Linux 2.2.  Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number  of  incomplete  connection  re‐
quests.   The  maximum  length  of  the  queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog.  When syncookies are enabled there is no logical maximum length and this setting is ignored.  See
tcp(7) for more information.

utils

  1. lxr
  2. github repository
  3. github release

阅读重点

  1. struct sock
  2. struct socket
  3. struct inet_connection_sock
  4. struct inet_sock

sock和socket互相指向。inet_connection_sock包含inet_sock,inet_sock包含sock。

  1. EXPORT_SYMBOL(inet_listen)
  2. EXPORT_SYMBOL(inet_accept)
  3. tcp_v4_rcv
    1. __inet_lookup_skb
      1. __inet_lookup
      2. __inet_lookup_established 开链法(Separate chaining with linked lists)[8][9]
      3. __inet_lookup_listener 注意reuseport[11][12]和INADDR_ANY的处理
    2. tcp_check_req
      1. inet_csk_complete_hashdance
      2. inet_csk_reqsk_queue_add
    3. tcp_v4_do_rcv
      1. tcp_rcv_state_process 重点process
      2. tcp_v4_conn_request
      3. tcp_conn_request
      4. inet_csk_reqsk_queue_hash_add req加hash表,不是sk
      5. reqsk_queue_hash_req
      6. inet_ehash_insert

结论

  1. 当没有synflood[3][4]时,正常返回。synflood时(超过sysctl_max_syn_backlog[2]的3/4),未开启syncookie[4][5]则丢弃。
  2. Ba在第3步建立,而后进入hashinfo结构。第5步通过hashinfo找到Ba,检验ack通过后进入accept_queue。
  3. Ba在半握手状态直接装入hashinfo。后续使用定时器重发SYN&ACK,直到超过tcp_synack_retries[2]规定的极限。
  4. fastopen[6][7]有助于这个过程。

references

  1. How TCP backlog works in Linux [14]
  2. ip-sysctl.txt
  3. SYN flood
  4. SYN Flood Mitigation with synsanity [15]
  5. SYN cookies
  6. TCP Fast Open
  7. TCP-Fast-Open-Experimentation
  8. Hash table
  9. An hashtable implementation in C
  10. listen
  11. socket
  12. The SO_REUSEPORT socket option
  13. Transmission Control Protocol#Connection establishment
  14. github bsd kernel
  15. tproxy