Step.1 APP(server)
1.1 Call Graph
sys_listen
│
├──inet_listen
│
├──inet_csk_listen_start
│
├──tcp_v4_hash
│
├──inet_hash
1.2 Details
- inet_csk_listen_start
- 初始化连接队列inet_connection_sock{}->icsk_accept_queue;
- sock{}->sk_state设置为TCP_LISTEN状态;
- inet_hash
- 将sock{}结构添加到listen hash table — inet_hashinfo{}->listening_hash[]中
Step.2 APP(server)
2.1 Call Graph
sys_connect
│
├──inet_stream_connect
│
├──tcp_v4_connect
│ │
│ ├──inet_hash_connect
│ │ │
│ │ ├──__inet_hash
│ │
│ ├──tcp_connect
│ │
│ ├──tcp_transmit_skb
│
├──inet_wait_for_connect
2.2 Details
- inet_csk_wait_for_connect
- 调度处理器,挂起当前进程,等待连接队列inet_connection_sock{}->icsk_accept_queue变为非NULL;
- reqsk_queue_get_child
- 从连接队列inet_connection_sock{}->icsk_accept_queue中获取新连接对应的sock{}结构
Step.3 APP(client)
3.1 Call Graph
sys_connect
│
├──inet_stream_connect
│
├──tcp_v4_connect
│ │
│ ├──inet_hash_connect
│ │ │
│ │ ├──__inet_hash
│ │
│ ├──tcp_connect
│ │
│ ├──tcp_transmit_skb
│
├──inet_wait_for_connect
3.2 Details
- tcp_v4_connect
- sock{}->sk_state设置为TCP_SYN_SENT状态
- __inet_hash
- 将sock{}结构添加到ehash table — inet_hashinfo{}->ehash[]中
- tcp_connect
- 构造SYN报文
- tcp_transmit_skb
- 发送SYN报文
- inet_wait_for_connect
- 调度处理器,挂起当前进程,等待sock{}->sk_state切换为非TCP_SYN_SENT状态
Step.4 Triggered by pkts(server)
4.1 Call Graph
tcp_v4_rcv
│
├──__inet_lookup
│ │
│ ├──__inet_lookup_established
│ │
│ ├──inet_lookup_listener
│
├──tcp_v4_do_rcv
│
├──tcp_v4_hnd_req
│ │
│ ├──inet_csk_search_req
│ │
│ ├──__inet_lookup_established
│
├──tcp_rcv_state_process
│
├──tcp_v4_conn_request
│
├──tcp_v4_send_synack
│
├──inet_csk_reqsk_queue_hash_add
4.2 Details
- tcp_v4_rcv
- 接收到SYN报文
- inet_lookup_listener
- 在listen hash table — inet_hashinfo{}->listening_hash[]中查找skb对应的sock{}结构
查找成功
- 在listen hash table — inet_hashinfo{}->listening_hash[]中查找skb对应的sock{}结构
- inet_csk_search_req
- 在半连接hash table — listen_sock{}->syn_table[]中查找request_sock{}结构
首次查找失败
- 在半连接hash table — listen_sock{}->syn_table[]中查找request_sock{}结构
- tcp_v4_hnd_req
- 返回原始的sock{}结构
- tcp_v4_conn_request
- 申请一个request_sock{}结构
- tcp_v4_send_synack
- 构造发送SYN+ACK报文
- inet_csk_reqsk_queue_hash_add
- 将request_sock{}结构插入到半连接hash table — listen_sock{}->syn_table[]中
sock{}->sk_state仍然处于TCP_LISTEN状态
- 将request_sock{}结构插入到半连接hash table — listen_sock{}->syn_table[]中
Step.5 Triggered by pkts(client)
5.1 Call Graph
tcp_v4_rcv
│
├──__inet_lookup
│ │
│ ├──__inet_lookup_established
│
├──tcp_v4_do_rcv
│
├──tcp_rcv_state_process
│
├──tcp_rcv_synsent_state_process
│ │
│ ├──tcp_ack
│ │
│ ├──tcp_send_ack
│
├──tcp_data_snd_check
5.2 Details
- tcp_v4_rcv
- 接收到SYN+ACK报文
- __inet_lookup_established
- 在ehash table — inet_hashinfo{}->ehash[]中查找到对应的sock{}结构
与Step. 3中调用函数__inet_hash相呼应
- 在ehash table — inet_hashinfo{}->ehash[]中查找到对应的sock{}结构
- tcp_rcv_synsent_state_process
- sock{}->sk_state由TCP_SYN_SENT状态切换为TCP_ESTABLISHED状态
- 执行sock{}->sk_state_change所指的函数,唤醒等待的所有进程
与Step. 3中调用函数inet_wait_for_connect相呼应,唤醒client端应用程序
- tcp_send_ack
- 发送ACK报文
Step.6 Triggered by pkts(server)
6.1 Call Graph
tcp_v4_rcv
│
├──__inet_lookup
│ │
│ ├──__inet_lookup_established
│ │
│ ├──inet_lookup_listener
│
├──tcp_v4_do_rcv
│
├──tcp_v4_hnd_req
│ │
│ ├──inet_csk_search_req
│ │
│ ├──tcp_check_req
│ │
│ ├──tcp_v4_syn_recv_sock
│ │ │
│ │ ├──tcp_create_openreq_child
│ │ │
│ │ ├──__inet_hash
│ │
│ ├──inet_csk_reqsk_queue_unlink
│ │
│ ├──inet_csk_reqsk_queue_add
│
├──tcp_child_process
│
├──tcp_rcv_state_process
│
├──tcp_ack
│
├──tcp_data_queue
│ │
│ ├──tcp_event_data_recv
│ │
│ ├──tcp_ofo_queue
│
├──tcp_data_snd_check
│
├──tcp_ack_snd_check
6.2 Details
- tcp_v4_rcv
- 接收到ACK报文
- inet_lookup_listener
- 在listen hash table — inet_hashinfo{}->listening_hash[]中查找skb对应的sock{}结构
查找成功
- 在listen hash table — inet_hashinfo{}->listening_hash[]中查找skb对应的sock{}结构
- inet_csk_search_req
- 在半连接hash table — listen_sock{}->syn_table[]中查找request_sock{}结构
与Step. 4中调用函数inet_csk_reqsk_queue_hash_add相呼应,第二次查找成功,返回之前新建的request_sock{}结构
- 在半连接hash table — listen_sock{}->syn_table[]中查找request_sock{}结构
- tcp_create_openreq_child
- 创建一个新sock{}结构
- 新sock{}结构的sock{}->sk_state设置为TCP_SYN_RECV状态
- inet_csk_reqsk_queue_unlink
- 将request_sock{}结构从半连接hash table — listen_sock{}->syn_table[]中移除
- inet_csk_reqsk_queue_add
- 将request_sock{}结构挂载到连接队列inet_connection_sock{}->icsk_accept_queue中
与Step. 2中调用函数inet_csk_wait_for_connect相呼应
- 将request_sock{}结构挂载到连接队列inet_connection_sock{}->icsk_accept_queue中
- tcp_check_req
- 最终会返回新创建的sock{}结构
- tcp_rcv_state_process
- 这里会将新创建的sock{}结构的sock{}->sk_state由TCP_SYN_RECV状态切换为TCP_ESTABLISHED状态
- tcp_data_snd_check
- 检查是否有数据可以发送
- tcp_ack_snd_check
- 检查是否需要发送ACK报文
- tcp_child_process
- 最后会唤醒等待原sock{}结构的进程
与Step. 2中调用函数inet_csk_wait_for_connect相呼应
- 最后会唤醒等待原sock{}结构的进程